quidproquo-web-admin 0.0.255 → 0.0.256

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/lib/commonjs/App/App.js +2 -2
  2. package/lib/commonjs/Config/Config.d.ts +2 -0
  3. package/lib/commonjs/Config/Config.js +48 -0
  4. package/lib/commonjs/Config/index.d.ts +1 -0
  5. package/lib/commonjs/{LogViewer → Config}/index.js +1 -1
  6. package/lib/commonjs/FederatedAddon.d.ts +2 -2
  7. package/lib/commonjs/components/MainLayout/MainLayout.d.ts +1 -0
  8. package/lib/commonjs/components/MainLayout/MainLayout.js +36 -0
  9. package/lib/commonjs/components/MainLayout/hooks/index.d.ts +1 -0
  10. package/lib/commonjs/components/MainLayout/hooks/index.js +17 -0
  11. package/lib/commonjs/components/MainLayout/hooks/useTabs.d.ts +5 -0
  12. package/lib/commonjs/components/MainLayout/hooks/useTabs.js +47 -0
  13. package/lib/commonjs/components/MainLayout/index.d.ts +1 -0
  14. package/lib/commonjs/components/MainLayout/index.js +17 -0
  15. package/lib/commonjs/components/index.d.ts +1 -0
  16. package/lib/commonjs/components/index.js +1 -0
  17. package/lib/esm/App/App.js +2 -2
  18. package/lib/esm/Config/Config.d.ts +2 -0
  19. package/lib/esm/Config/Config.js +43 -0
  20. package/lib/esm/Config/index.d.ts +1 -0
  21. package/lib/esm/Config/index.js +1 -0
  22. package/lib/esm/FederatedAddon.d.ts +2 -2
  23. package/lib/esm/components/MainLayout/MainLayout.d.ts +1 -0
  24. package/lib/esm/components/MainLayout/MainLayout.js +30 -0
  25. package/lib/esm/components/MainLayout/hooks/index.d.ts +1 -0
  26. package/lib/esm/components/MainLayout/hooks/index.js +1 -0
  27. package/lib/esm/components/MainLayout/hooks/useTabs.d.ts +5 -0
  28. package/lib/esm/components/MainLayout/hooks/useTabs.js +44 -0
  29. package/lib/esm/components/MainLayout/index.d.ts +1 -0
  30. package/lib/esm/components/MainLayout/index.js +1 -0
  31. package/lib/esm/components/index.d.ts +1 -0
  32. package/lib/esm/components/index.js +1 -0
  33. package/package.json +8 -8
  34. package/lib/commonjs/LogViewer/LogViewer.d.ts +0 -6
  35. package/lib/commonjs/LogViewer/LogViewer.js +0 -60
  36. package/lib/commonjs/LogViewer/index.d.ts +0 -1
  37. package/lib/esm/LogViewer/LogViewer.d.ts +0 -6
  38. package/lib/esm/LogViewer/LogViewer.js +0 -53
  39. package/lib/esm/LogViewer/index.d.ts +0 -1
  40. package/lib/esm/LogViewer/index.js +0 -1
@@ -11,7 +11,7 @@ const react_router_dom_1 = require("react-router-dom");
11
11
  const CssBaseline_1 = __importDefault(require("@mui/material/CssBaseline"));
12
12
  const styles_1 = require("@mui/material/styles");
13
13
  const Auth_1 = require("../Auth/Auth");
14
- const LogViewer_1 = require("../LogViewer");
14
+ const components_1 = require("../components");
15
15
  const contexts_1 = require("../platformLogic/contexts");
16
16
  const view_1 = require("../view");
17
17
  const WebSocketAuthProvider_1 = require("../WebSocketAuthProvider");
@@ -25,6 +25,6 @@ const App = ({ urlResolvers }) => {
25
25
  api: urlResolvers.getApiUrl(),
26
26
  ws: urlResolvers.getWsUrl(),
27
27
  }), [urlResolvers]);
