@digitaldefiance/express-suite-starter 2.3.5 → 2.3.6

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 (95) hide show
  1. package/package.json +2 -1
  2. package/scaffolding/api/.env.example.mustache +52 -0
  3. package/scaffolding/api/src/assets/.gitkeep +0 -0
  4. package/scaffolding/api/src/main.ts.mustache +19 -0
  5. package/scaffolding/api/src/views/index.ejs +34 -0
  6. package/scaffolding/api-lib/src/index.ts +9 -0
  7. package/scaffolding/api-lib/src/lib/application.ts +35 -0
  8. package/scaffolding/api-lib/src/lib/constants.ts.mustache +10 -0
  9. package/scaffolding/api-lib/src/lib/documents/index.ts +1 -0
  10. package/scaffolding/api-lib/src/lib/documents/user.ts +17 -0
  11. package/scaffolding/api-lib/src/lib/environment.ts +52 -0
  12. package/scaffolding/api-lib/src/lib/interfaces/constants.ts +9 -0
  13. package/scaffolding/api-lib/src/lib/interfaces/environment-aws.ts +7 -0
  14. package/scaffolding/api-lib/src/lib/interfaces/environment.ts +9 -0
  15. package/scaffolding/api-lib/src/lib/middlewares.ts.mustache +113 -0
  16. package/scaffolding/api-lib/src/lib/models/email-token.ts +12 -0
  17. package/scaffolding/api-lib/src/lib/models/mnemonic.ts +12 -0
  18. package/scaffolding/api-lib/src/lib/models/role.ts +12 -0
  19. package/scaffolding/api-lib/src/lib/models/used-direct-login-token.ts +12 -0
  20. package/scaffolding/api-lib/src/lib/models/user-role.ts +12 -0
  21. package/scaffolding/api-lib/src/lib/models/user.ts +14 -0
  22. package/scaffolding/api-lib/src/lib/routers/api.ts +23 -0
  23. package/scaffolding/api-lib/src/lib/routers/app.ts +31 -0
  24. package/scaffolding/api-lib/src/lib/routers/index.ts +2 -0
  25. package/scaffolding/api-lib/src/lib/schemas/index.ts +2 -0
  26. package/scaffolding/api-lib/src/lib/schemas/schema.ts +53 -0
  27. package/scaffolding/api-lib/src/lib/schemas/user.ts +13 -0
  28. package/scaffolding/api-lib/src/lib/services/email.ts +109 -0
  29. package/scaffolding/api-lib/src/lib/services/index.ts +1 -0
  30. package/scaffolding/api-lib/src/lib/shared-types.ts +172 -0
  31. package/scaffolding/devcontainer-mongodb/.devcontainer/.env.example +3 -0
  32. package/scaffolding/devcontainer-mongodb/.devcontainer/Dockerfile +6 -0
  33. package/scaffolding/devcontainer-mongodb/.devcontainer/devcontainer.json.mustache +31 -0
  34. package/scaffolding/devcontainer-mongodb/.devcontainer/docker-compose.yml +31 -0
  35. package/scaffolding/devcontainer-mongodb/.devcontainer/load-env.sh +20 -0
  36. package/scaffolding/devcontainer-mongodb/.devcontainer/post-create.sh.hbs +54 -0
  37. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/.env.example +14 -0
  38. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/Dockerfile +38 -0
  39. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/Mongo.Dockerfile +24 -0
  40. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/devcontainer.json +69 -0
  41. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/docker-compose.yml +66 -0
  42. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/entrypoint.sh +29 -0
  43. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/load-env.sh +20 -0
  44. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/mongodb_entrypoint.sh +124 -0
  45. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/mongodb_healthcheck.sh +36 -0
  46. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/post-create.sh.hbs +54 -0
  47. package/scaffolding/devcontainer-simple/.devcontainer/.env.example +4 -0
  48. package/scaffolding/devcontainer-simple/.devcontainer/devcontainer.json.mustache +60 -0
  49. package/scaffolding/devcontainer-simple/.devcontainer/post-create.sh.hbs +72 -0
  50. package/scaffolding/inituserdb/.env.example.mustache +9 -0
  51. package/scaffolding/inituserdb/src/main.ts.mustache +178 -0
  52. package/scaffolding/lib/src/index.ts.mustache +6 -0
  53. package/scaffolding/lib/src/lib/constants.ts.mustache +15 -0
  54. package/scaffolding/lib/src/lib/ecies-config.ts +10 -0
  55. package/scaffolding/lib/src/lib/enumerations/{{workspaceName}}-string-key.ts.mustache +5 -0
  56. package/scaffolding/lib/src/lib/i18n-setup.ts.mustache +99 -0
  57. package/scaffolding/lib/src/lib/interfaces/constants.ts +13 -0
  58. package/scaffolding/lib/src/lib/strings-collection.ts.mustache +45 -0
  59. package/scaffolding/react/src/app/app.tsx.mustache +170 -0
  60. package/scaffolding/react/src/app/menus/extraMenu.tsx +20 -0
  61. package/scaffolding/react/src/app/menus/index.ts +5 -0
  62. package/scaffolding/react/src/app/pages/SplashPage.tsx +60 -0
  63. package/scaffolding/react/src/app/theme.tsx.mustache +91 -0
  64. package/scaffolding/react/src/assets/albatross.ico +0 -0
  65. package/scaffolding/react/src/assets/albatross.png +0 -0
  66. package/scaffolding/react/src/assets/albatross.svg +108 -0
  67. package/scaffolding/react/src/assets/fonts/allroundgothic-xlig.otf +0 -0
  68. package/scaffolding/react/src/assets/fonts/allroundgothic-xlig.ttf +0 -0
  69. package/scaffolding/react/src/assets/fonts/allroundgothic-xlig.woff +0 -0
  70. package/scaffolding/react/src/assets/fonts/allroundgothic-xlig.woff2 +0 -0
  71. package/scaffolding/react/src/assets/gen-by-albatross.png +0 -0
  72. package/scaffolding/react/src/assets/gen-by-albatross.svg +124 -0
  73. package/scaffolding/react/src/config/ecies.ts +10 -0
  74. package/scaffolding/react/src/config/runtime-config.ts +25 -0
  75. package/scaffolding/react/src/environments/environment.prod.ts.mustache +16 -0
  76. package/scaffolding/react/src/environments/environment.ts +15 -0
  77. package/scaffolding/react/src/interfaces/environment.ts +5 -0
  78. package/scaffolding/react/src/main.tsx +22 -0
  79. package/scaffolding/react/src/styles.scss +103 -0
  80. package/scaffolding/react/src/test-setup.ts +1 -0
  81. package/scaffolding/react-lib/src/index.ts +6 -0
  82. package/scaffolding/react-lib/src/theme/theme.tsx +67 -0
  83. package/scaffolding/root/.github/dependabot.yml +11 -0
  84. package/scaffolding/root/.github/workflows/ci.yml +44 -0
  85. package/scaffolding/root/.vscode/extensions.json +9 -0
  86. package/scaffolding/root/DEPLOYMENT.md +104 -0
  87. package/scaffolding/root/do-yarn.sh +148 -0
  88. package/scaffolding/root/ensure-git-globals.sh +30 -0
  89. package/scaffolding/root/eslint.config.mjs +70 -0
  90. package/scaffolding/root/list-scripts.sh +12 -0
  91. package/scaffolding/root/npm-install-globals.sh +5 -0
  92. package/scaffolding/root/nuke-node-modules.sh +23 -0
  93. package/scaffolding/root/recover-yarn.sh +37 -0
  94. package/scaffolding/root/reset.sh.mustache +25 -0
  95. package/scaffolding/root/setup-nvm.sh +15 -0
