@endora-commerce/mod-megamenu 0.100.0
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/LICENSE +21 -0
- package/README.md +59 -0
- package/dist/admin/api/megamenu-client.d.ts +28 -0
- package/dist/admin/api/megamenu-client.d.ts.map +1 -0
- package/dist/admin/api/megamenu-client.js +43 -0
- package/dist/admin/api/megamenu-client.js.map +1 -0
- package/dist/admin/components/BindingsPanel.d.ts +10 -0
- package/dist/admin/components/BindingsPanel.d.ts.map +1 -0
- package/dist/admin/components/BindingsPanel.js +120 -0
- package/dist/admin/components/BindingsPanel.js.map +1 -0
- package/dist/admin/components/MenuItemConfigPanel.d.ts +22 -0
- package/dist/admin/components/MenuItemConfigPanel.d.ts.map +1 -0
- package/dist/admin/components/MenuItemConfigPanel.js +77 -0
- package/dist/admin/components/MenuItemConfigPanel.js.map +1 -0
- package/dist/admin/components/MenuItemTree.d.ts +13 -0
- package/dist/admin/components/MenuItemTree.d.ts.map +1 -0
- package/dist/admin/components/MenuItemTree.js +46 -0
- package/dist/admin/components/MenuItemTree.js.map +1 -0
- package/dist/admin/index.d.ts +31 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +47 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/pages/MegamenuEditor.d.ts +4 -0
- package/dist/admin/pages/MegamenuEditor.d.ts.map +1 -0
- package/dist/admin/pages/MegamenuEditor.js +151 -0
- package/dist/admin/pages/MegamenuEditor.js.map +1 -0
- package/dist/admin/pages/MegamenuListPage.d.ts +4 -0
- package/dist/admin/pages/MegamenuListPage.d.ts.map +1 -0
- package/dist/admin/pages/MegamenuListPage.js +51 -0
- package/dist/admin/pages/MegamenuListPage.js.map +1 -0
- package/dist/backend/entities/megamenu-binding.entity.d.ts +18 -0
- package/dist/backend/entities/megamenu-binding.entity.d.ts.map +1 -0
- package/dist/backend/entities/megamenu-binding.entity.js +61 -0
- package/dist/backend/entities/megamenu-binding.entity.js.map +1 -0
- package/dist/backend/entities/megamenu-item.entity.d.ts +27 -0
- package/dist/backend/entities/megamenu-item.entity.d.ts.map +1 -0
- package/dist/backend/entities/megamenu-item.entity.js +83 -0
- package/dist/backend/entities/megamenu-item.entity.js.map +1 -0
- package/dist/backend/entities/megamenu.entity.d.ts +17 -0
- package/dist/backend/entities/megamenu.entity.d.ts.map +1 -0
- package/dist/backend/entities/megamenu.entity.js +57 -0
- package/dist/backend/entities/megamenu.entity.js.map +1 -0
- package/dist/backend/index.d.ts +116 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +147 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/routes.admin.d.ts +10 -0
- package/dist/backend/routes.admin.d.ts.map +1 -0
- package/dist/backend/routes.admin.js +50 -0
- package/dist/backend/routes.admin.js.map +1 -0
- package/dist/backend/routes.storefront.d.ts +6 -0
- package/dist/backend/routes.storefront.d.ts.map +1 -0
- package/dist/backend/routes.storefront.js +26 -0
- package/dist/backend/routes.storefront.js.map +1 -0
- package/dist/backend/services/asset-references.d.ts +4 -0
- package/dist/backend/services/asset-references.d.ts.map +1 -0
- package/dist/backend/services/asset-references.js +36 -0
- package/dist/backend/services/asset-references.js.map +1 -0
- package/dist/backend/services/cms-references.d.ts +6 -0
- package/dist/backend/services/cms-references.d.ts.map +1 -0
- package/dist/backend/services/cms-references.js +39 -0
- package/dist/backend/services/cms-references.js.map +1 -0
- package/dist/backend/services/cross-module-ports.d.ts +112 -0
- package/dist/backend/services/cross-module-ports.d.ts.map +1 -0
- package/dist/backend/services/cross-module-ports.js +88 -0
- package/dist/backend/services/cross-module-ports.js.map +1 -0
- package/dist/backend/services/megamenu-cache.d.ts +36 -0
- package/dist/backend/services/megamenu-cache.d.ts.map +1 -0
- package/dist/backend/services/megamenu-cache.js +70 -0
- package/dist/backend/services/megamenu-cache.js.map +1 -0
- package/dist/backend/services/megamenu-item-service.d.ts +39 -0
- package/dist/backend/services/megamenu-item-service.d.ts.map +1 -0
- package/dist/backend/services/megamenu-item-service.js +151 -0
- package/dist/backend/services/megamenu-item-service.js.map +1 -0
- package/dist/backend/services/megamenu-language-reference.d.ts +12 -0
- package/dist/backend/services/megamenu-language-reference.d.ts.map +1 -0
- package/dist/backend/services/megamenu-language-reference.js +24 -0
- package/dist/backend/services/megamenu-language-reference.js.map +1 -0
- package/dist/backend/services/megamenu-reference-registry.d.ts +24 -0
- package/dist/backend/services/megamenu-reference-registry.d.ts.map +1 -0
- package/dist/backend/services/megamenu-reference-registry.js +69 -0
- package/dist/backend/services/megamenu-reference-registry.js.map +1 -0
- package/dist/backend/services/megamenu-service.d.ts +70 -0
- package/dist/backend/services/megamenu-service.d.ts.map +1 -0
- package/dist/backend/services/megamenu-service.js +299 -0
- package/dist/backend/services/megamenu-service.js.map +1 -0
- package/dist/backend/services/storefront-resolver.d.ts +46 -0
- package/dist/backend/services/storefront-resolver.d.ts.map +1 -0
- package/dist/backend/services/storefront-resolver.js +162 -0
- package/dist/backend/services/storefront-resolver.js.map +1 -0
- package/dist/backend/services/target-validator.d.ts +24 -0
- package/dist/backend/services/target-validator.d.ts.map +1 -0
- package/dist/backend/services/target-validator.js +105 -0
- package/dist/backend/services/target-validator.js.map +1 -0
- package/dist/manifest.d.ts +167 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +170 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrations/20260505T193836_megamenu_init.d.ts +23 -0
- package/dist/migrations/20260505T193836_megamenu_init.d.ts.map +1 -0
- package/dist/migrations/20260505T193836_megamenu_init.js +91 -0
- package/dist/migrations/20260505T193836_megamenu_init.js.map +1 -0
- package/dist/migrations/index.d.ts +27 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +29 -0
- package/dist/migrations/index.js.map +1 -0
- package/docs/megamenu/index.md +159 -0
- package/i18n/en.json +96 -0
- package/i18n/pl.json +96 -0
- package/package.json +99 -0
- package/tailwind.css +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Endora sp. z o.o. and the Endora Commerce contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<!-- Generated by `pnpm --filter backend run manifests:generate`. Delete this line to take the file over; a README without it is never regenerated. -->
|
|
2
|
+
|
|
3
|
+
# @endora-commerce/mod-megamenu
|
|
4
|
+
|
|
5
|
+
Multi-column dropdown navigation builder.
|
|
6
|
+
|
|
7
|
+
## What this is
|
|
8
|
+
|
|
9
|
+
An **Endora Commerce module package**. Its module id is `megamenu` — the identity of record in the platform's registries, in its migrations and in its setting, permission and translation codes.
|
|
10
|
+
|
|
11
|
+
A module is not imported by application code. The platform discovers the extension packages an instance has installed, reads the manifest on the root subpath and composes the module from it, so installing this package and starting the instance is the whole integration.
|
|
12
|
+
|
|
13
|
+
## Entry points
|
|
14
|
+
|
|
15
|
+
| Import | Contents |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `@endora-commerce/mod-megamenu` | the module manifest — its id, version, dependencies, settings and activation |
|
|
18
|
+
| `@endora-commerce/mod-megamenu/admin` | the Admin UI contribution: the screens, navigation and palette actions it adds |
|
|
19
|
+
| `@endora-commerce/mod-megamenu/backend` | the composition root the platform calls, with the entities, services, routes and workers it registers |
|
|
20
|
+
| `@endora-commerce/mod-megamenu/migrations` | the module’s own schema migrations, in the order the platform runs them |
|
|
21
|
+
| `@endora-commerce/mod-megamenu/tailwind.css` | the Tailwind source declaration for the admin code above |
|
|
22
|
+
|
|
23
|
+
## Depends on
|
|
24
|
+
|
|
25
|
+
Everything below is a **peer** dependency, so the application resolves exactly one copy of each — two copies of a host or of React are a runtime failure rather than a type error. An entry marked *optional* is needed only by the layers that use it.
|
|
26
|
+
|
|
27
|
+
**Endora packages**
|
|
28
|
+
|
|
29
|
+
- `@endora-commerce/admin-kit` — *optional*
|
|
30
|
+
- `@endora-commerce/contracts`
|
|
31
|
+
- `@endora-commerce/platform`
|
|
32
|
+
|
|
33
|
+
**Third-party**
|
|
34
|
+
|
|
35
|
+
- `@mikro-orm/core` ^6
|
|
36
|
+
- `@mikro-orm/migrations` ^6
|
|
37
|
+
- `@mikro-orm/postgresql` ^6
|
|
38
|
+
- `fastify` ^5
|
|
39
|
+
- `ioredis` ^5
|
|
40
|
+
- `lucide-react` ^1 — *optional*
|
|
41
|
+
- `react` ^19 — *optional*
|
|
42
|
+
- `react-router-dom` ^7 — *optional*
|
|
43
|
+
|
|
44
|
+
## What the tarball carries
|
|
45
|
+
|
|
46
|
+
- `dist/` — the compiled JavaScript and its type declarations
|
|
47
|
+
- `i18n/` — the translation bundles this package ships (`en`, `pl`), loaded by the platform
|
|
48
|
+
- `docs/` — the package’s own pages in the Endora Commerce documentation site
|
|
49
|
+
- `tailwind.css` — the Tailwind source declaration
|
|
50
|
+
|
|
51
|
+
## Install
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pnpm add @endora-commerce/mod-megamenu
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Licence
|
|
58
|
+
|
|
59
|
+
MIT — the text is in `LICENSE`, beside this file.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ActivateBindingRequest, ActivateBindingResponse, AddBindingRequest, CreateMegamenuRequest, MegamenuBinding, MegamenuDetail, MegamenuSummary, PatchMegamenuRequest, PutItemsRequest } from '@endora-commerce/contracts';
|
|
2
|
+
export type { ActivateBindingRequest, ActivateBindingResponse, AddBindingRequest, CreateMegamenuRequest, MegamenuBinding, MegamenuDetail, MegamenuSummary, PatchMegamenuRequest, PutItemsRequest, };
|
|
3
|
+
export interface ListMenusResponse {
|
|
4
|
+
data: MegamenuSummary[];
|
|
5
|
+
nextCursor: string | null;
|
|
6
|
+
}
|
|
7
|
+
export declare const megamenuClient: {
|
|
8
|
+
listMenus(): Promise<ListMenusResponse>;
|
|
9
|
+
createMenu(body: CreateMegamenuRequest): Promise<MegamenuDetail>;
|
|
10
|
+
getMenu(id: string): Promise<MegamenuDetail>;
|
|
11
|
+
patchMenu(id: string, body: PatchMegamenuRequest): Promise<MegamenuDetail>;
|
|
12
|
+
deleteMenu(id: string): Promise<void>;
|
|
13
|
+
putItems(id: string, body: PutItemsRequest): Promise<{
|
|
14
|
+
data: MegamenuDetail;
|
|
15
|
+
meta?: {
|
|
16
|
+
warnings: Array<{
|
|
17
|
+
code: string;
|
|
18
|
+
message: string;
|
|
19
|
+
}>;
|
|
20
|
+
};
|
|
21
|
+
}>;
|
|
22
|
+
listBindings(id: string): Promise<MegamenuBinding[]>;
|
|
23
|
+
addBinding(id: string, body: AddBindingRequest): Promise<MegamenuBinding>;
|
|
24
|
+
removeBinding(id: string, salesChannelId: string, language: string): Promise<void>;
|
|
25
|
+
activate(id: string, body: ActivateBindingRequest): Promise<ActivateBindingResponse>;
|
|
26
|
+
deactivate(id: string, body: ActivateBindingRequest): Promise<void>;
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=megamenu-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"megamenu-client.d.ts","sourceRoot":"","sources":["../../../src/admin/api/megamenu-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,eAAe,EACf,oBAAoB,EACpB,eAAe,EAChB,MAAM,4BAA4B,CAAC;AAEpC,YAAY,EACV,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,eAAe,EACf,oBAAoB,EACpB,eAAe,GAChB,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,eAAe,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,eAAO,MAAM,cAAc;iBACZ,OAAO,CAAC,iBAAiB,CAAC;qBAIhB,qBAAqB,GAAG,OAAO,CAAC,cAAc,CAAC;gBAKpD,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;kBAO9B,MAAM,QAAQ,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC;mBAQ3D,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;iBAKrC,MAAM,QACJ,eAAe,GACpB,OAAO,CAAC;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,IAAI,CAAC,EAAE;YAAE,QAAQ,EAAE,KAAK,CAAC;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,CAAA;KAAE,CAAC;qBAO5E,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;mBAOrC,MAAM,QAAQ,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC;sBAQvD,MAAM,kBAAkB,MAAM,YAAY,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;iBAMrE,MAAM,QAAQ,sBAAsB,GAAG,OAAO,CAAC,uBAAuB,CAAC;mBAQrE,MAAM,QAAQ,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;CAG1E,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { apiClient } from '@endora-commerce/admin-kit/lib';
|
|
2
|
+
export const megamenuClient = {
|
|
3
|
+
listMenus() {
|
|
4
|
+
return apiClient.get('/api/v1/admin/megamenu/menus');
|
|
5
|
+
},
|
|
6
|
+
async createMenu(body) {
|
|
7
|
+
const out = await apiClient.post('/api/v1/admin/megamenu/menus', body);
|
|
8
|
+
return out.data;
|
|
9
|
+
},
|
|
10
|
+
async getMenu(id) {
|
|
11
|
+
const out = await apiClient.get(`/api/v1/admin/megamenu/menus/${encodeURIComponent(id)}`);
|
|
12
|
+
return out.data;
|
|
13
|
+
},
|
|
14
|
+
async patchMenu(id, body) {
|
|
15
|
+
const out = await apiClient.patch(`/api/v1/admin/megamenu/menus/${encodeURIComponent(id)}`, body);
|
|
16
|
+
return out.data;
|
|
17
|
+
},
|
|
18
|
+
async deleteMenu(id) {
|
|
19
|
+
await apiClient.delete(`/api/v1/admin/megamenu/menus/${encodeURIComponent(id)}`);
|
|
20
|
+
},
|
|
21
|
+
async putItems(id, body) {
|
|
22
|
+
return apiClient.put(`/api/v1/admin/megamenu/menus/${encodeURIComponent(id)}/items`, body);
|
|
23
|
+
},
|
|
24
|
+
async listBindings(id) {
|
|
25
|
+
const out = await apiClient.get(`/api/v1/admin/megamenu/menus/${encodeURIComponent(id)}/bindings`);
|
|
26
|
+
return out.data;
|
|
27
|
+
},
|
|
28
|
+
async addBinding(id, body) {
|
|
29
|
+
const out = await apiClient.post(`/api/v1/admin/megamenu/menus/${encodeURIComponent(id)}/bindings`, body);
|
|
30
|
+
return out.data;
|
|
31
|
+
},
|
|
32
|
+
async removeBinding(id, salesChannelId, language) {
|
|
33
|
+
await apiClient.delete(`/api/v1/admin/megamenu/menus/${encodeURIComponent(id)}/bindings/${encodeURIComponent(salesChannelId)}/${encodeURIComponent(language)}`);
|
|
34
|
+
},
|
|
35
|
+
async activate(id, body) {
|
|
36
|
+
const out = await apiClient.post(`/api/v1/admin/megamenu/menus/${encodeURIComponent(id)}/activate`, body);
|
|
37
|
+
return out.data;
|
|
38
|
+
},
|
|
39
|
+
async deactivate(id, body) {
|
|
40
|
+
await apiClient.post(`/api/v1/admin/megamenu/menus/${encodeURIComponent(id)}/deactivate`, body);
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=megamenu-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"megamenu-client.js","sourceRoot":"","sources":["../../../src/admin/api/megamenu-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AA8B3D,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,SAAS;QACP,OAAO,SAAS,CAAC,GAAG,CAAoB,8BAA8B,CAAC,CAAC;IAC1E,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,IAA2B;QAC1C,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,IAAI,CAA2B,8BAA8B,EAAE,IAAI,CAAC,CAAC;QACjG,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,CAC7B,gCAAgC,kBAAkB,CAAC,EAAE,CAAC,EAAE,CACzD,CAAC;QACF,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,EAAU,EAAE,IAA0B;QACpD,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,KAAK,CAC/B,gCAAgC,kBAAkB,CAAC,EAAE,CAAC,EAAE,EACxD,IAAI,CACL,CAAC;QACF,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAU;QACzB,MAAM,SAAS,CAAC,MAAM,CAAC,gCAAgC,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACnF,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,EAAU,EACV,IAAqB;QAErB,OAAO,SAAS,CAAC,GAAG,CAGjB,gCAAgC,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC3E,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,EAAU;QAC3B,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,CAC7B,gCAAgC,kBAAkB,CAAC,EAAE,CAAC,WAAW,CAClE,CAAC;QACF,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,IAAuB;QAClD,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,IAAI,CAC9B,gCAAgC,kBAAkB,CAAC,EAAE,CAAC,WAAW,EACjE,IAAI,CACL,CAAC;QACF,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,EAAU,EAAE,cAAsB,EAAE,QAAgB;QACtE,MAAM,SAAS,CAAC,MAAM,CACpB,gCAAgC,kBAAkB,CAAC,EAAE,CAAC,aAAa,kBAAkB,CAAC,cAAc,CAAC,IAAI,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CACxI,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,EAAU,EAAE,IAA4B;QACrD,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,IAAI,CAC9B,gCAAgC,kBAAkB,CAAC,EAAE,CAAC,WAAW,EACjE,IAAI,CACL,CAAC;QACF,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,IAA4B;QACvD,MAAM,SAAS,CAAC,IAAI,CAAC,gCAAgC,kBAAkB,CAAC,EAAE,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IAClG,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { MegamenuBinding } from '@endora-commerce/contracts';
|
|
3
|
+
interface BindingsPanelProps {
|
|
4
|
+
menuId: string;
|
|
5
|
+
bindings: MegamenuBinding[];
|
|
6
|
+
onChanged: () => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function BindingsPanel({ menuId, bindings, onChanged }: BindingsPanelProps): ReactNode;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=BindingsPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BindingsPanel.d.ts","sourceRoot":"","sources":["../../../src/admin/components/BindingsPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAErE,OAAO,KAAK,EACV,eAAe,EAGhB,MAAM,4BAA4B,CAAC;AAOpC,UAAU,kBAAkB;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AASD,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,kBAAkB,GAAG,SAAS,CA2N5F"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
3
|
+
import { CheckCircle2, Circle, Trash2 } from 'lucide-react';
|
|
4
|
+
import { Alert, AlertDescription, Badge, Button, Select, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@endora-commerce/admin-kit/ui';
|
|
5
|
+
import { useTranslation } from '@endora-commerce/admin-kit/i18n';
|
|
6
|
+
import { apiClient } from '@endora-commerce/admin-kit/lib';
|
|
7
|
+
import { megamenuClient } from '../api/megamenu-client.js';
|
|
8
|
+
export function BindingsPanel({ menuId, bindings, onChanged }) {
|
|
9
|
+
const t = useTranslation('megamenu');
|
|
10
|
+
const [channels, setChannels] = useState([]);
|
|
11
|
+
const [pickedChannelId, setPickedChannelId] = useState('');
|
|
12
|
+
const [pickedLanguage, setPickedLanguage] = useState('');
|
|
13
|
+
const [pickedChannelLanguages, setPickedChannelLanguages] = useState([]);
|
|
14
|
+
const [error, setError] = useState(null);
|
|
15
|
+
const [busy, setBusy] = useState(false);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
apiClient
|
|
18
|
+
.get('/api/v1/admin/sales-channels?pageSize=100')
|
|
19
|
+
.then((res) => setChannels(res.items ?? []))
|
|
20
|
+
.catch((err) => setError(err instanceof Error ? err.message : String(err)));
|
|
21
|
+
}, []);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (!pickedChannelId) {
|
|
24
|
+
setPickedChannelLanguages([]);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const channel = channels.find((c) => c.id === pickedChannelId);
|
|
28
|
+
if (!channel)
|
|
29
|
+
return;
|
|
30
|
+
apiClient
|
|
31
|
+
.get(`/api/v1/admin/sales-channels/${encodeURIComponent(channel.code)}`)
|
|
32
|
+
.then((res) => setPickedChannelLanguages(res.data.languages))
|
|
33
|
+
.catch((err) => setError(err instanceof Error ? err.message : String(err)));
|
|
34
|
+
}, [channels, pickedChannelId]);
|
|
35
|
+
const channelById = useMemo(() => new Map(channels.map((c) => [c.id, c])), [channels]);
|
|
36
|
+
const availableLanguages = pickedChannelLanguages;
|
|
37
|
+
const addBinding = async () => {
|
|
38
|
+
if (!pickedChannelId || !pickedLanguage)
|
|
39
|
+
return;
|
|
40
|
+
setBusy(true);
|
|
41
|
+
setError(null);
|
|
42
|
+
try {
|
|
43
|
+
await megamenuClient.addBinding(menuId, {
|
|
44
|
+
salesChannelId: pickedChannelId,
|
|
45
|
+
language: pickedLanguage,
|
|
46
|
+
});
|
|
47
|
+
setPickedChannelId('');
|
|
48
|
+
setPickedLanguage('');
|
|
49
|
+
onChanged();
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
setBusy(false);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const remove = async (binding) => {
|
|
59
|
+
setBusy(true);
|
|
60
|
+
setError(null);
|
|
61
|
+
try {
|
|
62
|
+
await megamenuClient.removeBinding(menuId, binding.salesChannelId, binding.language);
|
|
63
|
+
onChanged();
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
setBusy(false);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
const activate = async (binding) => {
|
|
73
|
+
setBusy(true);
|
|
74
|
+
setError(null);
|
|
75
|
+
try {
|
|
76
|
+
const result = await megamenuClient.activate(menuId, {
|
|
77
|
+
salesChannelId: binding.salesChannelId,
|
|
78
|
+
language: binding.language,
|
|
79
|
+
});
|
|
80
|
+
if (result.previouslyActive) {
|
|
81
|
+
// Surface the swap so the admin knows what happened. A modal
|
|
82
|
+
// would be nicer; an alert keeps the surface light.
|
|
83
|
+
// eslint-disable-next-line no-alert
|
|
84
|
+
window.alert(t('bindings.activatedWithPrevious', { name: result.previouslyActive.name }));
|
|
85
|
+
}
|
|
86
|
+
onChanged();
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
setBusy(false);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
const deactivate = async (binding) => {
|
|
96
|
+
setBusy(true);
|
|
97
|
+
setError(null);
|
|
98
|
+
try {
|
|
99
|
+
await megamenuClient.deactivate(menuId, {
|
|
100
|
+
salesChannelId: binding.salesChannelId,
|
|
101
|
+
language: binding.language,
|
|
102
|
+
});
|
|
103
|
+
onChanged();
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
setBusy(false);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
return (_jsxs("div", { className: "space-y-3", children: [error ? (_jsx(Alert, { variant: "destructive", children: _jsx(AlertDescription, { children: error }) })) : null, _jsxs("div", { className: "grid grid-cols-12 gap-2", children: [_jsxs(Select, { className: "col-span-5", value: pickedChannelId, onChange: (event) => {
|
|
113
|
+
setPickedChannelId(event.target.value);
|
|
114
|
+
setPickedLanguage('');
|
|
115
|
+
}, disabled: busy, children: [_jsx("option", { value: "", children: t('bindings.salesChannelPlaceholder') }), channels.map((channel) => (_jsx("option", { value: channel.id, children: channel.code }, channel.id)))] }), _jsxs(Select, { className: "col-span-4", value: pickedLanguage, onChange: (event) => setPickedLanguage(event.target.value), disabled: busy || !pickedChannelId, children: [_jsx("option", { value: "", children: t('bindings.languagePlaceholder') }), availableLanguages.map((lang) => (_jsx("option", { value: lang, children: lang }, lang)))] }), _jsx(Button, { type: "button", className: "col-span-3", onClick: () => void addBinding(), disabled: busy || !pickedChannelId || !pickedLanguage, children: t('bindings.add') })] }), bindings.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: t('bindings.empty') })) : (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: t('columns.channel') }), _jsx(TableHead, { children: t('columns.language') }), _jsx(TableHead, { children: t('columns.active') }), _jsx(TableHead, { className: "text-right", children: t('columns.actions') })] }) }), _jsx(TableBody, { children: bindings.map((binding) => {
|
|
116
|
+
const channel = channelById.get(binding.salesChannelId);
|
|
117
|
+
return (_jsxs(TableRow, { children: [_jsx(TableCell, { className: "font-mono text-xs", children: channel?.code ?? binding.salesChannelId }), _jsx(TableCell, { className: "font-mono text-xs", children: binding.language }), _jsx(TableCell, { children: binding.active ? (_jsxs(Badge, { children: [_jsx(CheckCircle2, { className: "mr-1 h-3 w-3" }), " ", t('state.active')] })) : (_jsxs(Badge, { variant: "outline", children: [_jsx(Circle, { className: "mr-1 h-3 w-3" }), " ", t('state.staged')] })) }), _jsxs(TableCell, { className: "space-x-2 text-right", children: [binding.active ? (_jsx(Button, { size: "sm", variant: "outline", onClick: () => void deactivate(binding), disabled: busy, children: t('bindings.deactivate') })) : (_jsx(Button, { size: "sm", onClick: () => void activate(binding), disabled: busy, children: t('bindings.activate') })), _jsx(Button, { size: "sm", variant: "ghost", onClick: () => void remove(binding), disabled: busy, children: _jsx(Trash2, { className: "h-4 w-4" }) })] })] }, `${binding.salesChannelId}-${binding.language}`));
|
|
118
|
+
}) })] }))] }));
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=BindingsPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BindingsPanel.js","sourceRoot":"","sources":["../../../src/admin/components/BindingsPanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { MegamenuItem, MegamenuItemKind } from '@endora-commerce/contracts';
|
|
3
|
+
export type IndexedItem = MegamenuItem & {
|
|
4
|
+
id: string;
|
|
5
|
+
parentId: string | null;
|
|
6
|
+
};
|
|
7
|
+
interface MenuItemConfigPanelProps {
|
|
8
|
+
item: IndexedItem | null;
|
|
9
|
+
languages: string[];
|
|
10
|
+
onChange: (next: IndexedItem) => void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Kind-driven form. The same component covers every menu item kind
|
|
14
|
+
* (`category-link`, `cms-page-link`, `external-link`, `button`, `asset`,
|
|
15
|
+
* `cms-block-embed`); fields swap based on `item.kind`. Heavy validation
|
|
16
|
+
* (target existence, asset kind match, language-in-channel-scope) lives
|
|
17
|
+
* server-side — this surface only collects raw values.
|
|
18
|
+
*/
|
|
19
|
+
export declare function MenuItemConfigPanel({ item, languages, onChange, }: MenuItemConfigPanelProps): ReactNode;
|
|
20
|
+
export declare function defaultTargetFor(kind: MegamenuItemKind): Record<string, unknown>;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=MenuItemConfigPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MenuItemConfigPanel.d.ts","sourceRoot":"","sources":["../../../src/admin/components/MenuItemConfigPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAKjF,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAEjF,UAAU,wBAAwB;IAChC,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;CACvC;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,SAAS,EACT,QAAQ,GACT,EAAE,wBAAwB,GAAG,SAAS,CA8EtC;AA0HD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAehF"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { Alert, AlertDescription, Input, Label, Select } from '@endora-commerce/admin-kit/ui';
|
|
4
|
+
import { CategorySelect, CmsPagePicker, CmsBlockPicker, AssetFieldPicker } from '@endora-commerce/admin-kit/components';
|
|
5
|
+
import { useTranslation } from '@endora-commerce/admin-kit/i18n';
|
|
6
|
+
/**
|
|
7
|
+
* Kind-driven form. The same component covers every menu item kind
|
|
8
|
+
* (`category-link`, `cms-page-link`, `external-link`, `button`, `asset`,
|
|
9
|
+
* `cms-block-embed`); fields swap based on `item.kind`. Heavy validation
|
|
10
|
+
* (target existence, asset kind match, language-in-channel-scope) lives
|
|
11
|
+
* server-side — this surface only collects raw values.
|
|
12
|
+
*/
|
|
13
|
+
export function MenuItemConfigPanel({ item, languages, onChange, }) {
|
|
14
|
+
const t = useTranslation('megamenu');
|
|
15
|
+
const [error, setError] = useState(null);
|
|
16
|
+
const setLabel = (lang, value) => {
|
|
17
|
+
if (!item)
|
|
18
|
+
return;
|
|
19
|
+
onChange({ ...item, labels: { ...item.labels, [lang]: value } });
|
|
20
|
+
};
|
|
21
|
+
const setTarget = (next) => {
|
|
22
|
+
if (!item)
|
|
23
|
+
return;
|
|
24
|
+
onChange({ ...item, target: { ...item.target, ...next } });
|
|
25
|
+
};
|
|
26
|
+
const setKind = (kind) => {
|
|
27
|
+
if (!item)
|
|
28
|
+
return;
|
|
29
|
+
onChange({
|
|
30
|
+
...item,
|
|
31
|
+
kind,
|
|
32
|
+
target: defaultTargetFor(kind),
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
setError(null);
|
|
37
|
+
}, [item?.id]);
|
|
38
|
+
if (!item) {
|
|
39
|
+
return (_jsx("p", { className: "px-2 py-6 text-sm text-muted-foreground", children: t('itemConfig.empty') }));
|
|
40
|
+
}
|
|
41
|
+
return (_jsxs("div", { className: "space-y-4", children: [error ? (_jsx(Alert, { variant: "destructive", children: _jsx(AlertDescription, { children: error }) })) : null, _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: t('fields.kind') }), _jsxs(Select, { value: item.kind, onChange: (event) => setKind(event.target.value), children: [_jsx("option", { value: "category-link", children: t('itemKind.categoryLink') }), _jsx("option", { value: "cms-page-link", children: t('itemKind.cmsPageLink') }), _jsx("option", { value: "external-link", children: t('itemKind.externalLink') }), _jsx("option", { value: "button", children: t('itemKind.button') }), _jsx("option", { value: "asset", children: t('itemKind.asset') }), _jsx("option", { value: "cms-block-embed", children: t('itemKind.cmsBlockEmbed') })] })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: t('fields.labelsPerLanguage') }), languages.length === 0 ? (_jsx("p", { className: "text-xs text-muted-foreground", children: t('itemConfig.addBindingFirst') })) : null, languages.map((lang) => (_jsxs("div", { className: "grid grid-cols-12 items-center gap-2", children: [_jsx("span", { className: "col-span-2 font-mono text-xs text-muted-foreground", children: lang }), _jsx(Input, { className: "col-span-10", value: item.labels[lang] ?? '', onChange: (event) => setLabel(lang, event.target.value), placeholder: t('itemConfig.labelPlaceholder', { language: lang }) })] }, lang)))] }), _jsx(KindSpecificFields, { item: item, setTarget: setTarget })] }));
|
|
42
|
+
}
|
|
43
|
+
function KindSpecificFields({ item, setTarget, }) {
|
|
44
|
+
const t = useTranslation('megamenu');
|
|
45
|
+
const target = item.target;
|
|
46
|
+
switch (item.kind) {
|
|
47
|
+
case 'category-link':
|
|
48
|
+
return (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: t('fields.categoryId') }), _jsx(CategorySelect, { value: typeof target.categoryId === 'string' && target.categoryId ? target.categoryId : null, onChange: (v) => setTarget({ categoryId: v ?? '' }) })] }));
|
|
49
|
+
case 'cms-page-link':
|
|
50
|
+
return (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: t('fields.cmsPageId') }), _jsx(CmsPagePicker, { value: typeof target.pageId === 'string' && target.pageId ? target.pageId : null, onChange: (v) => setTarget({ pageId: v ?? '' }) })] }));
|
|
51
|
+
case 'external-link':
|
|
52
|
+
return (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: t('fields.url') }), _jsx(Input, { value: typeof target.url === 'string' ? target.url : '', onChange: (event) => setTarget({ url: event.target.value }), placeholder: t('placeholders.externalUrl') })] }));
|
|
53
|
+
case 'button':
|
|
54
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: t('fields.linkTarget') }), _jsx(Input, { value: typeof target.url === 'string' ? target.url : '', onChange: (event) => setTarget({ url: event.target.value }), placeholder: "/promotions" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: t('fields.variant') }), _jsxs(Select, { value: typeof target.variant === 'string' ? target.variant : 'primary', onChange: (event) => setTarget({ variant: event.target.value }), children: [_jsx("option", { value: "primary", children: t('variant.primary') }), _jsx("option", { value: "secondary", children: t('variant.secondary') }), _jsx("option", { value: "ghost", children: t('variant.ghost') })] })] })] }));
|
|
55
|
+
case 'asset':
|
|
56
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: t('fields.assetId') }), _jsx(AssetFieldPicker, { value: typeof target.assetId === 'string' ? target.assetId : '', onChange: (id) => setTarget({ assetId: id }), acceptMimePrefix: target.kind === 'video' ? 'video/' : 'image/', allowUpload: true })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: t('fields.kind') }), _jsxs(Select, { value: typeof target.kind === 'string' ? target.kind : 'image', onChange: (event) => setTarget({ kind: event.target.value }), children: [_jsx("option", { value: "image", children: t('assetKind.image') }), _jsx("option", { value: "video", children: t('assetKind.video') })] })] })] }));
|
|
57
|
+
case 'cms-block-embed':
|
|
58
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: t('fields.cmsBlockId') }), _jsx(CmsBlockPicker, { value: typeof target.blockId === 'string' && target.blockId ? target.blockId : null, onChange: (v) => setTarget({ blockId: v ?? '' }) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: t('fields.embedSide') }), _jsxs(Select, { value: typeof target.embedSide === 'string' ? target.embedSide : 'right', onChange: (event) => setTarget({ embedSide: event.target.value }), children: [_jsx("option", { value: "left", children: t('side.left') }), _jsx("option", { value: "right", children: t('side.right') })] })] })] }));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export function defaultTargetFor(kind) {
|
|
62
|
+
switch (kind) {
|
|
63
|
+
case 'category-link':
|
|
64
|
+
return { categoryId: '' };
|
|
65
|
+
case 'cms-page-link':
|
|
66
|
+
return { pageId: '' };
|
|
67
|
+
case 'external-link':
|
|
68
|
+
return { url: 'https://' };
|
|
69
|
+
case 'button':
|
|
70
|
+
return { url: '/', variant: 'primary' };
|
|
71
|
+
case 'asset':
|
|
72
|
+
return { assetId: '', kind: 'image' };
|
|
73
|
+
case 'cms-block-embed':
|
|
74
|
+
return { blockId: '', embedSide: 'right' };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=MenuItemConfigPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MenuItemConfigPanel.js","sourceRoot":"","sources":["../../../src/admin/components/MenuItemConfigPanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { MegamenuItem } from '@endora-commerce/contracts';
|
|
3
|
+
interface MenuItemTreeProps {
|
|
4
|
+
items: MegamenuItem[];
|
|
5
|
+
selectedItemId: string | null;
|
|
6
|
+
onSelect: (id: string | null) => void;
|
|
7
|
+
onMove: (id: string, direction: 'up' | 'down') => void;
|
|
8
|
+
onDelete: (id: string) => void;
|
|
9
|
+
onAddChild: (parentId: string | null) => void;
|
|
10
|
+
}
|
|
11
|
+
export declare function MenuItemTree({ items, selectedItemId, onSelect, onMove, onDelete, onAddChild, }: MenuItemTreeProps): ReactNode;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=MenuItemTree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MenuItemTree.d.ts","sourceRoot":"","sources":["../../../src/admin/components/MenuItemTree.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEhD,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,4BAA4B,CAAC;AAIjF,UAAU,iBAAiB;IACzB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACtC,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC;IACvD,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CAC/C;AAyBD,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,cAAc,EACd,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,UAAU,GACX,EAAE,iBAAiB,GAAG,SAAS,CAuG/B"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { ArrowDown, ArrowUp, ChevronDown, ChevronRight, GripVertical, Plus, Trash2 } from 'lucide-react';
|
|
4
|
+
import { Badge, Button } from '@endora-commerce/admin-kit/ui';
|
|
5
|
+
import { useTranslation } from '@endora-commerce/admin-kit/i18n';
|
|
6
|
+
function kindLabel(t, kind) {
|
|
7
|
+
return t(`treeKind.${kind}`);
|
|
8
|
+
}
|
|
9
|
+
function indexItems(items) {
|
|
10
|
+
return items
|
|
11
|
+
.filter((item) => typeof item.id === 'string')
|
|
12
|
+
.map((item) => ({ ...item, parentId: item.parentId ?? null }));
|
|
13
|
+
}
|
|
14
|
+
function pickLabel(labels, fallback) {
|
|
15
|
+
if (!labels)
|
|
16
|
+
return fallback;
|
|
17
|
+
const langs = Object.keys(labels);
|
|
18
|
+
if (langs.length === 0)
|
|
19
|
+
return fallback;
|
|
20
|
+
return labels[langs[0]] ?? fallback;
|
|
21
|
+
}
|
|
22
|
+
export function MenuItemTree({ items, selectedItemId, onSelect, onMove, onDelete, onAddChild, }) {
|
|
23
|
+
const t = useTranslation('megamenu');
|
|
24
|
+
const indexed = useMemo(() => indexItems(items), [items]);
|
|
25
|
+
const byParent = useMemo(() => {
|
|
26
|
+
const map = new Map();
|
|
27
|
+
for (const item of indexed) {
|
|
28
|
+
const list = map.get(item.parentId) ?? [];
|
|
29
|
+
list.push(item);
|
|
30
|
+
map.set(item.parentId, list);
|
|
31
|
+
}
|
|
32
|
+
for (const list of map.values()) {
|
|
33
|
+
list.sort((a, b) => a.position - b.position);
|
|
34
|
+
}
|
|
35
|
+
return map;
|
|
36
|
+
}, [indexed]);
|
|
37
|
+
const renderRow = (item, depth) => {
|
|
38
|
+
const children = byParent.get(item.id) ?? [];
|
|
39
|
+
const isSelected = item.id === selectedItemId;
|
|
40
|
+
const hasChildren = children.length > 0;
|
|
41
|
+
return (_jsxs("div", { children: [_jsxs("div", { className: `flex items-center gap-2 rounded px-2 py-1.5 hover:bg-muted ${isSelected ? 'bg-muted/60 ring-1 ring-primary/40' : ''}`, style: { paddingLeft: 8 + depth * 16 }, children: [_jsx(GripVertical, { className: "h-3 w-3 text-muted-foreground" }), hasChildren ? (_jsx(ChevronDown, { className: "h-3 w-3 text-muted-foreground" })) : (_jsx(ChevronRight, { className: "h-3 w-3 text-muted-foreground" })), _jsxs("button", { type: "button", className: "flex-1 truncate text-left text-sm", onClick: () => onSelect(item.id), children: [pickLabel(item.labels, t('tree.noLabel')), _jsx(Badge, { variant: "outline", className: "ml-2 text-[10px] uppercase tracking-wide", children: kindLabel(t, item.kind) })] }), _jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => onMove(item.id, 'up'), title: t('common.moveUp'), children: _jsx(ArrowUp, { className: "h-3 w-3" }) }), _jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => onMove(item.id, 'down'), title: t('common.moveDown'), children: _jsx(ArrowDown, { className: "h-3 w-3" }) }), _jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => onAddChild(item.id), title: t('tree.addChild'), children: _jsx(Plus, { className: "h-3 w-3" }) }), _jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => onDelete(item.id), title: t('tree.deleteItem'), children: _jsx(Trash2, { className: "h-3 w-3" }) })] }), children.map((child) => renderRow(child, depth + 1))] }, item.id));
|
|
42
|
+
};
|
|
43
|
+
const roots = byParent.get(null) ?? [];
|
|
44
|
+
return (_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center justify-between border-b pb-2", children: [_jsx("span", { className: "text-sm font-medium", children: t('tree.title') }), _jsxs(Button, { type: "button", size: "sm", variant: "outline", onClick: () => onAddChild(null), children: [_jsx(Plus, { className: "mr-1 h-3 w-3" }), " ", t('tree.addTopLevel')] })] }), roots.length === 0 ? (_jsx("p", { className: "px-2 py-3 text-sm text-muted-foreground", children: t('tree.empty') })) : (roots.map((root) => renderRow(root, 0)))] }));
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=MenuItemTree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MenuItemTree.js","sourceRoot":"","sources":["../../../src/admin/components/MenuItemTree.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `megamenu`'s admin surface — two routes and one sidebar entry, declared by
|
|
3
|
+
* the module that owns them (feature 091, Phase 4, batch 8;
|
|
4
|
+
* `specs/091-module-owned-admin-surfaces/contracts/admin-contribution.md`).
|
|
5
|
+
*
|
|
6
|
+
* **Its drain is zero and that is a measurement, not luck.** `plan.md`'s table
|
|
7
|
+
* recorded three Group A keys for this module — an asset picker and two CMS
|
|
8
|
+
* pickers — and P2 and P4c between them paid all three, in merge requests of
|
|
9
|
+
* their own. Re-derived on the tree this batch was cut from: `megamenu` has no
|
|
10
|
+
* shard in `backend/scripts/ledgers/cross-module-imports/`, no key in
|
|
11
|
+
* `admin-surface.ts` names one of its files, and no other module's shard names
|
|
12
|
+
* one either. The editor still renders a CMS page picker, a CMS block picker
|
|
13
|
+
* and an asset field picker; all three are `@endora-commerce/admin-kit`'s now,
|
|
14
|
+
* so none of them is a boundary reach.
|
|
15
|
+
*
|
|
16
|
+
* **Two routes, one nav entry, and the second route deliberately has none.**
|
|
17
|
+
* `/megamenu/:id` is the editor a row on `/megamenu` leads to — a nav entry is
|
|
18
|
+
* a landing surface, and `registryCrumbs` derives the editor's trail from this
|
|
19
|
+
* entry's own `to` because it matches anything beneath it.
|
|
20
|
+
*
|
|
21
|
+
* **The palette action is already the manifest's** (`edit-megamenu`), so
|
|
22
|
+
* nothing about the ⌘K surface moves here; the sidebar row is the whole of
|
|
23
|
+
* what this file adds.
|
|
24
|
+
*
|
|
25
|
+
* **This entry exports data and nothing else** (R2); both components are
|
|
26
|
+
* dynamic-import factories (R6), so the editor's chunk is not downloaded by an
|
|
27
|
+
* operator who only lists menus.
|
|
28
|
+
*/
|
|
29
|
+
import type { AdminContributions } from '@endora-commerce/admin-kit/contributions';
|
|
30
|
+
export declare const contributions: AdminContributions;
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAKnF,eAAO,MAAM,aAAa,EAAE,kBA2C3B,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** The module's landing route: the menu list. */
|
|
2
|
+
const LIST_ROUTE = '/megamenu';
|
|
3
|
+
export const contributions = {
|
|
4
|
+
routes: [
|
|
5
|
+
{
|
|
6
|
+
path: LIST_ROUTE,
|
|
7
|
+
component: () => import('./pages/MegamenuListPage.js'),
|
|
8
|
+
// `requireAdmin('megamenu.read')` on `GET /api/v1/admin/megamenu`, which
|
|
9
|
+
// the list calls on mount.
|
|
10
|
+
requiredPermission: 'megamenu.read',
|
|
11
|
+
index: true,
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
path: '/megamenu/:id',
|
|
15
|
+
component: () => import('./pages/MegamenuEditor.js'),
|
|
16
|
+
// The editor's own `GET /api/v1/admin/megamenu/:id` is read-gated: the
|
|
17
|
+
// write code would hide the screen from a read-only operator who can
|
|
18
|
+
// legitimately open it and be refused on save, which is issue #232's
|
|
19
|
+
// finding. The palette action declares `megamenu.write` because it
|
|
20
|
+
// advertises *editing*, and `check:action-route-permissions` holds it to
|
|
21
|
+
// `/megamenu`, whose route requirement is the read code — sufficiency,
|
|
22
|
+
// not equality, is what that check asks for.
|
|
23
|
+
requiredPermission: 'megamenu.read',
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
nav: [
|
|
27
|
+
{
|
|
28
|
+
to: LIST_ROUTE,
|
|
29
|
+
// Module-relative (R8), out of `packages/modules/megamenu/i18n/`. It was
|
|
30
|
+
// `appShell.nav.megamenu` in the shared `_i18n` bundle.
|
|
31
|
+
labelKey: 'nav.megamenu.label',
|
|
32
|
+
// The glyph the hand-written NAV entry carried. The palette action
|
|
33
|
+
// declares `Menu`, which is the icon for the *action*; the sidebar row's
|
|
34
|
+
// is the one an operator already sees and is kept rather than unified,
|
|
35
|
+
// because unifying it would be a visible change bought for nothing.
|
|
36
|
+
icon: 'Newspaper',
|
|
37
|
+
section: 'content',
|
|
38
|
+
// Fifth of eight in the hand-written *Content* table, after the four
|
|
39
|
+
// `/cms/*` rows and before the three `/blog/*` ones. Both neighbours are
|
|
40
|
+
// still the host's, so this appends after all of them; the weight is what
|
|
41
|
+
// restores the position once `cms` and `blog` convert.
|
|
42
|
+
weight: 500,
|
|
43
|
+
requiredPermission: 'megamenu.read',
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AA8BA,iDAAiD;AACjD,MAAM,UAAU,GAAG,WAAW,CAAC;AAE/B,MAAM,CAAC,MAAM,aAAa,GAAuB;IAC/C,MAAM,EAAE;QACN;YACE,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,6BAA6B,CAAC;YACtD,yEAAyE;YACzE,2BAA2B;YAC3B,kBAAkB,EAAE,eAAe;YACnC,KAAK,EAAE,IAAI;SACZ;QACD;YACE,IAAI,EAAE,eAAe;YACrB,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,2BAA2B,CAAC;YACpD,uEAAuE;YACvE,qEAAqE;YACrE,qEAAqE;YACrE,mEAAmE;YACnE,yEAAyE;YACzE,uEAAuE;YACvE,6CAA6C;YAC7C,kBAAkB,EAAE,eAAe;SACpC;KACF;IACD,GAAG,EAAE;QACH;YACE,EAAE,EAAE,UAAU;YACd,yEAAyE;YACzE,wDAAwD;YACxD,QAAQ,EAAE,oBAAoB;YAC9B,mEAAmE;YACnE,yEAAyE;YACzE,uEAAuE;YACvE,oEAAoE;YACpE,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,SAAS;YAClB,qEAAqE;YACrE,yEAAyE;YACzE,0EAA0E;YAC1E,uDAAuD;YACvD,MAAM,EAAE,GAAG;YACX,kBAAkB,EAAE,eAAe;SACpC;KACF;CACF,CAAC"}
|