28
- return ((0, jsx_runtime_1.jsx)(quidproquo_web_react_1.QpqContextProvider, { contextIdentifier: contexts_1.baseUrlsContext, value: baseUrls, children: (0, jsx_runtime_1.jsx)(react_router_dom_1.BrowserRouter, { children: (0, jsx_runtime_1.jsx)(quidproquo_web_react_1.BaseUrlProvider, { urlResolvers: urlResolvers, children: (0, jsx_runtime_1.jsxs)(styles_1.ThemeProvider, { theme: darkTheme, children: [(0, jsx_runtime_1.jsx)(CssBaseline_1.default, {}), (0, jsx_runtime_1.jsx)(view_1.LoadingProvider, { children: (0, jsx_runtime_1.jsx)(Auth_1.Auth, { children: (0, jsx_runtime_1.jsx)(quidproquo_web_react_1.WebsocketProvider, { wsUrl: urlResolvers.getWsUrl(), children: (0, jsx_runtime_1.jsx)(WebSocketAuthProvider_1.WebSocketAuthProvider, { children: (0, jsx_runtime_1.jsx)(LogViewer_1.LogViewer, {}) }) }) }) })] }) }) }) }));
28
+ return ((0, jsx_runtime_1.jsx)(quidproquo_web_react_1.QpqContextProvider, { contextIdentifier: contexts_1.baseUrlsContext, value: baseUrls, children: (0, jsx_runtime_1.jsx)(react_router_dom_1.BrowserRouter, { children: (0, jsx_runtime_1.jsx)(quidproquo_web_react_1.BaseUrlProvider, { urlResolvers: urlResolvers, children: (0, jsx_runtime_1.jsxs)(styles_1.ThemeProvider, { theme: darkTheme, children: [(0, jsx_runtime_1.jsx)(CssBaseline_1.default, {}), (0, jsx_runtime_1.jsx)(view_1.LoadingProvider, { children: (0, jsx_runtime_1.jsx)(Auth_1.Auth, { children: (0, jsx_runtime_1.jsx)(quidproquo_web_react_1.WebsocketProvider, { wsUrl: urlResolvers.getWsUrl(), children: (0, jsx_runtime_1.jsx)(WebSocketAuthProvider_1.WebSocketAuthProvider, { children: (0, jsx_runtime_1.jsx)(components_1.MainLayout, {}) }) }) }) })] }) }) }) }));
29
29
  };
30
30
  exports.App = App;
@@ -0,0 +1,2 @@
1
+ export declare function Config(): import("react/jsx-runtime").JSX.Element;
2
+ export default Config;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Config = Config;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const quidproquo_web_react_1 = require("quidproquo-web-react");
6
+ const quidproquo_webserver_1 = require("quidproquo-webserver");
7
+ const react_1 = require("react");
8
+ const material_1 = require("@mui/material");
9
+ const internals_1 = require("@mui/x-data-grid/internals");
10
+ const hooks_1 = require("../LogViewer/hooks");
11
+ const drawerWidth = 240;
12
+ const sections = ['General', 'Settings', 'Advanced'];
13
+ function Config() {
14
+ var _a;
15
+ const [selectedServiceOverride, setSelectedServiceOverride] = (0, react_1.useState)('');
16
+ const [tabIndex, setTabIndex] = (0, react_1.useState)(0);
17
+ const [search, setSearch] = (0, react_1.useState)('');
18
+ const services = (0, hooks_1.useServiceNames)();
19
+ const sendMessage = (0, quidproquo_web_react_1.useWebsocketSendEvent)();
20
+ (0, internals_1.useOnMount)(() => {
21
+ const configSyncRequestEvent = {
22
+ type: quidproquo_webserver_1.WebsocketAdminClientMessageEventType.ConfigSyncRequest,
23
+ payload: {},
24
+ };
25
+ sendMessage(configSyncRequestEvent);
26
+ });
27
+ const handleServiceClick = (service) => {
28
+ setSelectedServiceOverride(service);
29
+ setTabIndex(0);
30
+ };
31
+ const handleTabChange = (event, newIndex) => {
32
+ setTabIndex(newIndex);
33
+ };
34
+ const filteredServices = services.filter((s) => s.label.toLowerCase().includes(search.toLowerCase()));
35
+ const selectedService = selectedServiceOverride || ((_a = services[0]) === null || _a === void 0 ? void 0 : _a.label);
36
+ return ((0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { display: 'flex' }, children: [(0, jsx_runtime_1.jsx)(material_1.CssBaseline, {}), (0, jsx_runtime_1.jsxs)(material_1.Drawer, { variant: "permanent", sx: {
37
+ width: drawerWidth,
38
+ flexShrink: 0,
39
+ [`& .MuiDrawer-paper`]: { width: drawerWidth, boxSizing: 'border-box' },
40
+ }, children: [(0, jsx_runtime_1.jsx)(material_1.Toolbar, { children: (0, jsx_runtime_1.jsx)(material_1.TextField, { fullWidth: true, size: "small", variant: "outlined", placeholder: "Search services", value: search, onChange: (e) => setSearch(e.target.value), onKeyDown: (e) => {
41
+ var _a, _b;
42
+ if (e.key === 'Enter') {
43
+ setSearch((_a = filteredServices[0]) === null || _a === void 0 ? void 0 : _a.label);
44
+ handleServiceClick((_b = filteredServices[0]) === null || _b === void 0 ? void 0 : _b.label);
45
+ }
46
+ }, sx: { mt: 2 } }) }), (0, jsx_runtime_1.jsx)(material_1.Box, { sx: { overflow: 'auto', p: 2 }, children: (0, jsx_runtime_1.jsx)(material_1.List, { children: filteredServices.map((service) => ((0, jsx_runtime_1.jsx)(material_1.ListItem, { disablePadding: true, children: (0, jsx_runtime_1.jsx)(material_1.ListItemButton, { selected: service.label === selectedService, onClick: () => handleServiceClick(service.label), children: (0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: service.label }) }) }, service.value))) }) })] }), (0, jsx_runtime_1.jsxs)(material_1.Box, { component: "main", sx: { flexGrow: 1, p: 3 }, children: [(0, jsx_runtime_1.jsxs)(material_1.Typography, { variant: "h5", gutterBottom: true, children: [selectedService, " Service"] }), (0, jsx_runtime_1.jsx)(material_1.Tabs, { value: tabIndex, onChange: handleTabChange, sx: { borderBottom: 1, borderColor: 'divider' }, children: sections.map((section, index) => ((0, jsx_runtime_1.jsx)(material_1.Tab, { label: section }, index))) }), (0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { mt: 2 }, children: [sections[tabIndex] === 'General' && (0, jsx_runtime_1.jsxs)(material_1.Typography, { children: ["General settings for ", selectedService] }), sections[tabIndex] === 'Settings' && (0, jsx_runtime_1.jsx)(material_1.Typography, { children: "Custom configuration options" }), sections[tabIndex] === 'Advanced' && (0, jsx_runtime_1.jsx)(material_1.Typography, { children: "Advanced tuning and overrides" })] })] })] }));
47
+ }
48
+ exports.default = Config;
@@ -0,0 +1 @@
1
+ export * from './Config';
@@ -14,4 +14,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./LogViewer"), exports);
17
+ __exportStar(require("./Config"), exports);
@@ -1,7 +1,7 @@
1
- import { ComponentType, MemoExoticComponent } from 'react';
2
1
  export type FederatedTab = {
3
2
  name: string;
4
- View: ComponentType | MemoExoticComponent<ComponentType>;
3
+ View: React.ComponentType;
4
+ icon?: React.ReactElement;
5
5
  };
