diff --git a/README.adoc b/README.adoc index 49e776d7..d8312976 100644 --- a/README.adoc +++ b/README.adoc @@ -179,6 +179,11 @@ This example generates a complete application into the `target/frontend-react` d The `judo-ui-generator-maven-plugin` documentation is placed inside the plugin documentation itself. https://github.com/BlackBeltTechnology/judo-meta-ui/tree/develop/generator-maven-plugin +## Documentation + +Detailed documentation for the generated apps and how to maintain / modify them can be found under +link:{docdir}/docs/pages[docs/pages] folder. + ## Notes The `maven-dependency-plugin` copies repackaged dependencies from the module `judo-ui-react-external-packages`. diff --git a/docs/pages/00_intro.adoc b/docs/pages/00_intro.adoc new file mode 100644 index 00000000..7e4c4361 --- /dev/null +++ b/docs/pages/00_intro.adoc @@ -0,0 +1,11 @@ += Introduction +ifndef::env-site,env-github[] +endif::[] +// Settings +:idprefix: +:idseparator: - +:icons: font +:KW: [purple]##** +:KWE: **## + +JUDO React frontend generator templates and utilities / libraries. diff --git a/docs/pages/01_ui_react.adoc b/docs/pages/01_ui_react.adoc new file mode 100644 index 00000000..f6b48e12 --- /dev/null +++ b/docs/pages/01_ui_react.adoc @@ -0,0 +1,130 @@ += UI React +ifndef::env-site,env-github[] +endif::[] +// Settings +:idprefix: +:idseparator: - +:icons: font +:KW: [purple]##** +:KWE: **## + +JUDO React frontend generator templates. + +== Architecture + +WIP + +=== Fixed dependency versions and the map.json file + +In order for projects to be consistently re-built without changing versions and effective version mismatches, we fixed +in all dependency versions, and are providing a `pnpm.lock` file as well. + +Without fix versions, and a reproducible lock file, the dependency versions in `map.json` could differ, causing runtime +errors. + +== Customization + +There are two major ways how JUDO apps can be customized with various pros / cons: + +- Template overrides +- Providing custom implementations for certain interfaces + +Customization via template overrides is discussed at the https://github.com/BlackBeltTechnology/judo-meta-ui/tree/develop/generator-maven-plugin[ judo-meta-ui/generator-maven-plugin] +repository. + +In this documentation we will only discuss customization via interface implementation. + +=== Context + +JUDO frontend applications utilize the https://github.com/BlackBeltTechnology/pandino[Pandino] library. This library can +be considered as a "dependency injection framework on steroids". + +For details about Pandino, please check its corresponding documentation. + +Regardless of documentation, the fastest way of figuring out what interfaces can be re-implemented is by searching for: + +- `ComponentProxy` components +- `useTrackService()` hooks + +All of these usually consume at least a `filter` parameter and where applicable refer to a `T` generic type. + +> All customizable interfaces have a `string` representation (INTERFACE_KEY) since at the end of the day, JavaScript doesn't support + interfaces and we need to pair them up. + +=== First step + +The entry point for registering implementations is `src/custom/application-customizer.tsx`. + +[WARNING] +==== +This file MUST be put into the `.generator-ignore` file and should be added to Git, otherwise whatever we put into it +will be replaced by the generator. +==== + +You may put your implementations anywhere inside the project, the only purpose of the `application-customizer.tsx` file +is to be the entry point for registration. + +=== Implementing pages + +Interface keys for pages can be found at `src/routes.tsx` with their actual implementation pairs next to them. + +[source,typescriptjsx] +---- +import type { FC } from 'react'; +import type { BundleContext } from '@pandino/pandino-api'; +import { ApplicationCustomizer } from './interfaces'; +import { ROUTE_GOD_GALAXIES_TABLE_INTERFACE_KEY } from '../routes'; + +export class DefaultApplicationCustomizer implements ApplicationCustomizer { + async customize(context: BundleContext): Promise { + context.registerService(ROUTE_GOD_GALAXIES_TABLE_INTERFACE_KEY, CustomGalaxies); + } +} + +export const CustomGalaxies = () => { + return ( +
+ +
+ ); +}; +---- + +=== Implementing the localization loader + +The localization loader is responsible for loading the translations for the application. + +We need to implement the `L10NTranslationProvider` interface (`L10N_TRANSLATION_PROVIDER_INTERFACE_KEY`). + +[source,typescriptjsx] +---- +import type { BundleContext } from '@pandino/pandino-api'; +import { ApplicationCustomizer } from './interfaces'; +import { + L10N_TRANSLATION_PROVIDER_INTERFACE_KEY, + L10NTranslationProvider, + L10NTranslations, +} from '../l10n/l10n-context'; + +export class DefaultApplicationCustomizer implements ApplicationCustomizer { + async customize(context: BundleContext): Promise { + context.registerService(L10N_TRANSLATION_PROVIDER_INTERFACE_KEY, new CustomL10NProvider()); + } +} + +class CustomL10NProvider implements L10NTranslationProvider { + async provideTranslations(locale: string): Promise { + return Promise.resolve({ + systemTranslations: { + 'judo.pages.create': 'My Create Label', + // ... + }, + applicationTranslations: { + 'God.galaxies.View.group.group.2.group.2.constellation': 'cOnStElLaTiOn', + // ... + }, + }); + } +} +---- + diff --git a/docs/pages/02_react_external_packages.adoc b/docs/pages/02_react_external_packages.adoc new file mode 100644 index 00000000..2ff00799 --- /dev/null +++ b/docs/pages/02_react_external_packages.adoc @@ -0,0 +1,15 @@ += React External Packages +ifndef::env-site,env-github[] +endif::[] +// Settings +:idprefix: +:idseparator: - +:icons: font +:KW: [purple]##** +:KWE: **## + +Repackaged third-party dependencies used by JUDO React frontend apps / generators. + +== Process + +WIP diff --git a/docs/pom.xml b/docs/pom.xml new file mode 100644 index 00000000..17886e92 --- /dev/null +++ b/docs/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + + + hu.blackbelt.judo.generator + judo-ui-react-template + ${revision} + + + judo-ui-react-template-docs + JUDO UI React Frontend Generator Documentation + + jar + + + + + ${basedir} + + pages/ + + + + + + + + org.apache.felix + maven-bundle-plugin + 5.1.8 + true + + NONE + + {maven-resources} + + + + + + + diff --git a/judo-ui-react/src/main/java/hu/blackbelt/judo/ui/generator/react/UiPandinoHelper.java b/judo-ui-react/src/main/java/hu/blackbelt/judo/ui/generator/react/UiPandinoHelper.java new file mode 100644 index 00000000..13ba3fdd --- /dev/null +++ b/judo-ui-react/src/main/java/hu/blackbelt/judo/ui/generator/react/UiPandinoHelper.java @@ -0,0 +1,12 @@ +package hu.blackbelt.judo.ui.generator.react; + +import hu.blackbelt.judo.generator.commons.annotations.TemplateHelper; +import lombok.extern.java.Log; + +@Log +@TemplateHelper +public class UiPandinoHelper { + public static String camelCaseNameToInterfaceKey(String name) { + return name.replaceAll("([a-z])([A-Z]+)", "$1_$2").toUpperCase(); + } +} diff --git a/judo-ui-react/src/main/resources/actor/package.json.dependencies.fragment.hbs b/judo-ui-react/src/main/resources/actor/package.json.dependencies.fragment.hbs index 4ea9bf3c..d370f95f 100644 --- a/judo-ui-react/src/main/resources/actor/package.json.dependencies.fragment.hbs +++ b/judo-ui-react/src/main/resources/actor/package.json.dependencies.fragment.hbs @@ -5,6 +5,9 @@ "@mui/material": "5.11.4", "@mui/x-data-grid": "5.17.18", "@mui/x-date-pickers": "5.0.13", +"@pandino/loader-configuration-dom": "0.8.26", +"@pandino/pandino": "0.8.26", +"@pandino/react-hooks": "0.8.26", "@remix-run/router": "1.1.0", "axios": "1.2.1", "dayjs": "1.11.7", diff --git a/judo-ui-react/src/main/resources/actor/package.json.dev-dependencies.fragment.hbs b/judo-ui-react/src/main/resources/actor/package.json.dev-dependencies.fragment.hbs index 9e1704b0..0cdbdb77 100644 --- a/judo-ui-react/src/main/resources/actor/package.json.dev-dependencies.fragment.hbs +++ b/judo-ui-react/src/main/resources/actor/package.json.dev-dependencies.fragment.hbs @@ -1,4 +1,5 @@ "@judo/data-api-common": "0.4.2", +"@pandino/pandino-api": "0.8.26", "@rollup/plugin-commonjs": "24.0.0", "@rollup/plugin-node-resolve": "15.0.1", "@rollup/plugin-replace": "5.0.2", diff --git a/judo-ui-react/src/main/resources/actor/pnpm-lock.yaml b/judo-ui-react/src/main/resources/actor/pnpm-lock.yaml index f6b07857..27d57472 100644 --- a/judo-ui-react/src/main/resources/actor/pnpm-lock.yaml +++ b/judo-ui-react/src/main/resources/actor/pnpm-lock.yaml @@ -9,6 +9,10 @@ specifiers: '@mui/material': 5.11.4 '@mui/x-data-grid': 5.17.18 '@mui/x-date-pickers': 5.0.13 + '@pandino/loader-configuration-dom': 0.8.26 + '@pandino/pandino': 0.8.26 + '@pandino/pandino-api': 0.8.26 + '@pandino/react-hooks': 0.8.26 '@remix-run/router': 1.1.0 '@rollup/plugin-commonjs': 24.0.0 '@rollup/plugin-node-resolve': 15.0.1 @@ -46,6 +50,9 @@ dependencies: '@mui/material': 5.11.4_lskpmcsdi7ipu6qpuapyu56ihm '@mui/x-data-grid': 5.17.18_3sld6g3d73vxspzi5cx2xwhaya '@mui/x-date-pickers': 5.0.13_dd6xbejtdystigvbxpvulfxoou + '@pandino/loader-configuration-dom': 0.8.26 + '@pandino/pandino': 0.8.26 + '@pandino/react-hooks': 0.8.26 '@remix-run/router': 1.1.0 axios: 1.2.1 dayjs: 1.11.7 @@ -61,6 +68,7 @@ dependencies: devDependencies: '@judo/data-api-common': 0.4.2 + '@pandino/pandino-api': 0.8.26 '@rollup/plugin-commonjs': 24.0.0_rollup@3.7.5 '@rollup/plugin-node-resolve': 15.0.1_rollup@3.7.5 '@rollup/plugin-replace': 5.0.2_rollup@3.7.5 @@ -976,6 +984,26 @@ packages: fastq: 1.15.0 dev: true + /@pandino/loader-configuration-dom/0.8.26: + resolution: {integrity: sha512-vdh7dytSF8gbGpYXuAcwUoaK5KTR/8qRmF0m+822VhE/WmXbBMPeTPcsDdbZt3r/47JocWx2VcQa9B6bPuvgHA==} + engines: {node: '>=14.9.0'} + dev: false + + /@pandino/pandino-api/0.8.26: + resolution: {integrity: sha512-vKsT2C+AL2M/CkD0I2duwEjXI2jWDOmG4nDEV/7GlKjaRWjkGFVMgnjYaEPKqTjqA2pUK+ofKdaUfVPSN6DZLw==} + engines: {node: '>=14.9.0'} + dev: true + + /@pandino/pandino/0.8.26: + resolution: {integrity: sha512-PekDzJyK3vfDK9IPgz71oj+yFeTajKGB8DVHZXZ0Icow3Sum8woNIcPrsjv7DPSblmB65B0bQGEUj2SMRfzQqg==} + engines: {node: '>=14.9.0'} + dev: false + + /@pandino/react-hooks/0.8.26: + resolution: {integrity: sha512-iXY8I2JxjO5vExgqeeK89kAq2gXHDFSvZzFj2Ztp1pUqWETaaFvaVMO/2YWN+XuxcFGcVEYvXgjX4NOSrwZKDw==} + engines: {node: '>=14.9.0'} + dev: false + /@popperjs/core/2.11.6: resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==} dev: false diff --git a/judo-ui-react/src/main/resources/actor/public/map.json b/judo-ui-react/src/main/resources/actor/public/map.json index 80a767ef..a08a55ff 100644 --- a/judo-ui-react/src/main/resources/actor/public/map.json +++ b/judo-ui-react/src/main/resources/actor/public/map.json @@ -1,5 +1,9 @@ { "imports": { + "@pandino/loader-configuration-dom": "./externals/@pandino/loader-configuration-dom@0.8.26/dist/system/loader-configuration-dom.min.js", + "@pandino/pandino": "./externals/@pandino/pandino@0.8.26/dist/system/pandino.min.js", + "@pandino/pandino-api": "./externals/@pandino/pandino-api@0.8.26/dist/system/pandino-api.min.js", + "@pandino/react-hooks": "./externals/@pandino/react-hooks@0.8.26/dist/system/react-hooks.min.js", "dayjs": "./externals/dayjs@1.11.7/dayjs.min.js", "dayjs/locale/hu": "./externals/dayjs@1.11.7/locale/hu.js", "react/jsx-runtime": "./externals/react/jsx-runtime@18.2.0/umd/react-jsx-runtime.min.js", diff --git a/judo-ui-react/src/main/resources/actor/rollup.config.mjs.hbs b/judo-ui-react/src/main/resources/actor/rollup.config.mjs.hbs index bc9a9b4a..22a8c962 100644 --- a/judo-ui-react/src/main/resources/actor/rollup.config.mjs.hbs +++ b/judo-ui-react/src/main/resources/actor/rollup.config.mjs.hbs @@ -47,6 +47,10 @@ export default [ ['react', '/umd'], ['react-dom', '/umd'], ['i18next', '/dist/umd'], + ['@pandino/loader-configuration-dom', '/dist/system'], + ['@pandino/pandino', '/dist/system'], + ['@pandino/pandino-api', '/dist/system'], + ['@pandino/react-hooks', '/dist/system'], ['react-i18next', '/dist/umd'], ['@remix-run/router', '/dist'], ['react-router', '/dist/umd'], diff --git a/judo-ui-react/src/main/resources/actor/src/App.tsx.hbs b/judo-ui-react/src/main/resources/actor/src/App.tsx.hbs index 5b13a57b..0ad2ddd4 100644 --- a/judo-ui-react/src/main/resources/actor/src/App.tsx.hbs +++ b/judo-ui-react/src/main/resources/actor/src/App.tsx.hbs @@ -6,16 +6,7 @@ import { useEffect, useState } from 'react'; import { ThemeProvider } from '@mui/material'; -import { I18nextProvider } from 'react-i18next'; -{{# if defaultLanguage }} - {{# neq (shortLocale defaultLanguage '') 'en' }} - import 'dayjs/locale/{{ shortLocale defaultLanguage '' }}'; - {{/ neq }} -{{/ if }} -import i18n from 'i18next'; -import { initReactI18next } from 'react-i18next'; -import { LocalizationProvider } from '@mui/x-date-pickers'; -import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { L10NProvider } from './l10n/l10n-context'; import { theme } from './theme'; import { DialogProvider, BreadcrumbProvider, SnackProvider, MdiIcon } from './components'; import { Layout } from './layout'; @@ -26,69 +17,29 @@ import { useHeroProps, useLogoProps } from './hooks'; {{/ if }} function App() { - const defaultLocale = '{{ defaultLanguage }}' || 'default'; - const [locale] = useState(defaultLocale); - const [translation, setTranslation] = useState(null); - const [drawerWidth] = useState(300); - const heroProps = useHeroProps(); - const logoProps = useLogoProps(); - - useEffect(() => { - (async () => { - const responseSystem = await fetch(`i18n/system_${locale}.json`); - const dataSystem = await responseSystem.json(); - const responseApplication = await fetch(`i18n/application_${locale}.json`); - const dataApplication = await responseApplication.json(); - - setTranslation({ - ...dataSystem.translation, - ...dataApplication.translation, - }); - - i18n - .use(initReactI18next) - .init({ - resources: { - [locale]: { - translation: { - ...dataSystem.translation, - ...dataApplication.translation, - }, - }, - }, - lng: locale, - interpolation: { - escapeValue: false, - }, - }); - })(); - }, [locale]); + const [drawerWidth] = useState(300); + const heroProps = useHeroProps(); + const logoProps = useLogoProps(); - return ( - - - + return ( + + {{# if application.authentication }} {{/ if }} - { - translation - ? - : null - } + {{# if application.authentication }} {{/ if }} - - - - ); + + + ); } export default App; diff --git a/judo-ui-react/src/main/resources/actor/src/custom/application-customizer.tsx.hbs b/judo-ui-react/src/main/resources/actor/src/custom/application-customizer.tsx.hbs new file mode 100644 index 00000000..2d4d4ba1 --- /dev/null +++ b/judo-ui-react/src/main/resources/actor/src/custom/application-customizer.tsx.hbs @@ -0,0 +1,8 @@ +import type { BundleContext } from '@pandino/pandino-api'; +import { ApplicationCustomizer } from './interfaces'; + +export class DefaultApplicationCustomizer implements ApplicationCustomizer { + async customize(context: BundleContext): Promise { + // register your implementations here + } +} diff --git a/judo-ui-react/src/main/resources/actor/src/custom/index.tsx.hbs b/judo-ui-react/src/main/resources/actor/src/custom/index.tsx.hbs new file mode 100644 index 00000000..dbf34523 --- /dev/null +++ b/judo-ui-react/src/main/resources/actor/src/custom/index.tsx.hbs @@ -0,0 +1,10 @@ +/////////////////////////////////////////////////////////////////////////////// +// G E N E R A T E D S O U R C E +// ------------------------------ +// Path expression: {{{ cleanup template.pathExpression }}} +// Template name: {{ template.templateName }} + +import { DefaultApplicationCustomizer } from './application-customizer'; +export * from './interfaces'; + +export const applicationCustomizer = new DefaultApplicationCustomizer(); diff --git a/judo-ui-react/src/main/resources/actor/src/custom/interfaces.ts.hbs b/judo-ui-react/src/main/resources/actor/src/custom/interfaces.ts.hbs new file mode 100644 index 00000000..7bb655e3 --- /dev/null +++ b/judo-ui-react/src/main/resources/actor/src/custom/interfaces.ts.hbs @@ -0,0 +1,5 @@ +import type { BundleContext } from '@pandino/pandino-api'; + +export interface ApplicationCustomizer { + customize (context: BundleContext): Promise; +} diff --git a/judo-ui-react/src/main/resources/actor/src/l10n/l10n-context.tsx.hbs b/judo-ui-react/src/main/resources/actor/src/l10n/l10n-context.tsx.hbs new file mode 100644 index 00000000..15643be0 --- /dev/null +++ b/judo-ui-react/src/main/resources/actor/src/l10n/l10n-context.tsx.hbs @@ -0,0 +1,99 @@ +{{# if defaultLanguage }} + {{# neq (shortLocale defaultLanguage '') 'en' }} + import 'dayjs/locale/{{ shortLocale defaultLanguage '' }}'; + {{/ neq }} +{{/ if }} +import { createContext, useContext, useState, useEffect } from 'react'; +import type { ReactNode } from 'react'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { I18nextProvider } from 'react-i18next'; +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; +import { OBJECTCLASS, ServiceReference } from '@pandino/pandino-api'; +import { useTrackService, useBundleContext } from '@pandino/react-hooks'; + +export interface L10NContext { + locale: string; + setLocale: (newLocale: string) => void; +} + +const L10NContext = createContext({} as unknown as L10NContext); + +export interface L10NTranslations { + systemTranslations: Record; + applicationTranslations: Record; +}; + +export const L10N_TRANSLATION_PROVIDER_INTERFACE_KEY = 'L10NTranslationProvider'; + +export interface L10NTranslationProvider { + provideTranslations(locale: string): Promise; +} +export const L10NProvider = ({ children }: { children: ReactNode }) => { + const defaultLocale = '{{ defaultLanguage }}' || 'default'; + const [locale, setLocale] = useState(defaultLocale); + const [translation, setTranslation] = useState(null); + const [filter, setFilter] = useState(`(${OBJECTCLASS}=${L10N_TRANSLATION_PROVIDER_INTERFACE_KEY})`); + const { service: translationProvider } = useTrackService(filter); + + useEffect(() => { + (async () => { + let dataSystem: { translation: any } = { translation: {} }; + let dataApplication: { translation: any } = { translation: {} }; + + if (translationProvider) { + const { systemTranslations, applicationTranslations } = await translationProvider.provideTranslations(locale); + dataSystem = { translation: systemTranslations }; + dataApplication = { translation: applicationTranslations }; + } else { + try { + const responseSystem = await fetch(`i18n/system_${locale}.json`); + dataSystem = await responseSystem.json(); + const responseApplication = await fetch(`i18n/application_${locale}.json`); + dataApplication = await responseApplication.json(); + } catch(error) { + console.error(`Error fetching i18n resources: ${error}`); + } + } + + setTranslation({ + ...dataSystem.translation, + ...dataApplication.translation, + }); + + i18n + .use(initReactI18next) + .init({ + resources: { + [locale]: { + translation: { + ...dataSystem.translation, + ...dataApplication.translation, + }, + }, + }, + lng: locale, + interpolation: { + escapeValue: false, + }, + }); + })(); + }, [locale, translationProvider]); + + return ( + + + + {translation && children} + + + + ); +}; + +export const useL10N = () => { + const { locale, setLocale } = useContext(L10NContext); + + return { locale, setLocale }; +}; diff --git a/judo-ui-react/src/main/resources/actor/src/layout/Navigator.tsx.hbs b/judo-ui-react/src/main/resources/actor/src/layout/Navigator.tsx.hbs index cf5ee80d..bad89134 100644 --- a/judo-ui-react/src/main/resources/actor/src/layout/Navigator.tsx.hbs +++ b/judo-ui-react/src/main/resources/actor/src/layout/Navigator.tsx.hbs @@ -63,7 +63,9 @@ export function Navigator(props: DrawerProps & NavigatorProps) { return ( - + {{# if application.authentication }} + + {{/ if }} {items.map(item => item.items && item.items.length ? explicit api -> window.location.origin const FILE_DEFAULT_BASE_URL: string = process.env.FILE_DEFAULT_BASE_URL || API_DEFAULT_BASE_URL; +const pandino = new Pandino({ + ...loaderConfiguration, +}); + +await pandino.init(); +await pandino.start(); + +await applicationCustomizer.customize(pandino.getBundleContext()); + judoAxiosProvider.init({ axios, basePathFactory: () => API_DEFAULT_BASE_URL + API_RELATIVE_PATH, @@ -46,21 +59,23 @@ const root = createRoot(document.getElementById('root') as HTMLElement); {{/ if }} root.render( -{{# if application.authentication }} - - -{{/ if }} - - - }> - {routes.map((route) => ( - - ))} - - - , -{{# if application.authentication }} - - -{{/ if }} + + {{# if application.authentication }} + + + {{/ if }} + + + }> + {routes.map((route) => ( + + ))} + + + , + {{# if application.authentication }} + + + {{/ if }} + , ); diff --git a/judo-ui-react/src/main/resources/actor/src/routes.tsx.hbs b/judo-ui-react/src/main/resources/actor/src/routes.tsx.hbs index f08f6b67..0139d761 100644 --- a/judo-ui-react/src/main/resources/actor/src/routes.tsx.hbs +++ b/judo-ui-react/src/main/resources/actor/src/routes.tsx.hbs @@ -6,27 +6,35 @@ import { Navigate, Route } from 'react-router-dom'; import { lazy, ReactElement, Suspense } from 'react'; +import { OBJECTCLASS } from '@pandino/pandino-api'; +import { ComponentProxy } from '@pandino/react-hooks'; let routes: Array<{path: string, element: ReactElement, exact?: boolean}> = []; {{# each (getPagesForRouting application) as |page| }} {{# if page.isPageTypeDashboard }} + export const ROUTE_DASHBOARD_INTERFACE_KEY = 'DashboardRoute'; const DashboardRoute = lazy(() => import('./pages/{{ pageIndexRelativeImportPath page }}')); routes.push({ path: '', exact: true, element: - + + + , }); {{ else }} + export const ROUTE_{{ camelCaseNameToInterfaceKey (pageName page) }}_INTERFACE_KEY = '{{ pageName page }}Route'; const {{ pageName page }} = lazy(() => import('./pages/{{ pageIndexRelativeImportPath page }}')); routes.push({ path: '{{ getPageRoute page }}', element: - <{{ pageName page }} /> + + <{{ pageName page }} /> + , }); {{/ if }} diff --git a/judo-ui-react/src/main/resources/ui-react.yaml b/judo-ui-react/src/main/resources/ui-react.yaml index 0ddb2851..cf07034e 100644 --- a/judo-ui-react/src/main/resources/ui-react.yaml +++ b/judo-ui-react/src/main/resources/ui-react.yaml @@ -219,6 +219,23 @@ templates: templateName: actor/src/config/layout.ts.hbs applicationBased: true + # Actor - src - custom + + - name: actor/src/custom/application-customizer.tsx + pathExpression: "'src/custom/application-customizer.tsx'" + templateName: actor/src/custom/application-customizer.tsx.hbs + applicationBased: true + + - name: actor/src/custom/index.tsx + pathExpression: "'src/custom/index.tsx'" + templateName: actor/src/custom/index.tsx.hbs + applicationBased: true + + - name: actor/src/custom/interfaces.ts + pathExpression: "'src/custom/interfaces.ts'" + templateName: actor/src/custom/interfaces.ts.hbs + applicationBased: true + # Actor - src - auth - name: actor/src/auth/index.tsx @@ -547,6 +564,11 @@ templates: templateName: actor/src/l10n/@mui/x-date-pickers/huHU.ts.hbs applicationBased: true + - name: actor/src/l10n/l10n-context.tsx + pathExpression: "'src/l10n/l10n-context.tsx'" + templateName: actor/src/l10n/l10n-context.tsx.hbs + applicationBased: true + # Actor - src - pages - name: actor/src/pages/index.tsx