@lastbrain/app 0.1.47 → 1.0.2
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.
- package/dist/app-shell/layout.d.ts +1 -1
- package/dist/app-shell/layout.d.ts.map +1 -1
- package/dist/app-shell/layout.js +1 -1
- package/dist/components/NotificationContainer.js +1 -1
- package/dist/index.d.ts +19 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -19
- package/dist/layouts/AdminLayoutWithSidebar.d.ts +3 -2
- package/dist/layouts/AdminLayoutWithSidebar.d.ts.map +1 -1
- package/dist/layouts/AdminLayoutWithSidebar.js +5 -5
- package/dist/layouts/AppProviders.d.ts +1 -1
- package/dist/layouts/AppProviders.d.ts.map +1 -1
- package/dist/layouts/AppProviders.js +3 -3
- package/dist/layouts/AuthLayoutWithSidebar.d.ts +7 -4
- package/dist/layouts/AuthLayoutWithSidebar.d.ts.map +1 -1
- package/dist/layouts/AuthLayoutWithSidebar.js +5 -5
- package/dist/layouts/PublicLayoutWithSidebar.js +2 -2
- package/dist/layouts/RootLayout.js +1 -1
- package/dist/scripts/init-app.d.ts.map +1 -1
- package/dist/scripts/init-app.js +457 -39
- package/dist/scripts/module-add.js +1 -1
- package/dist/scripts/module-build.d.ts.map +1 -1
- package/dist/scripts/module-build.js +36 -15
- package/dist/scripts/module-create.js +8 -8
- package/dist/scripts/module-delete.d.ts.map +1 -1
- package/dist/scripts/module-delete.js +1 -1
- package/dist/templates/DefaultDoc.d.ts.map +1 -1
- package/dist/templates/DefaultDoc.js +1 -1
- package/dist/templates/DocPage.js +1 -1
- package/dist/templates/DocsPageWithModules.js +1 -1
- package/dist/types/menu.d.ts +23 -0
- package/dist/types/menu.d.ts.map +1 -0
- package/dist/types/menu.js +1 -0
- package/package.json +9 -1
- package/src/app-shell/layout.tsx +1 -1
- package/src/components/NotificationContainer.tsx +1 -1
- package/src/index.ts +24 -19
- package/src/layouts/AdminLayoutWithSidebar.tsx +11 -3
- package/src/layouts/AppProviders.tsx +4 -4
- package/src/layouts/AuthLayoutWithSidebar.tsx +18 -4
- package/src/layouts/PublicLayoutWithSidebar.tsx +2 -2
- package/src/layouts/RootLayout.tsx +1 -1
- package/src/scripts/init-app.ts +479 -49
- package/src/scripts/module-add.ts +1 -1
- package/src/scripts/module-build.ts +46 -22
- package/src/scripts/module-create.ts +8 -8
- package/src/scripts/module-delete.ts +1 -4
- package/src/templates/DefaultDoc.tsx +264 -0
- package/src/templates/DocPage.tsx +1 -1
- package/src/templates/DocsPageWithModules.tsx +1 -1
- package/src/types/menu.ts +18 -0
|
@@ -14,7 +14,7 @@ import type {
|
|
|
14
14
|
// Utiliser PROJECT_ROOT si défini (pour pnpm --filter), sinon process.cwd()
|
|
15
15
|
const projectRoot = process.env.PROJECT_ROOT || process.cwd();
|
|
16
16
|
// Si on est dans une app, monter jusqu'à la racine du monorepo
|
|
17
|
-
const
|
|
17
|
+
const _monorepoRoot = projectRoot.includes("/apps/")
|
|
18
18
|
? path.resolve(projectRoot, "..", "..")
|
|
19
19
|
: projectRoot;
|
|
20
20
|
const appDirectory = path.join(projectRoot, "app");
|
|
@@ -235,6 +235,13 @@ function buildPage(moduleConfig: ModuleBuildConfig, page: ModulePageConfig) {
|
|
|
235
235
|
page.path.includes("users/[id]") &&
|
|
236
236
|
page.componentExport === "UserPage";
|
|
237
237
|
|
|
238
|
+
// Détecter les pages légales qui utilisent cookies (privacy, terms, returns)
|
|
239
|
+
const isLegalPage =
|
|
240
|
+
page.section === "public" &&
|
|
241
|
+
(page.path.includes("privacy") ||
|
|
242
|
+
page.path.includes("terms") ||
|
|
243
|
+
page.path.includes("returns"));
|
|
244
|
+
|
|
238
245
|
let content: string;
|
|
239
246
|
|
|
240
247
|
if (isUserDetailPage) {
|
|
@@ -273,7 +280,17 @@ const ${page.componentExport} = dynamic(
|
|
|
273
280
|
{ ssr: false }
|
|
274
281
|
);
|
|
275
282
|
|
|
276
|
-
export default function ${wrapperName}${hasDynamicParams ? "(props:
|
|
283
|
+
export default function ${wrapperName}${hasDynamicParams ? "(props: Record<string, unknown>)" : "()"} {
|
|
284
|
+
return <${page.componentExport} ${hasDynamicParams ? "{...props}" : ""} />;
|
|
285
|
+
}
|
|
286
|
+
`;
|
|
287
|
+
} else if (isLegalPage) {
|
|
288
|
+
content = `// GENERATED BY LASTBRAIN MODULE BUILD
|
|
289
|
+
import { ${page.componentExport} } from "${moduleConfig.moduleName}";
|
|
290
|
+
|
|
291
|
+
export const dynamic = 'force-dynamic';
|
|
292
|
+
|
|
293
|
+
export default function ${wrapperName}${hasDynamicParams ? "(props: Record<string, unknown>)" : "()"} {
|
|
277
294
|
return <${page.componentExport} ${hasDynamicParams ? "{...props}" : ""} />;
|
|
278
295
|
}
|
|
279
296
|
`;
|
|
@@ -281,7 +298,7 @@ export default function ${wrapperName}${hasDynamicParams ? "(props: any)" : "()"
|
|
|
281
298
|
content = `// GENERATED BY LASTBRAIN MODULE BUILD
|
|
282
299
|
import { ${page.componentExport} } from "${moduleConfig.moduleName}";
|
|
283
300
|
|
|
284
|
-
export default function ${wrapperName}${hasDynamicParams ? "(props:
|
|
301
|
+
export default function ${wrapperName}${hasDynamicParams ? "(props: Record<string, unknown>)" : "()"} {
|
|
285
302
|
return <${page.componentExport} ${hasDynamicParams ? "{...props}" : ""} />;
|
|
286
303
|
}
|
|
287
304
|
`;
|
|
@@ -1012,33 +1029,40 @@ async function generateUserTabsConfig(moduleConfigs: ModuleBuildConfig[]) {
|
|
|
1012
1029
|
)
|
|
1013
1030
|
.sort((a, b) => (a.order || 0) - (b.order || 0));
|
|
1014
1031
|
|
|
1015
|
-
|
|
1016
|
-
console.log("⏭️ No user tabs configuration found in modules");
|
|
1017
|
-
return;
|
|
1018
|
-
}
|
|
1032
|
+
let appContent: string;
|
|
1019
1033
|
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
`const ${tab.componentExport} = dynamic(() => import("${tab.moduleName}").then(mod => ({ default: mod.${tab.componentExport} })), { ssr: true });`
|
|
1025
|
-
)
|
|
1026
|
-
.join("\n");
|
|
1034
|
+
if (userTabsConfigs.length === 0) {
|
|
1035
|
+
console.log(
|
|
1036
|
+
"⏭️ No user tabs configuration found in modules, creating empty config"
|
|
1037
|
+
);
|
|
1027
1038
|
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
.
|
|
1031
|
-
|
|
1039
|
+
// Créer un fichier vide avec l'interface correcte
|
|
1040
|
+
const timestamp = new Date().toISOString();
|
|
1041
|
+
appContent = `// GENERATED FILE - DO NOT EDIT MANUALLY\n// User tabs configuration\n// Generated at: ${timestamp}\n\n"use client";\n\nimport type React from "react";\n\nexport interface ModuleUserTab {\n key: string;\n title: string;\n icon?: string;\n component: React.ComponentType<{ userId: string }>;\n}\n\nexport const moduleUserTabs: ModuleUserTab[] = [];\n\nexport default moduleUserTabs;\n`;
|
|
1042
|
+
} else {
|
|
1043
|
+
// Générer les imports statiques (Next/dynamic pour chaque composant)
|
|
1044
|
+
const importsForApp = userTabsConfigs
|
|
1045
|
+
.map(
|
|
1046
|
+
(tab) =>
|
|
1047
|
+
`const ${tab.componentExport} = dynamic(() => import("${tab.moduleName}").then(mod => ({ default: mod.${tab.componentExport} })), { ssr: true });`
|
|
1048
|
+
)
|
|
1049
|
+
.join("\n");
|
|
1050
|
+
|
|
1051
|
+
// Générer le tableau des tabs
|
|
1052
|
+
const tabsArray = userTabsConfigs
|
|
1053
|
+
.map(
|
|
1054
|
+
(tab) => ` {
|
|
1032
1055
|
key: "${tab.key}",
|
|
1033
1056
|
title: "${tab.title}",
|
|
1034
1057
|
icon: "${tab.icon || ""}",
|
|
1035
1058
|
component: ${tab.componentExport},
|
|
1036
1059
|
}`
|
|
1037
|
-
|
|
1038
|
-
|
|
1060
|
+
)
|
|
1061
|
+
.join(",\n");
|
|
1039
1062
|
|
|
1040
|
-
|
|
1041
|
-
|
|
1063
|
+
const timestamp = new Date().toISOString();
|
|
1064
|
+
appContent = `// GENERATED FILE - DO NOT EDIT MANUALLY\n// User tabs configuration\n// Generated at: ${timestamp}\n\n"use client";\n\nimport dynamic from "next/dynamic";\nimport type React from "react";\n\n${importsForApp}\n\nexport interface ModuleUserTab {\n key: string;\n title: string;\n icon?: string;\n component: React.ComponentType<{ userId: string }>;\n}\n\nexport const moduleUserTabs: ModuleUserTab[] = [\n${tabsArray}\n];\n\nexport default moduleUserTabs;\n`;
|
|
1065
|
+
}
|
|
1042
1066
|
|
|
1043
1067
|
// Créer le fichier de configuration (uniquement dans /config)
|
|
1044
1068
|
const outputPath = path.join(projectRoot, "config", "user-tabs.ts");
|
|
@@ -399,7 +399,7 @@ export { default as buildConfig } from "./${moduleNameOnly}.build.config";
|
|
|
399
399
|
/**
|
|
400
400
|
* Génère le contenu du fichier server.ts
|
|
401
401
|
*/
|
|
402
|
-
function
|
|
402
|
+
function _generateServerTs(tables: TableConfig[]): string {
|
|
403
403
|
const exports: string[] = [];
|
|
404
404
|
|
|
405
405
|
for (const table of tables) {
|
|
@@ -1280,7 +1280,7 @@ export function getAvailableModuleNames(): string[] {
|
|
|
1280
1280
|
);
|
|
1281
1281
|
if (arrayMatch) {
|
|
1282
1282
|
const arrayContent = arrayMatch[1];
|
|
1283
|
-
const
|
|
1283
|
+
const _lastItem = arrayContent.trim().split("\n").pop();
|
|
1284
1284
|
|
|
1285
1285
|
// Ajouter le nouveau module à la fin du tableau
|
|
1286
1286
|
const newArrayContent =
|
|
@@ -1299,9 +1299,9 @@ export function getAvailableModuleNames(): string[] {
|
|
|
1299
1299
|
)
|
|
1300
1300
|
);
|
|
1301
1301
|
}
|
|
1302
|
-
} catch (
|
|
1302
|
+
} catch (_error) {
|
|
1303
1303
|
console.log(
|
|
1304
|
-
chalk.yellow(` ⚠️ Erreur lors de la mise à jour du registre: ${
|
|
1304
|
+
chalk.yellow(` ⚠️ Erreur lors de la mise à jour du registre: ${_error}`)
|
|
1305
1305
|
);
|
|
1306
1306
|
console.log(
|
|
1307
1307
|
chalk.gray(" Vous devrez ajouter manuellement le module au registre")
|
|
@@ -1472,7 +1472,7 @@ export async function createModuleStructure(
|
|
|
1472
1472
|
stdio: "inherit",
|
|
1473
1473
|
});
|
|
1474
1474
|
console.log(chalk.green("\n✅ Dépendances installées avec succès!"));
|
|
1475
|
-
} catch (
|
|
1475
|
+
} catch (_error) {
|
|
1476
1476
|
console.log(
|
|
1477
1477
|
chalk.yellow(
|
|
1478
1478
|
"\n⚠️ Erreur lors de l'installation, veuillez exécuter manuellement:"
|
|
@@ -1493,7 +1493,7 @@ export async function createModuleStructure(
|
|
|
1493
1493
|
stdio: "inherit",
|
|
1494
1494
|
});
|
|
1495
1495
|
console.log(chalk.green("✓ Module compilé"));
|
|
1496
|
-
} catch (
|
|
1496
|
+
} catch (_error) {
|
|
1497
1497
|
console.log(
|
|
1498
1498
|
chalk.yellow("⚠️ Build automatique échoué, exécutez: cd"),
|
|
1499
1499
|
config.slug,
|
|
@@ -1696,8 +1696,8 @@ export async function createModule() {
|
|
|
1696
1696
|
let rootDir: string;
|
|
1697
1697
|
try {
|
|
1698
1698
|
rootDir = findWorkspaceRoot();
|
|
1699
|
-
} catch (
|
|
1700
|
-
console.error(chalk.red("❌ " + (
|
|
1699
|
+
} catch (_error) {
|
|
1700
|
+
console.error(chalk.red("❌ " + (_error as Error).message));
|
|
1701
1701
|
process.exit(1);
|
|
1702
1702
|
}
|
|
1703
1703
|
|
|
@@ -3,10 +3,7 @@ import path from "path";
|
|
|
3
3
|
import chalk from "chalk";
|
|
4
4
|
import inquirer from "inquirer";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
|
-
import {
|
|
7
|
-
AVAILABLE_MODULES,
|
|
8
|
-
type ModuleMetadata,
|
|
9
|
-
} from "@lastbrain/core/config/modules";
|
|
6
|
+
import { AVAILABLE_MODULES } from "@lastbrain/core/config/modules";
|
|
10
7
|
|
|
11
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
12
9
|
const __dirname = path.dirname(__filename);
|
|
@@ -613,6 +613,270 @@ export function DefaultDocumentation() {
|
|
|
613
613
|
</code>
|
|
614
614
|
.
|
|
615
615
|
</p>
|
|
616
|
+
<h3 className="text-lg font-semibold mb-2">
|
|
617
|
+
1. Ajouter une page et un menu custom
|
|
618
|
+
</h3>
|
|
619
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
620
|
+
1. Crée une page dans l'app cible (exemple public) :
|
|
621
|
+
</p>
|
|
622
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
623
|
+
{" "}
|
|
624
|
+
```tsx
|
|
625
|
+
</p>
|
|
626
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
627
|
+
{" "}
|
|
628
|
+
// apps/lastbrain/app/nouvelle-page/page.tsx
|
|
629
|
+
</p>
|
|
630
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
631
|
+
{" "}
|
|
632
|
+
export default function NouvellePage() {
|
|
633
|
+
</p>
|
|
634
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
635
|
+
{" "}
|
|
636
|
+
return <div>Nouvelle Page</div>;
|
|
637
|
+
</p>
|
|
638
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
639
|
+
{" "}
|
|
640
|
+
}
|
|
641
|
+
</p>
|
|
642
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
643
|
+
{" "}
|
|
644
|
+
```
|
|
645
|
+
</p>
|
|
646
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
647
|
+
2. Déclare le menu dans{" "}
|
|
648
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
649
|
+
apps/lastbrain/config/menu-custom.ts
|
|
650
|
+
</code>{" "}
|
|
651
|
+
(fichier optionnel, non écrasé par les outils) :
|
|
652
|
+
</p>
|
|
653
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
654
|
+
{" "}
|
|
655
|
+
```ts
|
|
656
|
+
</p>
|
|
657
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
658
|
+
{" "}
|
|
659
|
+
import type { MenuCustom } from "./menu-custom";
|
|
660
|
+
</p>
|
|
661
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
662
|
+
{" "}
|
|
663
|
+
export const menuCustom: MenuCustom = {
|
|
664
|
+
</p>
|
|
665
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
666
|
+
{" "}
|
|
667
|
+
public: [
|
|
668
|
+
</p>
|
|
669
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
670
|
+
{" "}
|
|
671
|
+
{
|
|
672
|
+
</p>
|
|
673
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
674
|
+
{" "}
|
|
675
|
+
title: "Nouvelle Page",
|
|
676
|
+
</p>
|
|
677
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
678
|
+
{" "}
|
|
679
|
+
description: "Une page custom",
|
|
680
|
+
</p>
|
|
681
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
682
|
+
{" "}
|
|
683
|
+
icon: "Plus",
|
|
684
|
+
</p>
|
|
685
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
686
|
+
{" "}
|
|
687
|
+
path: "/nouvelle-page",
|
|
688
|
+
</p>
|
|
689
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
690
|
+
{" "}
|
|
691
|
+
order: 100,
|
|
692
|
+
</p>
|
|
693
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
694
|
+
{" "}
|
|
695
|
+
},
|
|
696
|
+
</p>
|
|
697
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2"> ],</p>
|
|
698
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
699
|
+
{" "}
|
|
700
|
+
auth: [],
|
|
701
|
+
</p>
|
|
702
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
703
|
+
{" "}
|
|
704
|
+
admin: [],
|
|
705
|
+
</p>
|
|
706
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
707
|
+
{" "}
|
|
708
|
+
};
|
|
709
|
+
</p>
|
|
710
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
711
|
+
{" "}
|
|
712
|
+
```
|
|
713
|
+
</p>
|
|
714
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
715
|
+
3. Choisis le préfixe de route pour la section :
|
|
716
|
+
</p>
|
|
717
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
718
|
+
{" "}
|
|
719
|
+
-{" "}
|
|
720
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
721
|
+
/
|
|
722
|
+
</code>{" "}
|
|
723
|
+
pour les pages publiques (header + palette + AppAside public).
|
|
724
|
+
</p>
|
|
725
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
726
|
+
{" "}
|
|
727
|
+
-{" "}
|
|
728
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
729
|
+
/auth/...
|
|
730
|
+
</code>{" "}
|
|
731
|
+
pour les pages authentifiées (header + palette + AppAside auth).
|
|
732
|
+
</p>
|
|
733
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
734
|
+
{" "}
|
|
735
|
+
-{" "}
|
|
736
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
737
|
+
/admin/...
|
|
738
|
+
</code>{" "}
|
|
739
|
+
pour les pages admin (header + palette + AppAside admin).
|
|
740
|
+
</p>
|
|
741
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
742
|
+
4. (Optionnel) Ajoute{" "}
|
|
743
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
744
|
+
order
|
|
745
|
+
</code>
|
|
746
|
+
,{" "}
|
|
747
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
748
|
+
icon
|
|
749
|
+
</code>
|
|
750
|
+
,{" "}
|
|
751
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
752
|
+
description
|
|
753
|
+
</code>{" "}
|
|
754
|
+
ou{" "}
|
|
755
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
756
|
+
shortcutDisplay
|
|
757
|
+
</code>{" "}
|
|
758
|
+
pour contrôler le tri, l'icône Lucide et l'affichage dans la
|
|
759
|
+
palette.
|
|
760
|
+
</p>
|
|
761
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
762
|
+
5. Aucun rebuild spécial : le système charge automatiquement{" "}
|
|
763
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
764
|
+
menu-custom.ts
|
|
765
|
+
</code>{" "}
|
|
766
|
+
et fusionne les menus custom avec la config existante dans le
|
|
767
|
+
Header, le Aside et la palette (KeyboardKey).
|
|
768
|
+
</p>
|
|
769
|
+
<h4 className="font-medium mb-2">Cas d'usage rapides</h4>
|
|
770
|
+
<div className="space-y-2">
|
|
771
|
+
<div className="flex items-start gap-2">
|
|
772
|
+
<span className="text-green-600">✅</span>
|
|
773
|
+
<span>
|
|
774
|
+
Page publique custom : place ton fichier dans{" "}
|
|
775
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
776
|
+
apps/lastbrain/app/(custom)/nouvelle-page/page.tsx
|
|
777
|
+
</code>{" "}
|
|
778
|
+
et ajoute l'entrée dans{" "}
|
|
779
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
780
|
+
menuCustom.public
|
|
781
|
+
</code>{" "}
|
|
782
|
+
avec{" "}
|
|
783
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
784
|
+
path: "/nouvelle-page"
|
|
785
|
+
</code>
|
|
786
|
+
.
|
|
787
|
+
</span>
|
|
788
|
+
</div>
|
|
789
|
+
<div className="flex items-start gap-2">
|
|
790
|
+
<span className="text-green-600">✅</span>
|
|
791
|
+
<span>
|
|
792
|
+
Page auth custom : place la page dans{" "}
|
|
793
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
794
|
+
apps/lastbrain/app/(custom)/auth/ma-page/page.tsx
|
|
795
|
+
</code>{" "}
|
|
796
|
+
avec un{" "}
|
|
797
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
798
|
+
path: "/auth/ma-page"
|
|
799
|
+
</code>{" "}
|
|
800
|
+
dans{" "}
|
|
801
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
802
|
+
menuCustom.auth
|
|
803
|
+
</code>
|
|
804
|
+
.
|
|
805
|
+
</span>
|
|
806
|
+
</div>
|
|
807
|
+
<div className="flex items-start gap-2">
|
|
808
|
+
<span className="text-green-600">✅</span>
|
|
809
|
+
<span>
|
|
810
|
+
Page admin custom : même principe avec un chemin{" "}
|
|
811
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
812
|
+
/admin/...
|
|
813
|
+
</code>{" "}
|
|
814
|
+
et une entrée dans{" "}
|
|
815
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
816
|
+
menuCustom.admin
|
|
817
|
+
</code>
|
|
818
|
+
.
|
|
819
|
+
</span>
|
|
820
|
+
</div>
|
|
821
|
+
</div>
|
|
822
|
+
<h3 className="text-lg font-semibold mb-2">
|
|
823
|
+
2. Masquer des menus et bloquer les routes (menu-ignored)
|
|
824
|
+
</h3>
|
|
825
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
826
|
+
1. Crée{" "}
|
|
827
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
828
|
+
apps/lastbrain/config/menu-ignored.ts
|
|
829
|
+
</code>{" "}
|
|
830
|
+
si absent :
|
|
831
|
+
</p>
|
|
832
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
833
|
+
{" "}
|
|
834
|
+
```ts
|
|
835
|
+
</p>
|
|
836
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
837
|
+
{" "}
|
|
838
|
+
export const menuIgnored = {
|
|
839
|
+
</p>
|
|
840
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
841
|
+
{" "}
|
|
842
|
+
public: [{ title: "Boutique", path: "/shop" }],
|
|
843
|
+
</p>
|
|
844
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
845
|
+
{" "}
|
|
846
|
+
auth: [
|
|
847
|
+
</p>
|
|
848
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
849
|
+
{" "}
|
|
850
|
+
{ title: "Mes commandes", path:
|
|
851
|
+
"/auth/core-order/account/orders" },
|
|
852
|
+
</p>
|
|
853
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2"> ],</p>
|
|
854
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
855
|
+
{" "}
|
|
856
|
+
};
|
|
857
|
+
</p>
|
|
858
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
859
|
+
{" "}
|
|
860
|
+
```
|
|
861
|
+
</p>
|
|
862
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
863
|
+
2. Le Header, l'AppAside et la palette excluent ces entrées par{" "}
|
|
864
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
865
|
+
title
|
|
866
|
+
</code>
|
|
867
|
+
.
|
|
868
|
+
</p>
|
|
869
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
870
|
+
3. Le middleware redirige toute route correspondante (
|
|
871
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
872
|
+
path
|
|
873
|
+
</code>{" "}
|
|
874
|
+
exact ou préfixe) vers{" "}
|
|
875
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
876
|
+
/404
|
|
877
|
+
</code>
|
|
878
|
+
.
|
|
879
|
+
</p>
|
|
616
880
|
</CardBody>
|
|
617
881
|
</Card>
|
|
618
882
|
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
HardDrive,
|
|
31
31
|
RotateCcw,
|
|
32
32
|
} from "lucide-react";
|
|
33
|
-
import { DefaultDocumentation } from "./DefaultDoc
|
|
33
|
+
import { DefaultDocumentation } from "./DefaultDoc";
|
|
34
34
|
|
|
35
35
|
// Composant NavigationListbox séparé pour éviter la recréation
|
|
36
36
|
interface NavigationListboxProps {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Template for docs page with dynamic module loading
|
|
2
2
|
import React from "react";
|
|
3
|
-
import { DocPage } from "./DocPage
|
|
3
|
+
import { DocPage } from "./DocPage";
|
|
4
4
|
|
|
5
5
|
// This will be replaced by module-build script with actual imports
|
|
6
6
|
// MODULES_IMPORTS_PLACEHOLDER
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { MenuItem } from "@lastbrain/ui";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Menu items to hide from display and block routes
|
|
5
|
+
*/
|
|
6
|
+
export interface MenuIgnored {
|
|
7
|
+
public: { title: string; path: string }[];
|
|
8
|
+
auth: { title: string; path: string }[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Custom menu items to add without creating a module
|
|
13
|
+
*/
|
|
14
|
+
export interface MenuCustom {
|
|
15
|
+
public?: MenuItem[];
|
|
16
|
+
auth?: MenuItem[];
|
|
17
|
+
admin?: MenuItem[];
|
|
18
|
+
}
|