6
6
  export type FederatedAddon = {
7
7
  tab: FederatedTab;
@@ -0,0 +1 @@
1
+ export declare function MainLayout(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MainLayout = MainLayout;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const material_1 = require("@mui/material");
9
+ const Box_1 = __importDefault(require("@mui/material/Box"));
10
+ const queryParams_1 = require("../../queryParams");
11
+ const hooks_1 = require("./hooks");
12
+ function MainLayout() {
13
+ const { tabs, loading } = (0, hooks_1.useTabs)();
14
+ const { tab, handleTabOnChange } = (0, queryParams_1.useUrlFields)();
15
+ return ((0, jsx_runtime_1.jsxs)(Box_1.default, { sx: {
16
+ display: 'flex',
17
+ flexDirection: 'column',
18
+ height: '100vh',
19
+ width: '100%',
20
+ }, children: [(0, jsx_runtime_1.jsx)(Box_1.default, { sx: {
21
+ flexGrow: 1,
22
+ overflow: 'auto',
23
+ pb: '56px', // <— prevent content from being hidden behind bottom nav
24
+ }, children: tabs
25
+ .filter((t, index) => index === tab)
26
+ .map((tab) => ((0, jsx_runtime_1.jsx)(tab.View, {}, tab.name))) }), (0, jsx_runtime_1.jsxs)(material_1.BottomNavigation, { value: tab, onChange: (event, newValue) => handleTabOnChange(event, newValue), showLabels: true, sx: {
27
+ position: 'fixed',
28
+ bottom: 0,
29
+ left: 0,
30
+ right: 0,
31
+ zIndex: (theme) => theme.zIndex.drawer + 1,
32
+ borderTop: 1,
33
+ borderColor: 'divider',
34
+ bgcolor: 'background.paper',
35
+ }, children: [tabs.map((t) => ((0, jsx_runtime_1.jsx)(material_1.BottomNavigationAction, { label: t.name, icon: t.icon }, t.name))), loading && (0, jsx_runtime_1.jsx)(material_1.BottomNavigationAction, { label: "Loading", icon: (0, jsx_runtime_1.jsx)(material_1.CircularProgress, { size: 18 }), disabled: true })] })] }));
36
+ }
@@ -0,0 +1 @@
1
+ export * from './useTabs';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./useTabs"), exports);
@@ -0,0 +1,5 @@
1
+ import { FederatedTab } from '../../../FederatedAddon';
2
+ export declare function useTabs(): {
3
+ tabs: FederatedTab[];
4
+ loading: boolean;
5
+ };
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.useTabs = useTabs;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const BugReport_1 = __importDefault(require("@mui/icons-material/BugReport"));
9
+ const Extension_1 = __importDefault(require("@mui/icons-material/Extension"));
10
+ const Restore_1 = __importDefault(require("@mui/icons-material/Restore"));
11
+ const Settings_1 = __importDefault(require("@mui/icons-material/Settings"));
12
+ const Terminal_1 = __importDefault(require("@mui/icons-material/Terminal"));
13
+ const Config_1 = require("../../../Config");
14
+ const AdminLogs_1 = require("../../../LogViewer/AdminLogs");
15
+ const Dashboard_1 = require("../../../LogViewer/Dashboard");
16
+ const LogSearch_1 = require("../../../LogViewer/LogSearch");
17
+ const useFederatedAddon_1 = require("../../../useFederatedAddon");
18
+ function useTabs() {
19
+ const { addons, loading } = (0, useFederatedAddon_1.useFederatedAddon)();
20
+ const allTabs = [
21
+ {
22
+ name: 'Events',
23
+ View: LogSearch_1.LogSearch,
24
+ icon: (0, jsx_runtime_1.jsx)(Restore_1.default, {}),
25
+ },
26
+ {
27
+ name: 'Logs',
28
+ View: AdminLogs_1.AdminLogs,
29
+ icon: (0, jsx_runtime_1.jsx)(Terminal_1.default, {}),
30
+ },
31
+ {
32
+ name: 'Errors',
33
+ View: Dashboard_1.Dashboard,
34
+ icon: (0, jsx_runtime_1.jsx)(BugReport_1.default, {}),
35
+ },
36
+ {
37
+ name: 'Advanced',
38
+ View: Config_1.Config,
39
+ icon: (0, jsx_runtime_1.jsx)(Settings_1.default, {}),
40
+ },
41
+ ...addons.map((addon) => (Object.assign(Object.assign({}, addon.tab), { icon: (0, jsx_runtime_1.jsx)(Extension_1.default, {}) }))),
42
+ ];
43
+ return {
44
+ tabs: allTabs,
45
+ loading,
46
+ };
47
+ }
@@ -0,0 +1 @@
1
+ export * from './MainLayout';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./MainLayout"), exports);
@@ -10,5 +10,6 @@ export * from './GridItem';
10
10
  export * from './LastSeen';
11
11
  export * from './LoadingBox';
12
12
  export * from './LoadingSpinner';
13
+ export * from './MainLayout';
13
14
  export * from './TabViewBox';
14
15
  export * from './TextInput';
@@ -26,5 +26,6 @@ __exportStar(require("./GridItem"), exports);
26
26
  __exportStar(require("./LastSeen"), exports);
27
27
  __exportStar(require("./LoadingBox"), exports);
28
28
  __exportStar(require("./LoadingSpinner"), exports);
29
+ __exportStar(require("./MainLayout"), exports);
29
30
  __exportStar(require("./TabViewBox"), exports);
30
31
  __exportStar(require("./TextInput"), exports);
@@ -5,7 +5,7 @@ import { BrowserRouter as Router } from 'react-router-dom';
5
5
  import CssBaseline from '@mui/material/CssBaseline';
6
6
  import { createTheme, ThemeProvider } from '@mui/material/styles';
7
7
  import { Auth } from '../Auth/Auth';
8
- import { LogViewer } from '../LogViewer';
8
+ import { MainLayout } from '../components';
9
9
  import { baseUrlsContext } from '../platformLogic/contexts';
10
10
  import { LoadingProvider } from '../view';
11
11
  import { WebSocketAuthProvider } from '../WebSocketAuthProvider';
@@ -19,5 +19,5 @@ export const App = ({ urlResolvers }) => {
19
19
  api: urlResolvers.getApiUrl(),
20
20
  ws: urlResolvers.getWsUrl(),
21
21
  }), [urlResolvers]);
