@andersonalmeidax0/appframe
v0.2.0
Published
appFrame
Downloads
29
Readme
Appframe
ReactComponent para aplicações com funcionalidades:
- header (with login name and logout button)
- menu for navigation
- render subcomponents (pages) for each menu item
- appContext singleton instance is passed through routes, to provide application context
- Login Handler & JWT generator (keycloak)
how to use:
- Create index.html
- Create App using AppFrame.
- App can initialize keycloack however its not mandatory
- Pass "routes", appname, appcontext,
- Create pageComponents (and include it)
Step 1:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>App</title>
<title></title>
<style>
body { margin:0px}
main { margin:8px}
header { margin:0px;background-color: #ccc;}
nav { margin:0px;background-color: #eee; }
</style>
</head>
<body id="main">
<script type="module" src="/app.jsx"></script>
</body>
</html>
Step 2a - app.jsx :Example "routes": labels, links and components for navigation
import pages...
var routes = [
{"route":"/index.html#page1","label":"PageNotes", "component":Page1},
{"route":"/index.html#page2","label":"PageNotes2", "component":Page2},
{"route":"/index.html#page3","label":"PageTestComps", "component":PageTestComps},
]
Step 2aa Example appContext
let kc = {tokenParsed:{email:"noLogon@nologon"}, logout(){alert("Fake logout")}}
class AppContext {
constructor(kc){
this.kc=kc;
}
}
Step 2b
<AppFrame routes={routes} appContext={appContext} appname='AppTest1' />
Step 3:Example PageComponent
class Page1 extends React.Component{
constructor(props){
super(props);
this.state ={}
}
render() {
return ( <React.Fragment>...)
}
}
Step 4: Keycloack login&reload handler
Handle automatic redirect do keyclock to handle app browser autentication and JWT token generation
kc global variable: contains kc.token (JWT)
//versions:
//"keycloak-js": "^24.0.4",
//"react": "^18.2.0",
//To logout: kc.logout({ redirectUri: 'http://apphost:port/' }
import Keycloak from 'keycloak-js';
let initOptions = {
url:'kc url',
realm: 'realm',
clientId: 'client',
}
const kcInitParams = {
onLoad: 'login-required',
checkLoginIframe: true,
pkceMethod: 'S256',
};
let kc = new Keycloak(initOptions);
kcInitDefaults(kc, kcInitParams);
Step 5: deps setup
{
"dependencies": {
"@andersonalmeidax0/appframe": "^0.1.1",
"@vitejs/plugin-react": "^4.0.0",
"react": "^18.0.1",
"react-dom": "^18.0.1",
"react-scripts": "4.0.3",
"vite": "^4.3.3"
},
"scripts": {
"dev": "vite --port 8081",
"build": "vite build",
"preview": "vite preview"
}
}
Step 6: vite setup: vite.config.js ==> "npm run dev" to test
import { defineConfig } from 'vite';
import path from 'path'
import react from '@vitejs/plugin-react';
export default defineConfig({
root: 'src',
build: {
outDir: '../_dist'
},
plugins: [react()],
esbuild: {
jsxFactory: 'React.createElement',
jsxFragment: 'React.Fragment',
},
css: {
modules: {
localsConvention: 'camelCaseOnly',
}
}
});
Complete app.jsx
import React from "react";
import ReactDOM from 'react-dom/client';
import {AppFrame} from '@andersonalmeidax0/appframe';
class App extends React.Component {
render() {
return (
<div>
<h1>Hello, world v3!</h1>
</div>
);
};
}
//Not used (simple example)
class Page1 extends React.Component {
render() {
return (
<div><h1>Page1 v2</h1></div>
);
};
}
let kc = {tokenParsed:{email:"[email protected]"}, logout(){alert("Fake logout")}}
class AppContext {
constructor(kc){
this.kc=kc;
}
}
var appContext = new AppContext(kc);
var routes = [
{"route":"/index.html#page1","label":"Page1", "component":Page1},
{"route":"/index.html#page2","label":"Page2", "component":Page1}
];
class App2 extends React.Component {
render() {
return (
<AppFrame routes={routes} appContext={appContext} appname='AppTest1v23' />
);
};
}
const root = ReactDOM.createRoot(document.getElementById('main'));
root.render(<App2 />);