module federation
This commit is contained in:
@ -5,3 +5,4 @@ REACT_APP_VERSION=1.0.0
|
||||
|
||||
# Development settings
|
||||
GENERATE_SOURCEMAP=true
|
||||
SKIP_PREFLIGHT_CHECK=true
|
||||
|
||||
1
kms/kms-frontend/.gitignore
vendored
1
kms/kms-frontend/.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
dist
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
|
||||
50
kms/kms-frontend/craco.config.js
Normal file
50
kms/kms-frontend/craco.config.js
Normal file
@ -0,0 +1,50 @@
|
||||
const { ModuleFederationPlugin } = require("webpack").container;
|
||||
|
||||
module.exports = {
|
||||
devServer: {
|
||||
port: 3001,
|
||||
historyApiFallback: true,
|
||||
},
|
||||
webpack: {
|
||||
plugins: {
|
||||
add: [
|
||||
new ModuleFederationPlugin({
|
||||
name: 'kms',
|
||||
filename: 'remoteEntry.js',
|
||||
exposes: {
|
||||
'./App': './src/federated/KMSApp',
|
||||
'./SearchProvider': './src/federated/SearchProvider',
|
||||
},
|
||||
shared: {
|
||||
react: {
|
||||
singleton: true,
|
||||
requiredVersion: '^19.1.1'
|
||||
},
|
||||
'react-dom': {
|
||||
singleton: true,
|
||||
requiredVersion: '^19.1.1'
|
||||
},
|
||||
'react-router-dom': {
|
||||
singleton: true,
|
||||
requiredVersion: '^7.8.2'
|
||||
},
|
||||
antd: {
|
||||
singleton: true,
|
||||
requiredVersion: '^5.27.1'
|
||||
},
|
||||
axios: {
|
||||
singleton: true
|
||||
}
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
configure: (webpackConfig) => ({
|
||||
...webpackConfig,
|
||||
output: {
|
||||
...webpackConfig.output,
|
||||
publicPath: "auto",
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
14880
kms/kms-frontend/package-lock.json
generated
14880
kms/kms-frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -23,11 +23,16 @@
|
||||
"typescript": "^4.9.5",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@craco/craco": "^7.1.0",
|
||||
"craco-module-federation": "^1.1.0",
|
||||
"webpack": "^5.96.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
"start": "craco start",
|
||||
"build": "craco build",
|
||||
"test": "craco test",
|
||||
"eject": "craco eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
|
||||
24
kms/kms-frontend/src/bootstrap.tsx
Normal file
24
kms/kms-frontend/src/bootstrap.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import { ConfigProvider, theme } from 'antd';
|
||||
import App from './App';
|
||||
import './App.css';
|
||||
|
||||
const root = ReactDOM.createRoot(
|
||||
document.getElementById('root') as HTMLElement
|
||||
);
|
||||
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
algorithm: theme.defaultAlgorithm,
|
||||
}}
|
||||
>
|
||||
<Router>
|
||||
<App />
|
||||
</Router>
|
||||
</ConfigProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
120
kms/kms-frontend/src/federated/KMSApp.tsx
Normal file
120
kms/kms-frontend/src/federated/KMSApp.tsx
Normal file
@ -0,0 +1,120 @@
|
||||
import React from 'react';
|
||||
import { Routes, Route, Navigate, useNavigate } from 'react-router-dom';
|
||||
import { Layout, Menu, theme } from 'antd';
|
||||
import {
|
||||
DashboardOutlined,
|
||||
AppstoreOutlined,
|
||||
KeyOutlined,
|
||||
UserOutlined,
|
||||
AuditOutlined,
|
||||
ExperimentOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
import Dashboard from '../components/Dashboard';
|
||||
import Applications from '../components/Applications';
|
||||
import Tokens from '../components/Tokens';
|
||||
import Users from '../components/Users';
|
||||
import Audit from '../components/Audit';
|
||||
import TokenTester from '../components/TokenTester';
|
||||
import TokenTesterCallback from '../components/TokenTesterCallback';
|
||||
import { AuthProvider, useAuth } from '../contexts/AuthContext';
|
||||
import Login from '../components/Login';
|
||||
|
||||
const { Sider, Content } = Layout;
|
||||
|
||||
const KMSAppContent: React.FC = () => {
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
const { user } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
token: { colorBgContainer, borderRadiusLG },
|
||||
} = theme.useToken();
|
||||
|
||||
if (!user) {
|
||||
return <Login />;
|
||||
}
|
||||
|
||||
const menuItems = [
|
||||
{
|
||||
key: '/kms',
|
||||
icon: <DashboardOutlined />,
|
||||
label: 'Dashboard',
|
||||
},
|
||||
{
|
||||
key: '/kms/applications',
|
||||
icon: <AppstoreOutlined />,
|
||||
label: 'Applications',
|
||||
},
|
||||
{
|
||||
key: '/kms/tokens',
|
||||
icon: <KeyOutlined />,
|
||||
label: 'Tokens',
|
||||
},
|
||||
{
|
||||
key: '/kms/token-tester',
|
||||
icon: <ExperimentOutlined />,
|
||||
label: 'Token Tester',
|
||||
},
|
||||
{
|
||||
key: '/kms/users',
|
||||
icon: <UserOutlined />,
|
||||
label: 'Users',
|
||||
},
|
||||
{
|
||||
key: '/kms/audit',
|
||||
icon: <AuditOutlined />,
|
||||
label: 'Audit Log',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Layout style={{ height: '100%', minHeight: '600px' }}>
|
||||
<Sider trigger={null} collapsible collapsed={collapsed} width={200}>
|
||||
<Menu
|
||||
theme="dark"
|
||||
mode="inline"
|
||||
defaultSelectedKeys={['/kms']}
|
||||
items={menuItems}
|
||||
onClick={({ key }) => {
|
||||
navigate(key);
|
||||
}}
|
||||
style={{ height: '100%', borderRight: 0 }}
|
||||
/>
|
||||
</Sider>
|
||||
<Layout style={{ background: colorBgContainer }}>
|
||||
<Content
|
||||
style={{
|
||||
margin: '16px',
|
||||
padding: 24,
|
||||
minHeight: 280,
|
||||
background: colorBgContainer,
|
||||
borderRadius: borderRadiusLG,
|
||||
overflow: 'auto',
|
||||
}}
|
||||
>
|
||||
<Routes>
|
||||
<Route path="/kms" element={<Dashboard />} />
|
||||
<Route path="/kms/applications" element={<Applications />} />
|
||||
<Route path="/kms/tokens" element={<Tokens />} />
|
||||
<Route path="/kms/token-tester" element={<TokenTester />} />
|
||||
<Route path="/kms/token-tester/callback" element={<TokenTesterCallback />} />
|
||||
<Route path="/kms/users" element={<Users />} />
|
||||
<Route path="/kms/audit" element={<Audit />} />
|
||||
<Route path="*" element={<Navigate to="/kms" replace />} />
|
||||
</Routes>
|
||||
</Content>
|
||||
</Layout>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
const KMSApp: React.FC = () => {
|
||||
return (
|
||||
<AuthProvider>
|
||||
<KMSAppContent />
|
||||
</AuthProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default KMSApp;
|
||||
64
kms/kms-frontend/src/federated/SearchProvider.tsx
Normal file
64
kms/kms-frontend/src/federated/SearchProvider.tsx
Normal file
@ -0,0 +1,64 @@
|
||||
import { apiService, Application, PaginatedResponse } from '../services/apiService';
|
||||
|
||||
interface SearchResult {
|
||||
id: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
appId: string;
|
||||
action?: () => void;
|
||||
}
|
||||
|
||||
export const kmsSearchProvider = async (query: string): Promise<SearchResult[]> => {
|
||||
const results: SearchResult[] = [];
|
||||
|
||||
try {
|
||||
// Search applications
|
||||
const applicationsResponse: PaginatedResponse<Application> = await apiService.getApplications();
|
||||
applicationsResponse.data
|
||||
.filter((app: Application) =>
|
||||
app.app_id.toLowerCase().includes(query.toLowerCase()) ||
|
||||
(app.owner?.name && app.owner.name.toLowerCase().includes(query.toLowerCase()))
|
||||
)
|
||||
.forEach((app: Application) => {
|
||||
results.push({
|
||||
id: `app-${app.app_id}`,
|
||||
title: app.app_id,
|
||||
description: `Application owned by ${app.owner?.name || 'Unknown'}`,
|
||||
appId: 'KMS',
|
||||
action: () => {
|
||||
window.location.hash = '/kms/applications';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Add quick actions
|
||||
const quickActions = [
|
||||
{ key: 'applications', title: 'Applications', path: '/kms/applications' },
|
||||
{ key: 'tokens', title: 'Tokens', path: '/kms/tokens' },
|
||||
{ key: 'users', title: 'Users', path: '/kms/users' },
|
||||
{ key: 'audit', title: 'Audit Log', path: '/kms/audit' },
|
||||
{ key: 'dashboard', title: 'Dashboard', path: '/kms' },
|
||||
];
|
||||
|
||||
quickActions
|
||||
.filter(action => action.title.toLowerCase().includes(query.toLowerCase()))
|
||||
.forEach(action => {
|
||||
results.push({
|
||||
id: `quick-${action.key}`,
|
||||
title: action.title,
|
||||
description: `Navigate to ${action.title}`,
|
||||
appId: 'KMS',
|
||||
action: () => {
|
||||
window.location.hash = action.path;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('KMS search error:', error);
|
||||
}
|
||||
|
||||
return results.slice(0, 10); // Limit results
|
||||
};
|
||||
|
||||
export default kmsSearchProvider;
|
||||
@ -1,19 +1,3 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
import('./bootstrap');
|
||||
|
||||
const root = ReactDOM.createRoot(
|
||||
document.getElementById('root') as HTMLElement
|
||||
);
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
reportWebVitals();
|
||||
export {};
|
||||
|
||||
Reference in New Issue
Block a user