22
- return (_jsx(QpqContextProvider, { contextIdentifier: baseUrlsContext, value: baseUrls, children: _jsx(Router, { children: _jsx(BaseUrlProvider, { urlResolvers: urlResolvers, children: _jsxs(ThemeProvider, { theme: darkTheme, children: [_jsx(CssBaseline, {}), _jsx(LoadingProvider, { children: _jsx(Auth, { children: _jsx(WebsocketProvider, { wsUrl: urlResolvers.getWsUrl(), children: _jsx(WebSocketAuthProvider, { children: _jsx(LogViewer, {}) }) }) }) })] }) }) }) }));
22
+ return (_jsx(QpqContextProvider, { contextIdentifier: baseUrlsContext, value: baseUrls, children: _jsx(Router, { children: _jsx(BaseUrlProvider, { urlResolvers: urlResolvers, children: _jsxs(ThemeProvider, { theme: darkTheme, children: [_jsx(CssBaseline, {}), _jsx(LoadingProvider, { children: _jsx(Auth, { children: _jsx(WebsocketProvider, { wsUrl: urlResolvers.getWsUrl(), children: _jsx(WebSocketAuthProvider, { children: _jsx(MainLayout, {}) }) }) }) })] }) }) }) }));
23
23
  };
@@ -0,0 +1,2 @@
1
+ export declare function Config(): import("react/jsx-runtime").JSX.Element;
2
+ export default Config;
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useWebsocketSendEvent } from 'quidproquo-web-react';
3
+ import { WebsocketAdminClientMessageEventType } from 'quidproquo-webserver';
4
+ import { useState } from 'react';
5
+ import { Box, CssBaseline, Drawer, List, ListItem, ListItemButton, ListItemText, Tab, Tabs, TextField, Toolbar, Typography } from '@mui/material';
6
+ import { useOnMount } from '@mui/x-data-grid/internals';
7
+ import { useServiceNames } from '../LogViewer/hooks';
8
+ const drawerWidth = 240;
9
+ const sections = ['General', 'Settings', 'Advanced'];
10
+ export function Config() {
11
+ const [selectedServiceOverride, setSelectedServiceOverride] = useState('');
12
+ const [tabIndex, setTabIndex] = useState(0);
13
+ const [search, setSearch] = useState('');
14
+ const services = useServiceNames();
15
+ const sendMessage = useWebsocketSendEvent();
16
+ useOnMount(() => {
17
+ const configSyncRequestEvent = {
18
+ type: WebsocketAdminClientMessageEventType.ConfigSyncRequest,
19
+ payload: {},
20
+ };
21
+ sendMessage(configSyncRequestEvent);
22
+ });
23
+ const handleServiceClick = (service) => {
24
+ setSelectedServiceOverride(service);
25
+ setTabIndex(0);
26
+ };
27
+ const handleTabChange = (event, newIndex) => {
28
+ setTabIndex(newIndex);
29
+ };
30
+ const filteredServices = services.filter((s) => s.label.toLowerCase().includes(search.toLowerCase()));
31
+ const selectedService = selectedServiceOverride || services[0]?.label;
32
+ return (_jsxs(Box, { sx: { display: 'flex' }, children: [_jsx(CssBaseline, {}), _jsxs(Drawer, { variant: "permanent", sx: {
33
+ width: drawerWidth,
34
+ flexShrink: 0,
35
+ [`& .MuiDrawer-paper`]: { width: drawerWidth, boxSizing: 'border-box' },
36
+ }, children: [_jsx(Toolbar, { children: _jsx(TextField, { fullWidth: true, size: "small", variant: "outlined", placeholder: "Search services", value: search, onChange: (e) => setSearch(e.target.value), onKeyDown: (e) => {
37
+ if (e.key === 'Enter') {
38
+ setSearch(filteredServices[0]?.label);
39
+ handleServiceClick(filteredServices[0]?.label);
40
+ }
41
+ }, sx: { mt: 2 } }) }), _jsx(Box, { sx: { overflow: 'auto', p: 2 }, children: _jsx(List, { children: filteredServices.map((service) => (_jsx(ListItem, { disablePadding: true, children: _jsx(ListItemButton, { selected: service.label === selectedService, onClick: () => handleServiceClick(service.label), children: _jsx(ListItemText, { primary: service.label }) }) }, service.value))) }) })] }), _jsxs(Box, { component: "main", sx: { flexGrow: 1, p: 3 }, children: [_jsxs(Typography, { variant: "h5", gutterBottom: true, children: [selectedService, " Service"] }), _jsx(Tabs, { value: tabIndex, onChange: handleTabChange, sx: { borderBottom: 1, borderColor: 'divider' }, children: sections.map((section, index) => (_jsx(Tab, { label: section }, index))) }), _jsxs(Box, { sx: { mt: 2 }, children: [sections[tabIndex] === 'General' && _jsxs(Typography, { children: ["General settings for ", selectedService] }), sections[tabIndex] === 'Settings' && _jsx(Typography, { children: "Custom configuration options" }), sections[tabIndex] === 'Advanced' && _jsx(Typography, { children: "Advanced tuning and overrides" })] })] })] }));
42
+ }
43
+ export default Config;
@@ -0,0 +1 @@
1
+ export * from './Config';
@@ -0,0 +1 @@
1
+ export * from './Config';
@@ -1,7 +1,7 @@
1
- import { ComponentType, MemoExoticComponent } from 'react';
2
1
  export type FederatedTab = {
3
2
  name: string;
4
- View: ComponentType | MemoExoticComponent<ComponentType>;
3
+ View: React.ComponentType;
4
+ icon?: React.ReactElement;
5
5
  };