@@ -0,0 +1,99 @@
1
+ import {
2
+ CoreLanguageCode,
3
+ LanguageCodes,
4
+ GlobalActiveContext,
5
+ IActiveContext,
6
+ LanguageContextSpace,
7
+ getCoreLanguageDefinitions,
8
+ I18nBuilder,
9
+ I18nEngine,
10
+ } from '@digitaldefiance/i18n-lib';
11
+ import { AppConstants } from './constants';
12
+ import { {{WorkspaceName}}StringKey } from './enumerations/{{workspaceName}}-string-key';
13
+ import { Strings } from './strings-collection';
14
+ import { createSuiteCoreComponentConfig } from '@digitaldefiance/suite-core-lib';
15
+
16
+ export const ComponentId = '{{WorkspaceName}}';
17
+
18
+ const componentStrings = {
19
+ [LanguageCodes.EN_US]: Strings[LanguageCodes.EN_US],
20
+ [LanguageCodes.EN_GB]: Strings[LanguageCodes.EN_GB],
21
+ [LanguageCodes.FR]: Strings[LanguageCodes.FR],
22
+ [LanguageCodes.ES]: Strings[LanguageCodes.ES],
23
+ [LanguageCodes.DE]: Strings[LanguageCodes.DE],
24
+ [LanguageCodes.ZH_CN]: Strings[LanguageCodes.ZH_CN],
25
+ [LanguageCodes.JA]: Strings[LanguageCodes.JA],
26
+ [LanguageCodes.UK]: Strings[LanguageCodes.UK],
27
+ };
28
+
29
+ let i18nEngine: I18nEngine;
30
+ if (I18nEngine.hasInstance('default')) {
31
+ i18nEngine = I18nEngine.getInstance('default');
32
+ i18nEngine.mergeConstants(AppConstants);
33
+ } else {
34
+ i18nEngine = I18nBuilder.create()
35
+ .withLanguages(getCoreLanguageDefinitions())
36
+ .withDefaultLanguage(LanguageCodes.EN_US)
37
+ .withFallbackLanguage(LanguageCodes.EN_US)
38
+ .withValidation({
39
+ requireCompleteStrings: false,
40
+ allowPartialRegistration: true,
41
+ })
42
+ .withConstants(AppConstants)
43
+ .withInstanceKey('default')
44
+ .build();
45
+
46
+ i18nEngine.register(createSuiteCoreComponentConfig());
47
+ }
48
+
49
+ export { i18nEngine };
50
+
51
+ const registrationResult = i18nEngine.registerIfNotExists({
52
+ id: ComponentId,
53
+ strings: componentStrings,
54
+ aliases: ['{{WorkspaceName}}StringKey'],
55
+ });
56
+
57
+ if (!registrationResult.isValid) {
58
+ console.warn('Component has missing translations:', registrationResult.errors);
59
+ }
60
+
61
+ const globalContext = GlobalActiveContext.getInstance<CoreLanguageCode, IActiveContext<CoreLanguageCode>>();
62
+ globalContext.createContext(LanguageCodes.EN_US, LanguageCodes.EN_US, ComponentId);
63
+
64
+ export const i18nContext: IActiveContext<CoreLanguageCode> = {
65
+ get language() {
66
+ return globalContext.getContext(ComponentId).language;
67
+ },
68
+ get adminLanguage() {
69
+ return globalContext.getContext(ComponentId).adminLanguage;
70
+ },
71
+ get currentContext() {
72
+ return globalContext.getContext(ComponentId).currentContext;
73
+ },
74
+ get currencyCode() {
75
+ return globalContext.getContext(ComponentId).currencyCode;
76
+ },
77
+ get timezone() {
78
+ return globalContext.getContext(ComponentId).timezone;
79
+ },
80
+ get adminTimezone() {
81
+ return globalContext.getContext(ComponentId).adminTimezone;
82
+ },
83
+ };
84
+
85
+ export const translate = (
86
+ name: {{WorkspaceName}}StringKey,
87
+ variables?: Record<string, string | number>,
88
+ language?: CoreLanguageCode,
89
+ context?: LanguageContextSpace,
90
+ ): string => {
91
+ const activeContext = context ?? globalContext.getContext(ComponentId).currentContext;
92
+ const lang =
93
+ language ??
94
+ (activeContext === 'admin'
95
+ ? globalContext.getContext(ComponentId).adminLanguage
96
+ : globalContext.getContext(ComponentId).language);
97
+
98
+ return i18nEngine.translate(ComponentId, name, variables, lang);
99
+ };
@@ -0,0 +1,13 @@
1
+ import { IConstants as ISuiteCoreConstants } from '@digitaldefiance/suite-core-lib';
2
+
3
+ export interface IConstants extends ISuiteCoreConstants {
4
+ readonly Site: string;
5
+ readonly SiteTagline: string;
6
+ readonly SiteDescription: string;
7
+ readonly SiteHostname: string;
8
+ readonly PasswordRegex: RegExp;
9
+ readonly UsernameMinLength: number;
10
+ readonly UsernameMaxLength: number;
11
+ readonly UsernameRegex: RegExp;
12
+ readonly PasswordMinLength: number;
13
+ }
@@ -0,0 +1,45 @@
1
+ import { LanguageCodes } from '@digitaldefiance/i18n-lib';
2
+ import { {{WorkspaceName}}StringKey } from './enumerations/{{workspaceName}}-string-key';
3
+
4
+ export const Strings = {
5
+ [LanguageCodes.EN_US]: {
6
+ [{{WorkspaceName}}StringKey.SiteTitle]: '{{#isEnUs}}{{siteTitle}}{{/isEnUs}}{{^isEnUs}}Your Site Title{{/isEnUs}}',
7
+ [{{WorkspaceName}}StringKey.SiteDescription]: '{{#isEnUs}}{{siteDescription}}{{/isEnUs}}{{^isEnUs}}Your description here{{/isEnUs}}',
8
+ [{{WorkspaceName}}StringKey.SiteTagline]: '{{#isEnUs}}{{siteTagline}}{{/isEnUs}}{{^isEnUs}}Your tagline here{{/isEnUs}}',
9
+ },
10
+ [LanguageCodes.EN_GB]: {
11
+ [{{WorkspaceName}}StringKey.SiteTitle]: '{{#isEnGb}}{{siteTitle}}{{/isEnGb}}{{^isEnGb}}Your Site Title{{/isEnGb}}',
12
+ [{{WorkspaceName}}StringKey.SiteDescription]: '{{#isEnGb}}{{siteDescription}}{{/isEnGb}}{{^isEnGb}}Your description here{{/isEnGb}}',
13
+ [{{WorkspaceName}}StringKey.SiteTagline]: '{{#isEnGb}}{{siteTagline}}{{/isEnGb}}{{^isEnGb}}Your tagline here{{/isEnGb}}',
14
+ },
15
+ [LanguageCodes.FR]: {
16
+ [{{WorkspaceName}}StringKey.SiteTitle]: '{{#isFr}}{{siteTitle}}{{/isFr}}{{^isFr}}Titre de votre site{{/isFr}}',
17
+ [{{WorkspaceName}}StringKey.SiteDescription]: '{{#isFr}}{{siteDescription}}{{/isFr}}{{^isFr}}Votre description ici{{/isFr}}',
18
+ [{{WorkspaceName}}StringKey.SiteTagline]: '{{#isFr}}{{siteTagline}}{{/isFr}}{{^isFr}}Votre slogan ici{{/isFr}}',
19
+ },
20
+ [LanguageCodes.ES]: {
21
+ [{{WorkspaceName}}StringKey.SiteTitle]: '{{#isEs}}{{siteTitle}}{{/isEs}}{{^isEs}}Título de su sitio{{/isEs}}',
22
+ [{{WorkspaceName}}StringKey.SiteDescription]: '{{#isEs}}{{siteDescription}}{{/isEs}}{{^isEs}}Su descripción aquí{{/isEs}}',
23
+ [{{WorkspaceName}}StringKey.SiteTagline]: '{{#isEs}}{{siteTagline}}{{/isEs}}{{^isEs}}Su eslogan aquí{{/isEs}}',
24
+ },
25
+ [LanguageCodes.DE]: {
26
+ [{{WorkspaceName}}StringKey.SiteTitle]: '{{#isDe}}{{siteTitle}}{{/isDe}}{{^isDe}}Ihr Seitentitel{{/isDe}}',
27
+ [{{WorkspaceName}}StringKey.SiteDescription]: '{{#isDe}}{{siteDescription}}{{/isDe}}{{^isDe}}Ihre Beschreibung hier{{/isDe}}',
28
+ [{{WorkspaceName}}StringKey.SiteTagline]: '{{#isDe}}{{siteTagline}}{{/isDe}}{{^isDe}}Ihr Slogan hier{{/isDe}}',
29
+ },
30
+ [LanguageCodes.ZH_CN]: {
31
+ [{{WorkspaceName}}StringKey.SiteTitle]: '{{#isZhCn}}{{siteTitle}}{{/isZhCn}}{{^isZhCn}}您的网站标题{{/isZhCn}}',
32
+ [{{WorkspaceName}}StringKey.SiteDescription]: '{{#isZhCn}}{{siteDescription}}{{/isZhCn}}{{^isZhCn}}您的描述在这里{{/isZhCn}}',
33
+ [{{WorkspaceName}}StringKey.SiteTagline]: '{{#isZhCn}}{{siteTagline}}{{/isZhCn}}{{^isZhCn}}您的标语在这里{{/isZhCn}}',
34
+ },
35
+ [LanguageCodes.JA]: {
36
+ [{{WorkspaceName}}StringKey.SiteTitle]: '{{#isJa}}{{siteTitle}}{{/isJa}}{{^isJa}}サイトのタイトル{{/isJa}}',
37
+ [{{WorkspaceName}}StringKey.SiteDescription]: '{{#isJa}}{{siteDescription}}{{/isJa}}{{^isJa}}ここに説明を入力{{/isJa}}',
38
+ [{{WorkspaceName}}StringKey.SiteTagline]: '{{#isJa}}{{siteTagline}}{{/isJa}}{{^isJa}}ここにキャッチフレーズを入力{{/isJa}}',
39
+ },
40
+ [LanguageCodes.UK]: {
41
+ [{{WorkspaceName}}StringKey.SiteTitle]: '{{#isUk}}{{siteTitle}}{{/isUk}}{{^isUk}}Назва вашого сайту{{/isUk}}',
42
+ [{{WorkspaceName}}StringKey.SiteDescription]: '{{#isUk}}{{siteDescription}}{{/isUk}}{{^isUk}}Ваш опис тут{{/isUk}}',
43
+ [{{WorkspaceName}}StringKey.SiteTagline]: '{{#isUk}}{{siteTagline}}{{/isUk}}{{^isUk}}Ваш слоган тут{{/isUk}}',
44
+ },
45
+ };
@@ -0,0 +1,170 @@
1
+ import { Box, CssBaseline } from '@mui/material';
2
+ import { LocalizationProvider } from '@mui/x-date-pickers';
3
+ import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
4
+ import { FC, useCallback } from 'react';
5
+ import { Route, Routes, useNavigate } from 'react-router-dom';
6
+ import '../styles.scss';
7
+ import SplashPage from './pages/SplashPage';
8
+ import { createAppTheme } from './theme.tsx';
9
+ import { AppThemeProvider, DashboardPage, MenuProvider, I18nProvider as TranslationProvider, AuthProvider, SuiteConfigProvider, ApiAccess, ChangePasswordFormWrapper, VerifyEmailPageWrapper, RegisterFormWrapper, UserSettingsFormWrapper, LogoutPageWrapper, LoginFormWrapper, PrivateRoute, UnAuthRoute, TopMenu, TranslatedTitle, BackupCodeLoginWrapper, BackupCodesWrapper } from '@digitaldefiance/express-suite-react-components';
10
+ import { environment } from '../environments/environment';
11
+ import { {{WorkspaceName}}StringKey, ComponentId, i18nEngine } from '{{namespace}}/lib';
12
+ import AlbatrossLogo from '../assets/albatross.svg';
13
+ import { AppConstants, EciesConfig } from '{{namespace}}/lib';
14
+ import { appMenuConfigs } from './menus';
15
+ import { LanguageRegistry } from '@digitaldefiance/i18n-lib';
16
+ import { SuiteCoreComponentId, SuiteCoreStringKey } from '@digitaldefiance/suite-core-lib';
17
+
18
+ const getApiBaseUrl = () => {
19
+ if (
20
+ typeof window !== 'undefined' &&
21
+ (window as any).APP_CONFIG &&
22
+ (window as any).APP_CONFIG.apiUrl
23
+ ) {
24
+ return (window as any).APP_CONFIG.apiUrl;
25
+ }
26
+ return environment.apiUrl;
27
+ };
28
+
29
+ const API_BASE_URL = getApiBaseUrl();
30
+
31
+ const AuthProviderWithNavigation: FC<{ children: React.ReactNode }> = ({
32
+ children,
33
+ }) => {
34
+ const navigate = useNavigate();
35
+
36
+ const handleLogout = useCallback(() => {
37
+ navigate('/');
38
+ }, [navigate]);
39
+
40
+ return (
41
+ <SuiteConfigProvider
42
+ baseUrl={API_BASE_URL}
43
+ routes={ {
44
+ dashboard: '/dashboard',
45
+ login: '/login',
46
+ register: '/register',
47
+ verifyEmail: '/verify-email',
48
+ settings: '/user-settings',
49
+ } }
50
+ languages={LanguageRegistry.getCodeLabelMap()}
51
+ >
52
+ <AuthProvider
53
+ baseUrl={API_BASE_URL}
54
+ constants={AppConstants}
55
+ eciesConfig={EciesConfig}
56
+ onLogout={handleLogout}
57
+ >
58
+ {children}
59
+ </AuthProvider>
60
+ </SuiteConfigProvider>
61
+ );
62
+ };
63
+
64
+ const App: FC = () => {
65
+ return (
66
+ <LocalizationProvider dateAdapter={AdapterDateFns}>
67
+ <TranslationProvider i18nEngine={i18nEngine}>
68
+ <TranslatedTitle<SuiteCoreStringKey>
69
+ componentId={SuiteCoreComponentId}
70
+ stringKey={SuiteCoreStringKey.Common_SiteTemplate} />
71
+ <AppThemeProvider customTheme={createAppTheme}>
72
+ <CssBaseline />
73
+ <AuthProviderWithNavigation>
74
+ <InnerApp />
75
+ </AuthProviderWithNavigation>
76
+ </AppThemeProvider>
77
+ </TranslationProvider>
78
+ </LocalizationProvider>
79
+ );
80
+ };
81
+
82
+ const LogoComponent = () => <img src={AlbatrossLogo} alt="Logo" />;
83
+
84
+ const InnerApp: FC = () => {
85
+ return (
86
+ <MenuProvider menuConfigs={appMenuConfigs}>
87
+ <Box className="app-container" sx={ { paddingTop: '64px' } }>
88
+ <TopMenu Logo={<LogoComponent />} />
89
+ <Routes>
90
+ <Route path="/" element={<SplashPage />} />
91
+ <Route
92
+ path="/api-access"
93
+ element={
94
+ <PrivateRoute>
95
+ <ApiAccess />
96
+ </PrivateRoute>
97
+ }
98
+ />
99
+ <Route path="/backup-code" element={<BackupCodeLoginWrapper />} />
100
+ <Route
101
+ path="/backup-codes"
102
+ element={
103
+ <PrivateRoute>
104
+ <BackupCodesWrapper />
105
+ </PrivateRoute>
106
+ }
107
+ />
108
+ <Route
109
+ path="/login"
110
+ element={
111
+ <UnAuthRoute>
112
+ <LoginFormWrapper />
113
+ </UnAuthRoute>
114
+ }
115
+ />
116
+ <Route
117
+ path="/logout"
118
+ element={
119
+ <PrivateRoute>
120
+ <LogoutPageWrapper />
121
+ </PrivateRoute>
122
+ }
123
+ />
124
+ <Route
125
+ path="/register"
126
+ element={
127
+ <UnAuthRoute>
128
+ <RegisterFormWrapper />
129
+ </UnAuthRoute>
130
+ }
131
+ />
132
+ <Route
133
+ path="/dashboard"
134
+ element={
135
+ <PrivateRoute>
136
+ <DashboardPage />
137
+ </PrivateRoute>
138
+ }
139
+ />
140
+ <Route
141
+ path="/change-password"
142
+ element={
143
+ <PrivateRoute>
144
+ <ChangePasswordFormWrapper />
145
+ </PrivateRoute>
146
+ }
147
+ />
148
+ <Route
149
+ path="/verify-email"
150
+ element={
151
+ <UnAuthRoute>
152
+ <VerifyEmailPageWrapper />
153
+ </UnAuthRoute>
154
+ }
155
+ />
156
+ <Route
157
+ path="/user-settings"
158
+ element={
159
+ <PrivateRoute>
160
+ <UserSettingsFormWrapper />
161
+ </PrivateRoute>
162
+ }
163
+ />
164
+ </Routes>
165
+ </Box>
166
+ </MenuProvider>
167
+ );
168
+ };
169
+
170
+ export default App;
@@ -0,0 +1,20 @@
1
+ import { createMenuType, IMenuConfig } from '@digitaldefiance/express-suite-react-components';
2
+ import { Dashboard } from '@mui/icons-material';
3
+
4
+ const ExtraMenu = createMenuType('ExtraMenu');
5
+
6
+ export const extraMenuConfig: IMenuConfig = {
7
+ menuType: ExtraMenu,
8
+ menuIcon: <Dashboard />,
9
+ priority: 1,
10
+ options: [
11
+ {
12
+ id: 'extra-option-1',
13
+ label: 'Extra Option 1',
14
+ link: '/extra-1',
15
+ requiresAuth: true,
16
+ includeOnMenus: [ExtraMenu],
17
+ index: 0,
18
+ },
19
+ ],
20
+ };
@@ -0,0 +1,5 @@
1
+ import { extraMenuConfig } from './extraMenu';
2
+
3
+ export { extraMenuConfig } from './extraMenu';
4
+
5
+ export const appMenuConfigs = [extraMenuConfig];
@@ -0,0 +1,60 @@
1
+ import { Box, Button, Container, Typography } from '@mui/material';
2
+ import { useNavigate } from 'react-router-dom';
3
+ import { useAuth } from '@digitaldefiance/express-suite-react-components';
4
+
5
+ const SplashPage = () => {
6
+ const navigate = useNavigate();
7
+ const { isAuthenticated } = useAuth();
8
+
9
+ return (
10
+ <Container maxWidth="md">
11
+ <Box
12
+ sx={{
13
+ display: 'flex',
14
+ flexDirection: 'column',
15
+ alignItems: 'center',
16
+ justifyContent: 'center',
17
+ minHeight: '80vh',
18
+ textAlign: 'center',
19
+ }}
20
+ >
21
+ <Typography variant="h2" component="h1" gutterBottom>
22
+ Welcome to @WORKSPACENAME@
23
+ </Typography>
24
+ <Typography variant="h5" color="text.secondary" paragraph>
25
+ A modern MERN stack application built with Express Suite
26
+ </Typography>
27
+ <Box sx={{ mt: 4, display: 'flex', gap: 2 }}>
28
+ {isAuthenticated ? (
29
+ <Button
30
+ variant="contained"
31
+ size="large"
32
+ onClick={() => navigate('/dashboard')}
33
+ >
34
+ Go to Dashboard
35
+ </Button>
36
+ ) : (
37
+ <>
38
+ <Button
39
+ variant="contained"
40
+ size="large"
41
+ onClick={() => navigate('/login')}
42
+ >
43
+ Login
44
+ </Button>
45
+ <Button
46
+ variant="outlined"
47
+ size="large"
48
+ onClick={() => navigate('/register')}
49
+ >
50
+ Register
51
+ </Button>
52
+ </>
53
+ )}
54
+ </Box>
55
+ </Box>
56
+ </Container>
57
+ );
58
+ };
59
+
60
+ export default SplashPage;
@@ -0,0 +1,91 @@
1
+ // src/app/theme.tsx
2
+
3
+ import { AppConstants } from '{{namespace}}/lib';
4
+ import { createTheme, PaletteMode } from '@mui/material/styles';
5
+
6
+ export const createAppTheme = (mode: PaletteMode) => createTheme({
7
+ palette: {
8
+ mode,
9
+ primary: {
10
+ main: AppConstants.logo_primary_color,
11
+ light: AppConstants.primary_text_light,
12
+ dark: AppConstants.primary_text_dark,
13
+ contrastText: '#ffffff',
14
+ },
15
+ secondary: {
16
+ main: AppConstants.logo_secondary_text,
17
+ light: AppConstants.secondary_text_light,
18
+ dark: AppConstants.secondary_text_dark,
19
+ contrastText: '#000000',
20
+ },
21
+ background: mode === 'light' ? {
22
+ default: '#f8f9fa',
23
+ paper: '#ffffff',
24
+ } : {
25
+ default: '#121212',
26
+ paper: '#1e1e1e',
27
+ },
28
+ text: {
29
+ primary: AppConstants.logo_primary_text,
30
+ },
31
+ error: {
32
+ main: AppConstants.failure_color,
33
+ },
34
+ warning: {
35
+ main: AppConstants.warning_color,
36
+ },
37
+ success: {
38
+ main: AppConstants.success_color,
39
+ },
40
+ },
41
+ typography: {
42
+ fontFamily: "'Roboto', sans-serif",
43
+ h1: {
44
+ fontFamily: "'ConneqtRegular', sans-serif",
45
+ fontWeight: 400,
46
+ },
47
+ h2: {
48
+ fontFamily: "'ConneqtRegular', sans-serif",
49
+ fontWeight: 400,
50
+ },
51
+ h3: {
52
+ fontFamily: "'ConneqtRegular', sans-serif",
53
+ fontWeight: 400,
54
+ },
55
+ h4: {
56
+ fontFamily: "'ConneqtRegular', sans-serif",
57
+ fontWeight: 400,
58
+ },
59
+ h5: {
60
+ fontFamily: "'ConneqtRegular', sans-serif",
61
+ fontWeight: 400,
62
+ },
63
+ h6: {
64
+ fontFamily: "'ConneqtRegular', sans-serif",
65
+ fontWeight: 400,
66
+ },
67
+ subtitle1: {
68
+ fontFamily: "'ConneqtRegular', sans-serif",
69
+ fontWeight: 400,
70
+ textTransform: 'uppercase',
71
+ },
72
+ body1: {
73
+ fontFamily: "'Roboto', sans-serif",
74
+ fontWeight: 400,
75
+ },
76
+ },
77
+ components: {
78
+ MuiButton: {
79
+ styleOverrides: {
80
+ root: {
81
+ borderRadius: '4px',
82
+ textTransform: 'none',
83
+ },
84
+ },
85
+ },
86
+ },
87
+ });
88
+
89
+ // Export a light theme as default for backward compatibility
90
+ const theme = createAppTheme('light');
91
+ export default theme;
@@ -0,0 +1,108 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800">
3
+ <defs>
4
+ <style>
5
+ .cls-1 {
6
+ fill: #433834;
7
+ }
8
+
9
+ .cls-2, .cls-3, .cls-4, .cls-5, .cls-6 {
10
+ mix-blend-mode: multiply;
11
+ }
12
+
13
+ .cls-2, .cls-5 {
14
+ opacity: .2;
15
+ }
16
+
17
+ .cls-2, .cls-7 {
18
+ fill: #bebfaf;
19
+ }
20
+
21
+ .cls-3, .cls-4, .cls-6 {
22
+ opacity: .3;
23
+ }
24
+
25
+ .cls-8 {
26
+ fill: #9ca6b2;
27
+ }
28
+
29
+ .cls-9 {
30
+ fill: #d5561e;
31
+ }
32
+
33
+ .cls-10 {
34
+ isolation: isolate;
35
+ }
36
+
37
+ .cls-4 {
38
+ fill: #60260f;
39
+ }
40
+
41
+ .cls-11 {
42
+ fill: #fcfcf5;
43
+ }
44
+
45
+ .cls-12 {
46
+ fill: #352b28;
47
+ }
48
+
49
+ .cls-5 {
50
+ fill: #a7a9ac;
51
+ }
52
+
53
+ .cls-6 {
54
+ fill: #4d5156;
55
+ }
56
+ </style>
57
+ </defs>
58
+ <g class="cls-10">
59
+ <g id="Layer_2" data-name="Layer 2">
60
+ <ellipse class="cls-5" cx="422.34" cy="641.36" rx="190.28" ry="38.87"/>
61
+ <g>
62
+ <g>
63
+ <path class="cls-8" d="M474.23,603.27c0-1.54.09-3.07.26-4.59.23-2.03-1.57-3.84-4.11-4.16-5.67-.7-11.71-1.08-17.99-1.08-32.28,0-58.45,10.03-58.45,22.4s26.17,22.4,58.45,22.4c10.62,0,20.57-1.09,29.14-2.98,2.51-.56,3.71-2.83,2.39-4.61-9.33-12.64,11.48-11.25,9.57-17.3-1.28-4.05-19.27-5.77-19.27-10.09Z"/>
64
+ <g class="cls-3">
65
+ <path class="cls-7" d="M489.51,617.85c-36.17.26-64.58,2.85-64.58,6,0,2.98,25.23,5.45,58.41,5.94-5.01-7.56,1.45-9.75,6.17-11.94Z"/>
66
+ </g>
67
+ <g class="cls-3">
68
+ <path class="cls-7" d="M424.93,603.63c0,4.4,29.8,7.99,67.21,8.2-4.47-3.03-17.9-4.82-17.9-8.56,0-1.54.09-3.07.26-4.59.12-1.07-.33-2.08-1.15-2.84-28.12,1.08-48.41,4.16-48.41,7.79Z"/>
69
+ </g>
70
+ <path class="cls-8" d="M404.26,617.51h0c-4.67,1.15-9.63-.91-11.09-4.6l-31.76-80.65,16.91-4.16,31.76,80.65c1.45,3.69-1.15,7.62-5.82,8.76Z"/>
71
+ <g class="cls-3">
72
+ <path class="cls-7" d="M403.4,612.9l-31.76-80.65,7.58-1.87-.9-2.3-16.91,4.16,31.76,80.65c1.45,3.69,6.42,5.75,11.09,4.6.92-.23,1.75-.56,2.49-.98-1.53-.86-2.74-2.1-3.34-3.63Z"/>
73
+ </g>
74
+ <path class="cls-8" d="M364.15,554.59c3.13,8.54,10.63,10.08,18.12,8.36,7.49-1.72,12.14-6.03,9.01-14.57-3.13-8.54-12.85-18.07-20.35-16.35s-9.92,14.03-6.79,22.57Z"/>
75
+ <path class="cls-11" d="M440.5,490.46c0,24.38-11.57,9.98-42.4,49.12-6.99,8.88-40.02,8.39-50.99-1.47-11.39-10.24-.6-30.26-.6-42.67,0-24.38,21.04-44.14,47-44.14s47,14.79,47,39.17Z"/>
76
+ </g>
77
+ <path class="cls-6" d="M482.25,627.86s-.03-.06-.04-.09c-.27-.59-.45-1.14-.56-1.66,0-.03-.01-.06-.02-.08-.1-.52-.13-1-.1-1.45,0-.02,0-.03,0-.05.07-.75.31-1.41.68-2,.01-.02.02-.04.04-.06.22-.34.49-.66.79-.96.03-.03.05-.05.08-.08.19-.18.39-.36.61-.52.02-.01.03-.03.05-.04.11-.09.22-.17.34-.25.04-.03.09-.06.14-.09.19-.13.39-.26.59-.38.06-.04.12-.08.19-.11.11-.07.23-.13.34-.2.1-.05.19-.11.29-.16.16-.09.32-.17.48-.26.1-.05.2-.1.29-.15.1-.05.2-.1.3-.15.18-.09.36-.17.53-.25.09-.04.18-.08.27-.13.16-.08.33-.15.49-.22.05-.02.11-.05.16-.07.25-.11.49-.22.74-.33.18-.08.35-.16.53-.24,2.6-1.21,4.68-2.41,4.02-4.51-.84-2.66-8.87-4.31-14.3-6.35,0,0,0,0,0,0-.24-.09-.47-.18-.7-.27-.04-.01-.07-.03-.11-.04-.2-.08-.39-.16-.57-.24-.05-.02-.09-.04-.14-.06-.18-.08-.35-.16-.51-.24-.04-.02-.09-.04-.13-.06-.18-.09-.36-.18-.53-.27-.02,0-.04-.02-.06-.03-.19-.1-.37-.21-.54-.32-.01,0-.02-.01-.03-.02-.15-.1-.29-.19-.42-.29-.04-.03-.08-.06-.12-.1-.09-.07-.18-.15-.27-.23-.04-.04-.08-.08-.12-.12-.07-.07-.14-.14-.2-.21-.04-.04-.07-.09-.1-.13-.05-.07-.1-.15-.14-.22-.03-.04-.05-.09-.08-.13-.04-.08-.07-.16-.1-.24-.01-.04-.03-.08-.04-.12-.03-.12-.05-.25-.05-.37,0-1.54.09-3.07.26-4.59.01-.13.02-.26.02-.39,0-.03,0-.06,0-.1,0-.1-.01-.19-.02-.29,0-.03-.01-.06-.02-.1-.02-.1-.03-.19-.06-.28,0-.03-.02-.05-.02-.08-.03-.1-.06-.2-.1-.29,0-.02-.02-.04-.02-.05-.04-.1-.09-.21-.15-.3,0-.01-.01-.02-.02-.03-.06-.11-.13-.21-.2-.31,0,0,0,0,0-.01-.08-.11-.16-.21-.25-.31,0,0,0,0,0,0-.09-.1-.19-.2-.29-.3,0,0,0,0,0,0h0c-.73-.68-1.76-1.16-2.97-1.31-5.67-.7-11.71-1.08-17.99-1.08-18.17,0-34.4,3.18-45.12,8.16l-16.89-42.89c2.03-2.4,2.59-5.76.91-10.34-.49-1.35-1.15-2.72-1.94-4.06,3.95-1.05,7.09-2.63,8.75-4.73,30.83-39.14,42.4-24.74,42.4-49.12s-21.04-39.17-47-39.17-47,19.76-47,44.14c0,12.41-10.78,32.44.6,42.67,3.52,3.17,9.32,5.36,15.8,6.6-.27,3.34.14,6.85,1.25,9.89,1.88,5.14,5.35,7.74,9.45,8.62l19.57,49.69c.09.23.2.46.31.67.17.31.37.6.58.88-.07.46-.12.92-.12,1.38,0,12.37,26.17,22.4,58.45,22.4,10.62,0,20.57-1.09,29.14-2.98,2.51-.56,3.71-2.83,2.39-4.61-.22-.3-.41-.58-.59-.86h0c-.15-.22-.28-.43-.41-.64-.03-.05-.06-.1-.09-.15-.23-.39-.43-.77-.59-1.13Z"/>
78
+ </g>
79
+ <path class="cls-11" d="M583.23,393.7c0-31.91-14.48-151.42-1.02-180.35,3.34-7.17,7.01-12.76,10.69-15.5,4.25-3.17-1.45-27.18-7.16-37.24-9.06-15.95-31.5-32.22-70.35-31.35-49.31,1.11-59.79,65.78-64.66,114.88-1.71,17.22-8.38,33.59-19.28,47.04-24.5,30.22-282.51,32.6-276.03,44.9,87.85,166.81,211.62,187.5,275.59,187.5s152.23-72.02,152.23-129.88Z"/>
80
+ <path class="cls-12" d="M498.56,164.68c-.74-.4.6-1.19,1.38-.88,8.67,3.44,14.63,6.95,24.89,8.14,3.49.41,21.48-.97,21.97,2.41s-3.04,7.61-4.5,9.11c-1.8,1.84-4.63,3.5-8.28,2.45-11.15-3.21-23.68-14.89-35.46-21.23Z"/>
81
+ <path class="cls-2" d="M593.41,197.28c.08-.11.15-.23.22-.36.04-.07.07-.16.11-.24.06-.13.11-.27.16-.42.03-.09.06-.19.09-.29.04-.16.08-.33.12-.5.02-.1.04-.21.06-.32.03-.2.06-.4.09-.61.01-.1.03-.2.04-.31.03-.27.05-.55.06-.84,0-.06,0-.12.01-.18.03-.74.02-1.53-.03-2.39,0-.07,0-.14-.01-.21-.02-.36-.05-.72-.08-1.1,0-.09-.02-.19-.03-.28-.03-.37-.07-.74-.12-1.12-.01-.09-.02-.18-.03-.27-.05-.41-.1-.82-.16-1.24,0-.06-.02-.13-.03-.19-.37-2.53-.93-5.28-1.62-8.06-14.52,10.95-7.32,30.8-53.77,48.91-12.21,4.76,26.78,8.73,43.96,147.69-2.82-45.76-11.76-136.83-.24-161.59,3.34-7.17,7.01-12.76,10.69-15.5.14-.11.27-.24.4-.4.04-.05.07-.11.11-.17Z"/>
82
+ <path class="cls-9" d="M669.22,195.54c-.9-14.38-6.37-22.75-15.74-24.4-11.04-1.94-17.36,4.16-38.14,1.91-11.8-1.28-29.51-16.25-38.23-13.33-.19.06-.36.14-.54.22,1.18,9.92,1.83,20.82,1.83,32.27v.06c0,3.32,2.25,6.03,5.05,6.03h76.86c2.74,0,4.96,2.63,4.96,5.87,2.11,2.13,4.13-5.58,3.94-8.62Z"/>
83
+ <path class="cls-4" d="M578.17,180.38c.15,3.86.24,7.81.24,11.82v.06c0,3.32,2.25,6.03,5.05,6.03h76.86c.72,0,1.41.19,2.02.52-7.28-6.71-13.11-6.27-51.08-8.31-15.83-.85-21.28-9.62-33.1-10.12Z"/>
84
+ <path class="cls-4" d="M583.23,167.25s13.22,1.2,12.27,6.47c-.94,5.26-12.27-6.47-12.27-6.47Z"/>
85
+ <path class="cls-1" d="M475.91,325.57l-44.46-34.39-204.19,5.87c-22.9.66-45.08,8.15-63.69,21.5l-40.55,29.1,245.71,107.73c13.86,6.08,30.06,2.42,39.97-9.01l71.06-82c10.09-11.64,8.32-29.37-3.86-38.79Z"/>
86
+ <path class="cls-1" d="M228.43,408.36c-46.45-5.79-108.22-20.11-150.98-56.31-5.65-4.78-1.74-13.94,5.62-13.23,37.28,3.59,57.44,2.96,97.7-12.42l47.67,81.96Z"/>
87
+ <path class="cls-6" d="M144.52,332.23l-21.5,15.43,245.71,107.73c13.86,6.08,30.06,2.42,39.97-9.01l44.62-51.49c-127.73-.17-240.55-24.9-308.8-62.65Z"/>
88
+ <g>
89
+ <path class="cls-8" d="M502.63,634.23c0-1.26.09-2.51.26-3.74.23-1.66-1.57-3.14-4.11-3.39-5.67-.57-11.71-.88-17.99-.88-32.28,0-58.45,8.18-58.45,18.28s26.17,18.28,58.45,18.28c10.62,0,20.57-.89,29.14-2.44,2.51-.45,3.71-2.31,2.39-3.76-9.33-10.31,11.48-9.18,9.57-14.12-1.28-3.3-19.27-4.71-19.27-8.23Z"/>
90
+ <g class="cls-3">
91
+ <path class="cls-7" d="M517.91,646.13c-36.17.21-64.58,2.32-64.58,4.9,0,2.43,25.23,4.45,58.41,4.85-5.01-6.17,1.45-7.96,6.17-9.75Z"/>
92
+ </g>
93
+ <g class="cls-3">
94
+ <path class="cls-7" d="M453.33,634.53c0,3.59,29.8,6.52,67.21,6.69-4.47-2.47-17.9-3.94-17.9-6.98,0-1.26.09-2.51.26-3.74.12-.88-.33-1.7-1.15-2.32-28.12.88-48.41,3.39-48.41,6.36Z"/>
95
+ </g>
96
+ <path class="cls-8" d="M432.66,647.69h0c-4.67,1.28-9.63-1.02-11.09-5.13l-31.76-89.8,16.91-4.63,31.76,89.8c1.45,4.11-1.15,8.48-5.82,9.76Z"/>
97
+ <g class="cls-3">
98
+ <path class="cls-7" d="M431.8,642.56l-31.76-89.8,7.58-2.08-.9-2.56-16.91,4.63,31.76,89.8c1.45,4.11,6.42,6.4,11.09,5.13.92-.25,1.75-.62,2.49-1.09-1.53-.95-2.74-2.34-3.34-4.04Z"/>
99
+ </g>
100
+ <path class="cls-8" d="M392.55,577.64c3.13,9.51,10.63,11.22,18.12,9.31,7.49-1.91,12.14-6.72,9.01-16.23-3.13-9.51-12.85-20.12-20.35-18.21-7.49,1.91-9.92,15.62-6.79,25.13Z"/>
101
+ <path class="cls-11" d="M502.59,500.61c-26.16,17.71-45.26,16.73-76.09,60.31-6.99,9.89-40.02,9.35-50.99-1.64-11.39-11.4-.6-33.69-.6-47.51,0-27.15,21.04-49.15,47-49.15s103.17,22.78,80.69,38Z"/>
102
+ <g class="cls-3">
103
+ <path class="cls-7" d="M374.9,511.77c0-11.32,3.67-21.73,9.81-30.04-48.73-7.75-103.44-25.32-163.2-51.21,51.77,54.95,107.23,78.18,152.85,87.43.33-2.19.54-4.27.54-6.18Z"/>
104
+ </g>
105
+ </g>
106
+ </g>
107
+ </g>
108
+ </svg>