6
6
  export type FederatedAddon = {
7
7
  tab: FederatedTab;
@@ -0,0 +1 @@
1
+ export declare function MainLayout(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { BottomNavigation, BottomNavigationAction, CircularProgress } from '@mui/material';
3
+ import Box from '@mui/material/Box';
4
+ import { useUrlFields } from '../../queryParams';
5
+ import { useTabs } from './hooks';
6
+ export function MainLayout() {
7
+ const { tabs, loading } = useTabs();
8
+ const { tab, handleTabOnChange } = useUrlFields();
9
+ return (_jsxs(Box, { sx: {
10
+ display: 'flex',
11
+ flexDirection: 'column',
12
+ height: '100vh',
13
+ width: '100%',
14
+ }, children: [_jsx(Box, { sx: {
15
+ flexGrow: 1,
16
+ overflow: 'auto',
17
+ pb: '56px', // <— prevent content from being hidden behind bottom nav
18
+ }, children: tabs
19
+ .filter((t, index) => index === tab)
20
+ .map((tab) => (_jsx(tab.View, {}, tab.name))) }), _jsxs(BottomNavigation, { value: tab, onChange: (event, newValue) => handleTabOnChange(event, newValue), showLabels: true, sx: {
21
+ position: 'fixed',
22
+ bottom: 0,
23
+ left: 0,
24
+ right: 0,
25
+ zIndex: (theme) => theme.zIndex.drawer + 1,
26
+ borderTop: 1,
27
+ borderColor: 'divider',
28
+ bgcolor: 'background.paper',
29
+ }, children: [tabs.map((t) => (_jsx(BottomNavigationAction, { label: t.name, icon: t.icon }, t.name))), loading && _jsx(BottomNavigationAction, { label: "Loading", icon: _jsx(CircularProgress, { size: 18 }), disabled: true })] })] }));
30
+ }
@@ -0,0 +1 @@
1
+ export * from './useTabs';
@@ -0,0 +1 @@
1
+ export * from './useTabs';
@@ -0,0 +1,5 @@
1
+ import { FederatedTab } from '../../../FederatedAddon';
2
+ export declare function useTabs(): {
3
+ tabs: FederatedTab[];
4
+ loading: boolean;
5
+ };
@@ -0,0 +1,44 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import BugReportIcon from '@mui/icons-material/BugReport';
3
+ import ExtensionIcon from '@mui/icons-material/Extension';
4
+ import RestoreIcon from '@mui/icons-material/Restore';
5
+ import SettingsIcon from '@mui/icons-material/Settings';
6
+ import TerminalIcon from '@mui/icons-material/Terminal';
7
+ import { Config } from '../../../Config';
8
+ import { AdminLogs } from '../../../LogViewer/AdminLogs';
9
+ import { Dashboard } from '../../../LogViewer/Dashboard';
10
+ import { LogSearch } from '../../../LogViewer/LogSearch';
11
+ import { useFederatedAddon } from '../../../useFederatedAddon';
12
+ export function useTabs() {
13
+ const { addons, loading } = useFederatedAddon();
14
+ const allTabs = [
15
+ {
16
+ name: 'Events',
17
+ View: LogSearch,
18
+ icon: _jsx(RestoreIcon, {}),
19
+ },
20
+ {
21
+ name: 'Logs',
22
+ View: AdminLogs,
23
+ icon: _jsx(TerminalIcon, {}),
24
+ },
25
+ {
26
+ name: 'Errors',
27
+ View: Dashboard,
28
+ icon: _jsx(BugReportIcon, {}),
29
+ },
30
+ {
31
+ name: 'Advanced',
32
+ View: Config,
33
+ icon: _jsx(SettingsIcon, {}),
34
+ },
35
+ ...addons.map((addon) => ({
36
+ ...addon.tab,
37
+ icon: _jsx(ExtensionIcon, {}),
38
+ })),
39
+ ];
40
+ return {
41
+ tabs: allTabs,
42
+ loading,
43
+ };
44
+ }
@@ -0,0 +1 @@
1
+ export * from './MainLayout';
@@ -0,0 +1 @@
1
+ export * from './MainLayout';
@@ -10,5 +10,6 @@ export * from './GridItem';
10
10
  export * from './LastSeen';
11
11
  export * from './LoadingBox';
12
12
  export * from './LoadingSpinner';
13
+ export * from './MainLayout';
13
14
  export * from './TabViewBox';
14
15
  export * from './TextInput';
@@ -10,5 +10,6 @@ export * from './GridItem';
10
10
  export * from './LastSeen';
11
11
  export * from './LoadingBox';
12
12
  export * from './LoadingSpinner';
13
+ export * from './MainLayout';
13
14
  export * from './TabViewBox';
14
15
  export * from './TextInput';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quidproquo-web-admin",
3
- "version": "0.0.255",
3
+ "version": "0.0.256",
4
4
  "description": "",
5
5
  "main": "./lib/commonjs/index.js",
6
6
  "module": "./lib/esm/index.js",
@@ -34,7 +34,7 @@
34
34
  "dependencies": {
35
35
  "@emotion/react": "^11.10.8",
36
36
  "@emotion/styled": "^11.10.8",
37
- "@module-federation/enhanced": "^0.8.9",
37
+ "@module-federation/enhanced": "^0.17.1",
38
38
  "@mui/icons-material": "^5.11.16",
39
39
  "@mui/lab": "^5.0.0-alpha.128",
40
40
  "@mui/material": "^5.12.2",
@@ -45,11 +45,11 @@
45
45
  "date-fns": "^2.30.0",
46
46
  "dayjs": "^1.11.7",
47
47
  "javascript-time-ago": "^2.5.9",
48
- "quidproquo-core": "0.0.255",
49
- "quidproquo-tsconfig": "0.0.255",
50
- "quidproquo-web": "0.0.255",
51
- "quidproquo-web-react": "0.0.255",
52
- "quidproquo-webserver": "0.0.255",
48
+ "quidproquo-core": "0.0.256",
49
+ "quidproquo-tsconfig": "0.0.256",
50
+ "quidproquo-web": "0.0.256",
51
+ "quidproquo-web-react": "0.0.256",
52
+ "quidproquo-webserver": "0.0.256",
53
53
  "react": ">=18.3.1",
54
54
  "react-d3-tree": "^3.6.0",
55
55
  "react-dom": "18.3.1",
@@ -78,7 +78,7 @@
78
78
  "typescript": "^5.8.2",
79
79
  "webpack": "^5.98.0",
80
80
  "webpack-cli": "^5.0.2",
81
- "webpack-dev-server": "^4.13.3"
81
+ "webpack-dev-server": "^5.2.2"
82
82
  },
83
83
  "peerDependencies": {
84
84
  "react": ">=18.3.1"
@@ -1,6 +0,0 @@
1
- import { FederatedTab } from '../FederatedAddon';
2
- export declare function useTabs(): {
3
- tabs: FederatedTab[];
4
- loading: boolean;
5
- };
6
- export declare function LogViewer(): import("react/jsx-runtime").JSX.Element;
@@ -1,60 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.useTabs = useTabs;
7
- exports.LogViewer = LogViewer;
8
- const jsx_runtime_1 = require("react/jsx-runtime");
9
- const material_1 = require("@mui/material");
10
- const Box_1 = __importDefault(require("@mui/material/Box"));
11
- const queryParams_1 = require("../queryParams");
12
- const useFederatedAddon_1 = require("../useFederatedAddon");
13
- const AdminLogs_1 = require("./AdminLogs");
14
- const Dashboard_1 = require("./Dashboard");
15
- const LogSearch_1 = require("./LogSearch");
16
- function useTabs() {
17
- const { addons, loading } = (0, useFederatedAddon_1.useFederatedAddon)();
18
- const allTabs = [
19
- // {
20
- // name: 'TEST',
21
- // View: RandomView,
22
- // },
23
- {
24
- name: 'Events',
25
- View: LogSearch_1.LogSearch,
26
- },
27
- {
28
- name: 'Logs',
29
- View: AdminLogs_1.AdminLogs,
30
- },
31
- {
32
- name: 'Errors',
33
- View: Dashboard_1.Dashboard,
34
- },
35
- ...addons.map((addon) => addon.tab),
36
- ];
37
- return {
38
- tabs: allTabs,
39
- loading,
40
- };
41
- }
42
- function LogViewer() {
43
- const { tabs, loading } = useTabs();
44
- const { tab, handleTabOnChange } = (0, queryParams_1.useUrlFields)();
45
- return ((0, jsx_runtime_1.jsxs)(Box_1.default, { sx: {
46
- display: 'flex',
47
- flexDirection: 'column',
48
- height: '100vh',
49
- width: '100%',
50
- }, children: [(0, jsx_runtime_1.jsx)(Box_1.default, { sx: { flexGrow: 1, overflow: 'auto' }, children: tabs
51
- .filter((t, index) => index === tab)
52
- .map((tab) => ((0, jsx_runtime_1.jsx)(tab.View, {}, tab.name))) }), (0, jsx_runtime_1.jsx)(Box_1.default, { sx: {
53
- borderTop: 1,
54
- borderColor: 'divider',
55
- position: 'sticky',
56
- bottom: 0,
57
- bgcolor: 'background.paper',
58
- zIndex: 1,
59
- }, children: (0, jsx_runtime_1.jsxs)(material_1.Tabs, { value: tab, onChange: handleTabOnChange, centered: true, children: [tabs.map((tab, index) => ((0, jsx_runtime_1.jsx)(material_1.Tab, { label: tab.name }, tab.name))), loading && (0, jsx_runtime_1.jsx)(material_1.Tab, { label: (0, jsx_runtime_1.jsx)(material_1.CircularProgress, { size: 16 }) })] }) })] }));
60
- }
@@ -1 +0,0 @@
1
- export * from './LogViewer';
@@ -1,6 +0,0 @@
1
- import { FederatedTab } from '../FederatedAddon';
2
- export declare function useTabs(): {
3
- tabs: FederatedTab[];
4
- loading: boolean;
5
- };
6
- export declare function LogViewer(): import("react/jsx-runtime").JSX.Element;
@@ -1,53 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { CircularProgress, Tab, Tabs } from '@mui/material';
3
- import Box from '@mui/material/Box';
4
- import { useUrlFields } from '../queryParams';
5
- import { useFederatedAddon } from '../useFederatedAddon';
6
- import { AdminLogs } from './AdminLogs';
7
- import { Dashboard } from './Dashboard';
8
- import { LogSearch } from './LogSearch';
9
- export function useTabs() {
10
- const { addons, loading } = useFederatedAddon();
11
- const allTabs = [
12
- // {
13
- // name: 'TEST',
14
- // View: RandomView,
15
- // },
16
- {
17
- name: 'Events',
18
- View: LogSearch,
19
- },
20
- {
21
- name: 'Logs',
22
- View: AdminLogs,
23
- },
24
- {
25
- name: 'Errors',
26
- View: Dashboard,
27
- },
28
- ...addons.map((addon) => addon.tab),
29
- ];
30
- return {
31
- tabs: allTabs,
32
- loading,
33
- };
34
- }
35
- export function LogViewer() {
36
- const { tabs, loading } = useTabs();
37
- const { tab, handleTabOnChange } = useUrlFields();
38
- return (_jsxs(Box, { sx: {
39
- display: 'flex',
40
- flexDirection: 'column',
41
- height: '100vh',
42
- width: '100%',
43
- }, children: [_jsx(Box, { sx: { flexGrow: 1, overflow: 'auto' }, children: tabs
44
- .filter((t, index) => index === tab)
45
- .map((tab) => (_jsx(tab.View, {}, tab.name))) }), _jsx(Box, { sx: {
46
- borderTop: 1,
47
- borderColor: 'divider',
48
- position: 'sticky',
49
- bottom: 0,
50
- bgcolor: 'background.paper',
51
- zIndex: 1,
52
- }, children: _jsxs(Tabs, { value: tab, onChange: handleTabOnChange, centered: true, children: [tabs.map((tab, index) => (_jsx(Tab, { label: tab.name }, tab.name))), loading && _jsx(Tab, { label: _jsx(CircularProgress, { size: 16 }) })] }) })] }));
53
- }
@@ -1 +0,0 @@
1
- export * from './LogViewer';
@@ -1 +0,0 @@
1
- export * from './LogViewer';