@endora-commerce/mod-sales-channels 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 +67 -0
- package/dist/admin/api/sales-channels-client.d.ts +69 -0
- package/dist/admin/api/sales-channels-client.d.ts.map +1 -0
- package/dist/admin/api/sales-channels-client.js +74 -0
- package/dist/admin/api/sales-channels-client.js.map +1 -0
- package/dist/admin/components/ChannelIdentityForm.d.ts +24 -0
- package/dist/admin/components/ChannelIdentityForm.d.ts.map +1 -0
- package/dist/admin/components/ChannelIdentityForm.js +147 -0
- package/dist/admin/components/ChannelIdentityForm.js.map +1 -0
- package/dist/admin/components/DefaultChannelBadge.d.ts +21 -0
- package/dist/admin/components/DefaultChannelBadge.d.ts.map +1 -0
- package/dist/admin/components/DefaultChannelBadge.js +26 -0
- package/dist/admin/components/DefaultChannelBadge.js.map +1 -0
- package/dist/admin/components/EntityChannelMembership.d.ts +52 -0
- package/dist/admin/components/EntityChannelMembership.d.ts.map +1 -0
- package/dist/admin/components/EntityChannelMembership.js +98 -0
- package/dist/admin/components/EntityChannelMembership.js.map +1 -0
- package/dist/admin/index.d.ts +44 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +148 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/pages/SalesChannelEditPage.d.ts +25 -0
- package/dist/admin/pages/SalesChannelEditPage.d.ts.map +1 -0
- package/dist/admin/pages/SalesChannelEditPage.js +185 -0
- package/dist/admin/pages/SalesChannelEditPage.js.map +1 -0
- package/dist/admin/pages/SalesChannelsListPage.d.ts +25 -0
- package/dist/admin/pages/SalesChannelsListPage.d.ts.map +1 -0
- package/dist/admin/pages/SalesChannelsListPage.js +91 -0
- package/dist/admin/pages/SalesChannelsListPage.js.map +1 -0
- package/dist/admin/zones/OrganizationChannelMembership.d.ts +34 -0
- package/dist/admin/zones/OrganizationChannelMembership.d.ts.map +1 -0
- package/dist/admin/zones/OrganizationChannelMembership.js +11 -0
- package/dist/admin/zones/OrganizationChannelMembership.js.map +1 -0
- package/dist/admin/zones/ProductChannelMembership.d.ts +23 -0
- package/dist/admin/zones/ProductChannelMembership.d.ts.map +1 -0
- package/dist/admin/zones/ProductChannelMembership.js +11 -0
- package/dist/admin/zones/ProductChannelMembership.js.map +1 -0
- package/dist/backend/commands/set-default.command.d.ts +53 -0
- package/dist/backend/commands/set-default.command.d.ts.map +1 -0
- package/dist/backend/commands/set-default.command.js +87 -0
- package/dist/backend/commands/set-default.command.js.map +1 -0
- package/dist/backend/index.d.ts +71 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +81 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/routes.admin.d.ts +12 -0
- package/dist/backend/routes.admin.d.ts.map +1 -0
- package/dist/backend/routes.admin.js +302 -0
- package/dist/backend/routes.admin.js.map +1 -0
- package/dist/backend/routes.storefront.d.ts +36 -0
- package/dist/backend/routes.storefront.d.ts.map +1 -0
- package/dist/backend/routes.storefront.js +58 -0
- package/dist/backend/routes.storefront.js.map +1 -0
- package/dist/backend/services/index.d.ts +2 -0
- package/dist/backend/services/index.d.ts.map +1 -0
- package/dist/backend/services/index.js +2 -0
- package/dist/backend/services/index.js.map +1 -0
- package/dist/backend/services/sales-channel-attribution-registry.d.ts +28 -0
- package/dist/backend/services/sales-channel-attribution-registry.d.ts.map +1 -0
- package/dist/backend/services/sales-channel-attribution-registry.js +50 -0
- package/dist/backend/services/sales-channel-attribution-registry.js.map +1 -0
- package/dist/backend/services/sales-channels.service.d.ts +247 -0
- package/dist/backend/services/sales-channels.service.d.ts.map +1 -0
- package/dist/backend/services/sales-channels.service.js +535 -0
- package/dist/backend/services/sales-channels.service.js.map +1 -0
- package/dist/manifest.d.ts +185 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +204 -0
- package/dist/manifest.js.map +1 -0
- package/docs/sales_channels/admin-usage.md +77 -0
- package/docs/sales_channels/developer-guide.md +107 -0
- package/docs/sales_channels/index.md +95 -0
- package/i18n/en.json +75 -0
- package/i18n/pl.json +75 -0
- package/package.json +88 -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,67 @@
|
|
|
1
|
+
# sales_channels
|
|
2
|
+
|
|
3
|
+
Owns the **admin surface** for sales channels — CRUD, lifecycle and the
|
|
4
|
+
membership routes — and the nine `sales_channel_*` membership bridge tables and
|
|
5
|
+
their migration. A single deployment serves multiple channels; catalog
|
|
6
|
+
visibility, related/cross-sell/up-sell links, promotions/coupons, pricing, CMS,
|
|
7
|
+
mega-menu and blog are all scoped to the request's channel through those bridges.
|
|
8
|
+
|
|
9
|
+
## What lives in the kernel (feature 072, T019)
|
|
10
|
+
|
|
11
|
+
Channel *resolution* is a platform concern, not a module one: the resolution
|
|
12
|
+
order is a refusal contract (Constitution XII) and 49 call sites read the
|
|
13
|
+
resolved channel. So the `SalesChannel` entity, the resolver middleware and
|
|
14
|
+
resolver service, `SalesChannelMembershipService`, the cache and its invalidator
|
|
15
|
+
and `DefaultChannelReconciler` all live under
|
|
16
|
+
`backend/src/kernel/sales-channels/`. This module keeps
|
|
17
|
+
`services/sales-channels.service.ts` (admin CRUD, zero external importers) and
|
|
18
|
+
`routes.admin.ts`.
|
|
19
|
+
|
|
20
|
+
Nothing about the resolution order or the refusal behaviour changed with the
|
|
21
|
+
move; a module may import the kernel freely.
|
|
22
|
+
|
|
23
|
+
## The single resolution contract (feature 053 / FR-002)
|
|
24
|
+
|
|
25
|
+
The **canonical resolver middleware**
|
|
26
|
+
(`kernel/sales-channels/sales-channel-resolver.middleware.ts`)
|
|
27
|
+
runs as a Fastify `onRequest` hook on every `/api/v1/*` request (bypassing
|
|
28
|
+
`/api/v1/_health`). It resolves the channel **once**, in this order:
|
|
29
|
+
|
|
30
|
+
1. `X-Sales-Channel: <code>` header
|
|
31
|
+
2. `?salesChannel=<code>` query — storefront only; ignored on `/api/v1/admin/*`
|
|
32
|
+
3. `SALES_CHANNEL_HOST_MAP` host mapping
|
|
33
|
+
4. the **system-default** channel (`systemDefault = true`) — the single
|
|
34
|
+
empty-channel fallback (the legacy `isPublic` fallback is retired)
|
|
35
|
+
|
|
36
|
+
It validates existence + active state (unknown → `UNKNOWN_SALES_CHANNEL`,
|
|
37
|
+
inactive → `INACTIVE_SALES_CHANNEL`), attaches the result to
|
|
38
|
+
`request.salesChannel` (a `CachedChannel`, backed by the LRU+Redis cache), and
|
|
39
|
+
echoes `X-Sales-Channel: <resolvedCode>` on the response.
|
|
40
|
+
|
|
41
|
+
### Consuming the channel — the one rule
|
|
42
|
+
|
|
43
|
+
Storefront-facing modules **MUST** read `request.salesChannel` (via
|
|
44
|
+
`getResolvedChannel(request)`) and **MUST NOT** re-parse the header/query/host or
|
|
45
|
+
re-query `SalesChannel` to derive the request channel. Routes hand services the
|
|
46
|
+
resolved channel object; services never re-resolve. Reading `channel.isPublic`
|
|
47
|
+
(price visibility) off the already-resolved channel is fine — it is a display
|
|
48
|
+
flag, not resolution.
|
|
49
|
+
|
|
50
|
+
This invariant is enforced by `backend/scripts/check-channel-resolution.ts`
|
|
51
|
+
(CI `--enforce`). Bridge membership is read only through
|
|
52
|
+
`SalesChannelMembershipService`; `check:module-boundary`'s `sql` predicate is what
|
|
53
|
+
refuses a raw `sales_channel_*` statement (D-87).
|
|
54
|
+
|
|
55
|
+
Full contract + consumption guide: `specs/053-sales-channel-scoping-unification/`
|
|
56
|
+
(`contracts/resolved-channel-context.md`, `contracts/header-dialect.md`,
|
|
57
|
+
`quickstart.md`).
|
|
58
|
+
|
|
59
|
+
### Notes
|
|
60
|
+
|
|
61
|
+
- The `X-Sales-Channel-Id` (UUID) header is **removed** — `X-Sales-Channel`
|
|
62
|
+
(code) is the only dialect.
|
|
63
|
+
- Activation/deactivation invalidates the resolver cache through the
|
|
64
|
+
`sales_channels.lifecycle_changed` pub/sub, so a channel goes offline on every
|
|
65
|
+
surface within the cache TTL (one cache, all surfaces).
|
|
66
|
+
- Carts/quotes are assigned the system-default channel at creation, so no
|
|
67
|
+
null-channel cart reaches pricing/checkout.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { ChannelMemberEntityType, SalesChannelCreateBody, SalesChannelDetail, SalesChannelListResponse, SalesChannelSetDefaultResponse, SalesChannelSummary, SalesChannelUpdateBody } from '@endora-commerce/contracts';
|
|
2
|
+
/**
|
|
3
|
+
* Typed wrapper around `/api/v1/admin/sales-channels/*` — feature 005 / T038.
|
|
4
|
+
* Source-of-truth schemas live in `@endora-commerce/contracts`.
|
|
5
|
+
*
|
|
6
|
+
* Optimistic concurrency for PATCH rides on the body's `expectedVersion`
|
|
7
|
+
* field (matches feature 003/004); the response's ETag is also exposed
|
|
8
|
+
* for completeness so a future refactor to `If-Match` is one-line away.
|
|
9
|
+
*/
|
|
10
|
+
export interface ListOptions {
|
|
11
|
+
page?: number;
|
|
12
|
+
pageSize?: number;
|
|
13
|
+
activeOnly?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare const salesChannelsClient: {
|
|
16
|
+
list(options?: ListOptions): Promise<SalesChannelListResponse>;
|
|
17
|
+
getByCode(code: string): Promise<SalesChannelDetail>;
|
|
18
|
+
create(body: SalesChannelCreateBody): Promise<SalesChannelDetail>;
|
|
19
|
+
update(code: string, body: SalesChannelUpdateBody & {
|
|
20
|
+
expectedVersion: number;
|
|
21
|
+
}): Promise<SalesChannelDetail>;
|
|
22
|
+
deactivate(code: string): Promise<SalesChannelDetail>;
|
|
23
|
+
activate(code: string): Promise<SalesChannelDetail>;
|
|
24
|
+
/**
|
|
25
|
+
* Move the system-default flag to this channel (D-51). Promoting the channel
|
|
26
|
+
* that already holds it answers 200 with `changed: false`, so a double click
|
|
27
|
+
* is not an error; an inactive channel is refused with 422
|
|
28
|
+
* `INACTIVE_SALES_CHANNEL`.
|
|
29
|
+
*/
|
|
30
|
+
setDefault(code: string): Promise<SalesChannelSetDefaultResponse>;
|
|
31
|
+
delete(code: string, options?: {
|
|
32
|
+
fallbackToDefault?: boolean;
|
|
33
|
+
}): Promise<void>;
|
|
34
|
+
/** List entity ids of `entityType` that belong to `code`. */
|
|
35
|
+
listEntitiesInChannel(code: string, entityType: ChannelMemberEntityType, options?: {
|
|
36
|
+
page?: number;
|
|
37
|
+
pageSize?: number;
|
|
38
|
+
}): Promise<{
|
|
39
|
+
salesChannelCode: string;
|
|
40
|
+
entityType: ChannelMemberEntityType;
|
|
41
|
+
entityIds: string[];
|
|
42
|
+
page: number;
|
|
43
|
+
pageSize: number;
|
|
44
|
+
total: number;
|
|
45
|
+
}>;
|
|
46
|
+
/** List the channels an entity belongs to. */
|
|
47
|
+
listChannelsForEntity(entityType: ChannelMemberEntityType, entityId: string): Promise<{
|
|
48
|
+
entityType: ChannelMemberEntityType;
|
|
49
|
+
entityId: string;
|
|
50
|
+
channels: SalesChannelSummary[];
|
|
51
|
+
}>;
|
|
52
|
+
/** Idempotent — re-adding an existing membership returns `changed: false`. */
|
|
53
|
+
addEntityToChannel(code: string, entityType: ChannelMemberEntityType, entityId: string): Promise<{
|
|
54
|
+
changed: boolean;
|
|
55
|
+
}>;
|
|
56
|
+
/**
|
|
57
|
+
* Remove a membership. With `fallbackToDefault=false` (default), removing
|
|
58
|
+
* the entity's last channel returns 422 ENTITY_WOULD_HAVE_ZERO_CHANNELS;
|
|
59
|
+
* with `true`, the entity is rebound to the system default in one
|
|
60
|
+
* transaction.
|
|
61
|
+
*/
|
|
62
|
+
removeEntityFromChannel(code: string, entityType: ChannelMemberEntityType, entityId: string, options?: {
|
|
63
|
+
fallbackToDefault?: boolean;
|
|
64
|
+
}): Promise<{
|
|
65
|
+
changed: boolean;
|
|
66
|
+
fallbackAppliedToDefault: boolean;
|
|
67
|
+
}>;
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=sales-channels-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sales-channels-client.d.ts","sourceRoot":"","sources":["../../../src/admin/api/sales-channels-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACtB,kBAAkB,EAClB,wBAAwB,EACxB,8BAA8B,EAC9B,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,4BAA4B,CAAC;AAGpC;;;;;;;GAOG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,mBAAmB;mBAChB,WAAW,GAAQ,OAAO,CAAC,wBAAwB,CAAC;oBAWlD,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;iBAMvC,sBAAsB,GAAG,OAAO,CAAC,kBAAkB,CAAC;iBAKzD,MAAM,QACN,sBAAsB,GAAG;QAAE,eAAe,EAAE,MAAM,CAAA;KAAE,GACzD,OAAO,CAAC,kBAAkB,CAAC;qBAOb,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;mBAOtC,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAOnD;;;;;OAKG;qBACc,MAAM,GAAG,OAAO,CAAC,8BAA8B,CAAC;iBAOpD,MAAM,YAAW;QAAE,iBAAiB,CAAC,EAAE,OAAO,CAAA;KAAE,GAAQ,OAAO,CAAC,IAAI,CAAC;IAWlF,6DAA6D;gCAErD,MAAM,cACA,uBAAuB,YAC1B;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAC5C,OAAO,CAAC;QACT,gBAAgB,EAAE,MAAM,CAAC;QACzB,UAAU,EAAE,uBAAuB,CAAC;QACpC,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IAUF,8CAA8C;sCAEhC,uBAAuB,YACzB,MAAM,GACf,OAAO,CAAC;QACT,UAAU,EAAE,uBAAuB,CAAC;QACpC,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;KACjC,CAAC;IAMF,8EAA8E;6BAEtE,MAAM,cACA,uBAAuB,YACzB,MAAM,GACf,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAOhC;;;;;OAKG;kCAEK,MAAM,cACA,uBAAuB,YACzB,MAAM,YACP;QAAE,iBAAiB,CAAC,EAAE,OAAO,CAAA;KAAE,GACvC,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,wBAAwB,EAAE,OAAO,CAAA;KAAE,CAAC;CAMpE,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { apiClient } from '@endora-commerce/admin-kit/lib';
|
|
2
|
+
export const salesChannelsClient = {
|
|
3
|
+
list(options = {}) {
|
|
4
|
+
const qs = new URLSearchParams();
|
|
5
|
+
if (options.page !== undefined)
|
|
6
|
+
qs.set('page', String(options.page));
|
|
7
|
+
if (options.pageSize !== undefined)
|
|
8
|
+
qs.set('pageSize', String(options.pageSize));
|
|
9
|
+
if (options.activeOnly !== undefined)
|
|
10
|
+
qs.set('activeOnly', String(options.activeOnly));
|
|
11
|
+
const tail = qs.toString();
|
|
12
|
+
return apiClient.get(`/api/v1/admin/sales-channels${tail ? `?${tail}` : ''}`);
|
|
13
|
+
},
|
|
14
|
+
getByCode(code) {
|
|
15
|
+
return apiClient.get(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}`);
|
|
16
|
+
},
|
|
17
|
+
create(body) {
|
|
18
|
+
return apiClient.post('/api/v1/admin/sales-channels', body);
|
|
19
|
+
},
|
|
20
|
+
update(code, body) {
|
|
21
|
+
return apiClient.patch(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}`, body);
|
|
22
|
+
},
|
|
23
|
+
deactivate(code) {
|
|
24
|
+
return apiClient.post(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}/deactivate`, {});
|
|
25
|
+
},
|
|
26
|
+
activate(code) {
|
|
27
|
+
return apiClient.post(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}/activate`, {});
|
|
28
|
+
},
|
|
29
|
+
/**
|
|
30
|
+
* Move the system-default flag to this channel (D-51). Promoting the channel
|
|
31
|
+
* that already holds it answers 200 with `changed: false`, so a double click
|
|
32
|
+
* is not an error; an inactive channel is refused with 422
|
|
33
|
+
* `INACTIVE_SALES_CHANNEL`.
|
|
34
|
+
*/
|
|
35
|
+
setDefault(code) {
|
|
36
|
+
return apiClient.post(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}/set-default`, {});
|
|
37
|
+
},
|
|
38
|
+
delete(code, options = {}) {
|
|
39
|
+
const qs = options.fallbackToDefault
|
|
40
|
+
? `?fallbackToDefault=true`
|
|
41
|
+
: '';
|
|
42
|
+
return apiClient.delete(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}${qs}`);
|
|
43
|
+
},
|
|
44
|
+
// -- Membership routes (Phase 5b) ---------------------------------------
|
|
45
|
+
/** List entity ids of `entityType` that belong to `code`. */
|
|
46
|
+
listEntitiesInChannel(code, entityType, options = {}) {
|
|
47
|
+
const qs = new URLSearchParams();
|
|
48
|
+
if (options.page !== undefined)
|
|
49
|
+
qs.set('page', String(options.page));
|
|
50
|
+
if (options.pageSize !== undefined)
|
|
51
|
+
qs.set('pageSize', String(options.pageSize));
|
|
52
|
+
const tail = qs.toString();
|
|
53
|
+
return apiClient.get(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}/${entityType}${tail ? `?${tail}` : ''}`);
|
|
54
|
+
},
|
|
55
|
+
/** List the channels an entity belongs to. */
|
|
56
|
+
listChannelsForEntity(entityType, entityId) {
|
|
57
|
+
return apiClient.get(`/api/v1/admin/sales-channels/by-entity/${entityType}/${encodeURIComponent(entityId)}`);
|
|
58
|
+
},
|
|
59
|
+
/** Idempotent — re-adding an existing membership returns `changed: false`. */
|
|
60
|
+
addEntityToChannel(code, entityType, entityId) {
|
|
61
|
+
return apiClient.put(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}/${entityType}/${encodeURIComponent(entityId)}`, {});
|
|
62
|
+
},
|
|
63
|
+
/**
|
|
64
|
+
* Remove a membership. With `fallbackToDefault=false` (default), removing
|
|
65
|
+
* the entity's last channel returns 422 ENTITY_WOULD_HAVE_ZERO_CHANNELS;
|
|
66
|
+
* with `true`, the entity is rebound to the system default in one
|
|
67
|
+
* transaction.
|
|
68
|
+
*/
|
|
69
|
+
removeEntityFromChannel(code, entityType, entityId, options = {}) {
|
|
70
|
+
const qs = options.fallbackToDefault ? `?fallbackToDefault=true` : '';
|
|
71
|
+
return apiClient.delete(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}/${entityType}/${encodeURIComponent(entityId)}${qs}`);
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=sales-channels-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sales-channels-client.js","sourceRoot":"","sources":["../../../src/admin/api/sales-channels-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type SalesChannelDetail } from '@endora-commerce/contracts';
|
|
3
|
+
export interface ChannelIdentityFormValue {
|
|
4
|
+
code: string;
|
|
5
|
+
name: string;
|
|
6
|
+
themeCode: string;
|
|
7
|
+
languages: string[];
|
|
8
|
+
defaultLanguage: string;
|
|
9
|
+
currencies: string[];
|
|
10
|
+
defaultCurrency: string;
|
|
11
|
+
active: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface ChannelIdentityFormProps {
|
|
14
|
+
mode: 'create' | 'edit';
|
|
15
|
+
initial?: SalesChannelDetail | null;
|
|
16
|
+
/** When true, the code field is read-only (renames possible later via a dedicated dialog). */
|
|
17
|
+
lockCode?: boolean;
|
|
18
|
+
errorMessage?: string | null;
|
|
19
|
+
saving?: boolean;
|
|
20
|
+
onSubmit: (value: ChannelIdentityFormValue) => void;
|
|
21
|
+
onCancel?: () => void;
|
|
22
|
+
}
|
|
23
|
+
export declare function ChannelIdentityForm({ mode, initial, lockCode, errorMessage, saving, onSubmit, onCancel, }: ChannelIdentityFormProps): ReactNode;
|
|
24
|
+
//# sourceMappingURL=ChannelIdentityForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChannelIdentityForm.d.ts","sourceRoot":"","sources":["../../../src/admin/components/ChannelIdentityForm.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAKL,KAAK,kBAAkB,EACxB,MAAM,4BAA4B,CAAC;AAkCpC,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACpC,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACpD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAOD,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,OAAO,EACP,QAAgB,EAChB,YAAY,EACZ,MAAc,EACd,QAAQ,EACR,QAAQ,GACT,EAAE,wBAAwB,GAAG,SAAS,CA+QtC"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useState, } from 'react';
|
|
3
|
+
import {} from '@endora-commerce/contracts';
|
|
4
|
+
import { apiClient } from '@endora-commerce/admin-kit/lib';
|
|
5
|
+
import { Alert, AlertDescription, Button, Card, CardContent, CardHeader, CardTitle, Checkbox, Input, Label, Select } from '@endora-commerce/admin-kit/ui';
|
|
6
|
+
import { useTranslation } from '@endora-commerce/admin-kit/i18n';
|
|
7
|
+
/**
|
|
8
|
+
* ChannelIdentityForm — feature 005 / T040.
|
|
9
|
+
*
|
|
10
|
+
* Captures the identity surface of a Sales Channel for both the create
|
|
11
|
+
* page and the edit page. Language and currency scopes are selected from
|
|
12
|
+
* Dictionary entries and submitted as the existing contract arrays.
|
|
13
|
+
*
|
|
14
|
+
* The i18n display name is captured as a single `en-US` string for
|
|
15
|
+
* v1 (matches the test-server seed). A multi-locale editor lands as
|
|
16
|
+
* a follow-up — the contract already supports the wider shape.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* List dictionary entries (feature 091, P6).
|
|
20
|
+
*
|
|
21
|
+
* The requests are built here rather than through `dictionaries`' own admin
|
|
22
|
+
* API client: that client is another module's **code**, which is what the
|
|
23
|
+
* cross-module ledger recorded, while `/api/v1/admin/dictionary/*` and the
|
|
24
|
+
* `Dictionary*PageResponse` types are an HTTP path and
|
|
25
|
+
* `@endora-commerce/contracts` types that both sides already compile. That is
|
|
26
|
+
* the exit P2 established and `admin-kit-surface.md` R6 records.
|
|
27
|
+
*/
|
|
28
|
+
function listDictionary(entry, pageSize) {
|
|
29
|
+
const qs = new URLSearchParams();
|
|
30
|
+
qs.set('pageSize', String(pageSize));
|
|
31
|
+
qs.set('sort', 'sortOrder');
|
|
32
|
+
return apiClient.get(`/api/v1/admin/dictionary/${entry}?${qs.toString()}`);
|
|
33
|
+
}
|
|
34
|
+
function pickEnglishName(name) {
|
|
35
|
+
if (!name)
|
|
36
|
+
return '';
|
|
37
|
+
return name['en-US'] ?? name['en'] ?? Object.values(name)[0] ?? '';
|
|
38
|
+
}
|
|
39
|
+
export function ChannelIdentityForm({ mode, initial, lockCode = false, errorMessage, saving = false, onSubmit, onCancel, }) {
|
|
40
|
+
const t = useTranslation('sales_channels');
|
|
41
|
+
const [code, setCode] = useState(initial?.code ?? '');
|
|
42
|
+
const [name, setName] = useState(pickEnglishName(initial?.name));
|
|
43
|
+
const [themeCode, setThemeCode] = useState(initial?.themeCode ?? '');
|
|
44
|
+
const [languages, setLanguages] = useState(initial?.languages ?? ['en-US']);
|
|
45
|
+
const [defaultLanguage, setDefaultLanguage] = useState(initial?.defaultLanguage ?? 'en-US');
|
|
46
|
+
const [currencies, setCurrencies] = useState(initial?.currencies ?? ['PLN']);
|
|
47
|
+
const [defaultCurrency, setDefaultCurrency] = useState(initial?.defaultCurrency ?? 'PLN');
|
|
48
|
+
const [active, setActive] = useState(initial?.active ?? true);
|
|
49
|
+
const [dictionaryLanguages, setDictionaryLanguages] = useState([]);
|
|
50
|
+
const [dictionaryCurrencies, setDictionaryCurrencies] = useState([]);
|
|
51
|
+
// Re-seed when the underlying entity changes (typical on first GET response after mount).
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (!initial)
|
|
54
|
+
return;
|
|
55
|
+
setCode(initial.code);
|
|
56
|
+
setName(pickEnglishName(initial.name));
|
|
57
|
+
setThemeCode(initial.themeCode ?? '');
|
|
58
|
+
setLanguages(initial.languages);
|
|
59
|
+
setDefaultLanguage(initial.defaultLanguage);
|
|
60
|
+
setCurrencies(initial.currencies);
|
|
61
|
+
setDefaultCurrency(initial.defaultCurrency);
|
|
62
|
+
setActive(initial.active);
|
|
63
|
+
}, [initial]);
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
let cancelled = false;
|
|
66
|
+
void Promise.all([
|
|
67
|
+
listDictionary('languages', 250),
|
|
68
|
+
listDictionary('currencies', 250),
|
|
69
|
+
])
|
|
70
|
+
.then(([languagePage, currencyPage]) => {
|
|
71
|
+
if (cancelled)
|
|
72
|
+
return;
|
|
73
|
+
setDictionaryLanguages(languagePage.data);
|
|
74
|
+
setDictionaryCurrencies(currencyPage.data);
|
|
75
|
+
})
|
|
76
|
+
.catch(() => {
|
|
77
|
+
if (cancelled)
|
|
78
|
+
return;
|
|
79
|
+
setDictionaryLanguages([]);
|
|
80
|
+
setDictionaryCurrencies([]);
|
|
81
|
+
});
|
|
82
|
+
return () => {
|
|
83
|
+
cancelled = true;
|
|
84
|
+
};
|
|
85
|
+
}, []);
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
if (languages.length > 0 && !languages.includes(defaultLanguage)) {
|
|
88
|
+
setDefaultLanguage(languages[0] ?? '');
|
|
89
|
+
}
|
|
90
|
+
}, [defaultLanguage, languages]);
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
if (currencies.length > 0 && !currencies.includes(defaultCurrency)) {
|
|
93
|
+
setDefaultCurrency(currencies[0] ?? '');
|
|
94
|
+
}
|
|
95
|
+
}, [currencies, defaultCurrency]);
|
|
96
|
+
const languageRows = useMemo(() => mergeSelectedDictionaryRows(dictionaryLanguages, languages), [dictionaryLanguages, languages]);
|
|
97
|
+
const currencyRows = useMemo(() => mergeSelectedDictionaryRows(dictionaryCurrencies, currencies), [dictionaryCurrencies, currencies]);
|
|
98
|
+
const toggleLanguage = (language) => {
|
|
99
|
+
setLanguages((prev) => prev.includes(language) ? prev.filter((code) => code !== language) : [...prev, language]);
|
|
100
|
+
};
|
|
101
|
+
const toggleCurrency = (currency) => {
|
|
102
|
+
setCurrencies((prev) => prev.includes(currency) ? prev.filter((code) => code !== currency) : [...prev, currency]);
|
|
103
|
+
};
|
|
104
|
+
const handleSubmit = useCallback((e) => {
|
|
105
|
+
e.preventDefault();
|
|
106
|
+
onSubmit({
|
|
107
|
+
code: code.trim(),
|
|
108
|
+
name: name.trim(),
|
|
109
|
+
themeCode: themeCode.trim(),
|
|
110
|
+
languages,
|
|
111
|
+
defaultLanguage: defaultLanguage.trim(),
|
|
112
|
+
currencies,
|
|
113
|
+
defaultCurrency: defaultCurrency.trim(),
|
|
114
|
+
active,
|
|
115
|
+
});
|
|
116
|
+
}, [
|
|
117
|
+
onSubmit,
|
|
118
|
+
code,
|
|
119
|
+
name,
|
|
120
|
+
themeCode,
|
|
121
|
+
languages,
|
|
122
|
+
defaultLanguage,
|
|
123
|
+
currencies,
|
|
124
|
+
defaultCurrency,
|
|
125
|
+
active,
|
|
126
|
+
]);
|
|
127
|
+
const cannotSubmit = saving || languages.length === 0 || currencies.length === 0;
|
|
128
|
+
return (_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-base", children: mode === 'create' ? t('identity.title.create') : t('identity.title.edit') }) }), _jsxs(CardContent, { children: [errorMessage && (_jsx(Alert, { variant: "destructive", className: "mb-4", children: _jsx(AlertDescription, { children: errorMessage }) })), _jsxs("form", { className: "grid gap-4", onSubmit: handleSubmit, children: [_jsxs("div", { className: "grid gap-2", children: [_jsx(Label, { htmlFor: "sc-code", children: t('identity.code.label') }), _jsx(Input, { id: "sc-code", value: code, onChange: (e) => setCode(e.target.value), placeholder: "serwis-a", disabled: lockCode, required: true }), lockCode && (_jsx("p", { className: "text-xs text-muted-foreground", children: t('identity.code.lockedHelp') }))] }), _jsxs("div", { className: "grid gap-2", children: [_jsx(Label, { htmlFor: "sc-name", children: t('identity.name.label') }), _jsx(Input, { id: "sc-name", value: name, onChange: (e) => setName(e.target.value), placeholder: t('identity.name.placeholder'), required: true })] }), _jsxs("div", { className: "grid gap-2", children: [_jsx(Label, { htmlFor: "sc-theme", children: t('identity.theme.label') }), _jsx(Input, { id: "sc-theme", value: themeCode, onChange: (e) => setThemeCode(e.target.value), placeholder: t('identity.theme.placeholder'), pattern: "[a-z][a-z0-9_-]*", title: t('identity.theme.pattern') }), _jsx("p", { className: "text-xs text-muted-foreground", children: t('identity.theme.help') })] }), _jsxs("div", { className: "grid gap-2 md:grid-cols-[2fr_1fr]", children: [_jsxs("div", { className: "grid gap-2", children: [_jsx(Label, { children: t('identity.languages.label') }), _jsx(DictionaryCheckboxList, { rows: languageRows, selected: languages, onToggle: toggleLanguage }), _jsx("p", { className: "text-xs text-muted-foreground", children: t('identity.languages.help') })] }), _jsxs("div", { className: "grid gap-2", children: [_jsx(Label, { htmlFor: "sc-default-lang", children: t('identity.defaultLanguage.label') }), _jsxs(Select, { id: "sc-default-lang", value: defaultLanguage, onChange: (e) => setDefaultLanguage(e.target.value), children: [_jsx("option", { value: "", disabled: true, children: t('identity.pickOption') }), languages.map((lang) => (_jsx("option", { value: lang, children: lang }, lang)))] })] })] }), _jsxs("div", { className: "grid gap-2 md:grid-cols-[2fr_1fr]", children: [_jsxs("div", { className: "grid gap-2", children: [_jsx(Label, { children: t('identity.currencies.label') }), _jsx(DictionaryCheckboxList, { rows: currencyRows, selected: currencies, onToggle: toggleCurrency }), _jsx("p", { className: "text-xs text-muted-foreground", children: t('identity.currencies.help') })] }), _jsxs("div", { className: "grid gap-2", children: [_jsx(Label, { htmlFor: "sc-default-curr", children: t('identity.defaultCurrency.label') }), _jsxs(Select, { id: "sc-default-curr", value: defaultCurrency, onChange: (e) => setDefaultCurrency(e.target.value), children: [_jsx("option", { value: "", disabled: true, children: t('identity.pickOption') }), currencies.map((curr) => (_jsx("option", { value: curr, children: curr }, curr)))] })] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Checkbox, { id: "sc-active", checked: active, onChange: (e) => setActive(e.target.checked), disabled: initial?.systemDefault === true }), _jsx(Label, { htmlFor: "sc-active", className: "cursor-pointer", children: t('identity.active') }), initial?.systemDefault && (_jsx("span", { className: "text-xs text-muted-foreground", children: t('identity.cannotDeactivateDefault') }))] }), _jsxs("div", { className: "flex justify-end gap-2", children: [onCancel && (_jsx(Button, { type: "button", variant: "ghost", onClick: onCancel, disabled: saving, children: t('identity.action.cancel') })), _jsx(Button, { type: "submit", disabled: cannotSubmit, children: mode === 'create' ? t('identity.action.create') : t('identity.action.save') })] })] })] })] }));
|
|
129
|
+
}
|
|
130
|
+
function mergeSelectedDictionaryRows(rows, selected) {
|
|
131
|
+
const byCode = new Map(rows.map((row) => [row.code, row]));
|
|
132
|
+
const merged = [...rows];
|
|
133
|
+
for (const code of selected) {
|
|
134
|
+
if (!byCode.has(code)) {
|
|
135
|
+
merged.push({ code, label: code, isActive: false });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return merged;
|
|
139
|
+
}
|
|
140
|
+
function DictionaryCheckboxList({ rows, selected, onToggle, }) {
|
|
141
|
+
const t = useTranslation('sales_channels');
|
|
142
|
+
const activeRows = rows.filter((row) => row.isActive);
|
|
143
|
+
const inactiveSelected = rows.filter((row) => !row.isActive && selected.includes(row.code));
|
|
144
|
+
const visibleRows = [...activeRows, ...inactiveSelected];
|
|
145
|
+
return (_jsxs("div", { className: "max-h-48 overflow-auto rounded-md border p-3", children: [visibleRows.map((row) => (_jsxs("label", { className: "flex items-center gap-2 py-1 text-sm", children: [_jsx(Checkbox, { checked: selected.includes(row.code), onChange: () => onToggle(row.code) }), _jsx("span", { className: "font-mono text-xs", children: row.code }), _jsx("span", { children: row.label }), !row.isActive ? (_jsx("span", { className: "text-xs text-muted-foreground", children: t('identity.dictionary.inactive') })) : null] }, row.code))), visibleRows.length === 0 ? (_jsx("p", { className: "text-xs text-muted-foreground", children: t('identity.dictionary.empty') })) : null] }));
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=ChannelIdentityForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChannelIdentityForm.js","sourceRoot":"","sources":["../../../src/admin/components/ChannelIdentityForm.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Read-only marker for the system-default Sales Channel (feature 005 / T039).
|
|
4
|
+
*
|
|
5
|
+
* The channel is identified by `systemDefault === true` (FR-002); this renders
|
|
6
|
+
* the visual and nothing else.
|
|
7
|
+
*
|
|
8
|
+
* **There is one copy, and this is it.** A second stood at
|
|
9
|
+
* `admin/src/modules/sales_channels/components/` for the length of P7a, serving
|
|
10
|
+
* this module's own two screens; batch 14 moved both screens into this package,
|
|
11
|
+
* they import this file, and the other one is deleted — which is what the note
|
|
12
|
+
* that stood here said would happen. `EntityChannelMembership` beside it went
|
|
13
|
+
* the same way one merge request earlier.
|
|
14
|
+
* `admin/test/modules/sales_channels/organization-channels-zone.test.tsx`
|
|
15
|
+
* asserts that no file remains at the old path, because nothing in this estate
|
|
16
|
+
* compares two copies of one component.
|
|
17
|
+
*/
|
|
18
|
+
export declare function DefaultChannelBadge({ systemDefault, }: {
|
|
19
|
+
systemDefault: boolean;
|
|
20
|
+
}): ReactNode;
|
|
21
|
+
//# sourceMappingURL=DefaultChannelBadge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DefaultChannelBadge.d.ts","sourceRoot":"","sources":["../../../src/admin/components/DefaultChannelBadge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,aAAa,GACd,EAAE;IACD,aAAa,EAAE,OAAO,CAAC;CACxB,GAAG,SAAS,CAQZ"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Badge } from '@endora-commerce/admin-kit/ui';
|
|
3
|
+
import { useTranslation } from '@endora-commerce/admin-kit/i18n';
|
|
4
|
+
/**
|
|
5
|
+
* Read-only marker for the system-default Sales Channel (feature 005 / T039).
|
|
6
|
+
*
|
|
7
|
+
* The channel is identified by `systemDefault === true` (FR-002); this renders
|
|
8
|
+
* the visual and nothing else.
|
|
9
|
+
*
|
|
10
|
+
* **There is one copy, and this is it.** A second stood at
|
|
11
|
+
* `admin/src/modules/sales_channels/components/` for the length of P7a, serving
|
|
12
|
+
* this module's own two screens; batch 14 moved both screens into this package,
|
|
13
|
+
* they import this file, and the other one is deleted — which is what the note
|
|
14
|
+
* that stood here said would happen. `EntityChannelMembership` beside it went
|
|
15
|
+
* the same way one merge request earlier.
|
|
16
|
+
* `admin/test/modules/sales_channels/organization-channels-zone.test.tsx`
|
|
17
|
+
* asserts that no file remains at the old path, because nothing in this estate
|
|
18
|
+
* compares two copies of one component.
|
|
19
|
+
*/
|
|
20
|
+
export function DefaultChannelBadge({ systemDefault, }) {
|
|
21
|
+
const t = useTranslation('sales_channels');
|
|
22
|
+
if (!systemDefault)
|
|
23
|
+
return null;
|
|
24
|
+
return (_jsx(Badge, { variant: "secondary", className: "ml-2 text-[10px] uppercase tracking-wider", children: t('badge.systemDefault') }));
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=DefaultChannelBadge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DefaultChannelBadge.js","sourceRoot":"","sources":["../../../src/admin/components/DefaultChannelBadge.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAClC,aAAa,GAGd;IACC,MAAM,CAAC,GAAG,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAC3C,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAChC,OAAO,CACL,KAAC,KAAK,IAAC,OAAO,EAAC,WAAW,EAAC,SAAS,EAAC,2CAA2C,YAC7E,CAAC,CAAC,qBAAqB,CAAC,GACnB,CACT,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { ChannelMemberEntityType } from '@endora-commerce/contracts';
|
|
3
|
+
/**
|
|
4
|
+
* The channels an entity belongs to, editable from the entity's own editor
|
|
5
|
+
* (feature 005 / T065).
|
|
6
|
+
*
|
|
7
|
+
* Loads the entity's current channels and the platform's full channel list in
|
|
8
|
+
* parallel on mount. The Add control offers only channels the entity is not
|
|
9
|
+
* already in; Remove tries `fallbackToDefault: false` first and, on
|
|
10
|
+
* `ENTITY_WOULD_HAVE_ZERO_CHANNELS`, asks the operator whether to rebind to the
|
|
11
|
+
* system default. The mutation goes through the centralised
|
|
12
|
+
* `/api/v1/admin/sales-channels/:code/:entityType/:entityId` routes, so an
|
|
13
|
+
* entity editor never needs membership endpoints of its own.
|
|
14
|
+
*
|
|
15
|
+
* ## Why the calls are rebuilt rather than the client moved (feature 091, P7a)
|
|
16
|
+
*
|
|
17
|
+
* `catalog`'s product editor imported this file by path — one of the three
|
|
18
|
+
* admin keys in `backend/scripts/ledgers/cross-module-imports/catalog.ts`. It
|
|
19
|
+
* lives in this module's package now and reaches that screen as a
|
|
20
|
+
* `product.editor.channels` contribution. Its four reads and writes are HTTP
|
|
21
|
+
* paths whose payload types are already `@endora-commerce/contracts`', so they
|
|
22
|
+
* are rebuilt from the published `apiClient` here (P2's exit) rather than
|
|
23
|
+
* dragging that module's admin API client along, which at the time would have
|
|
24
|
+
* been a package reaching back into the admin application. Batch 14 moved the
|
|
25
|
+
* client into this package as `../api/sales-channels-client.ts`; this file goes
|
|
26
|
+
* on building its own requests, because a zone contribution rendered inside
|
|
27
|
+
* another module's screen has no business carrying a client whose only other
|
|
28
|
+
* readers are two screens it never renders with.
|
|
29
|
+
*
|
|
30
|
+
* **P7b deleted the copy.** One stood at
|
|
31
|
+
* `admin/src/modules/sales_channels/components/` for the length of P7a, serving
|
|
32
|
+
* `organizations`' detail screen; that screen is a zone mount now, nothing
|
|
33
|
+
* imported the file, and it is gone. Nothing in this estate compares two copies
|
|
34
|
+
* of one component, so the retiring condition was written here rather than left
|
|
35
|
+
* to be remembered.
|
|
36
|
+
*
|
|
37
|
+
* `DefaultChannelBadge` beside it is the other half of that copy and **went
|
|
38
|
+
* the same way in batch 14**, which is what the note that stood here said would
|
|
39
|
+
* happen: this module's own two screens moved into this package, they import the
|
|
40
|
+
* sibling file, and the `admin/src` copy is deleted.
|
|
41
|
+
*
|
|
42
|
+
* The `entityId` guard below is unreachable under a zone — all three mounts
|
|
43
|
+
* have an id before they mount — and stays as the component's own contract.
|
|
44
|
+
*/
|
|
45
|
+
export interface EntityChannelMembershipProps {
|
|
46
|
+
entityType: ChannelMemberEntityType;
|
|
47
|
+
entityId: string | null | undefined;
|
|
48
|
+
/** When set, called after every successful add / remove / fallback so the parent can refetch. */
|
|
49
|
+
onChanged?: () => void;
|
|
50
|
+
}
|
|
51
|
+
export declare function EntityChannelMembership({ entityType, entityId, onChanged, }: EntityChannelMembershipProps): ReactNode;
|
|
52
|
+
//# sourceMappingURL=EntityChannelMembership.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityChannelMembership.d.ts","sourceRoot":"","sources":["../../../src/admin/components/EntityChannelMembership.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClF,OAAO,KAAK,EACV,uBAAuB,EAGxB,MAAM,4BAA4B,CAAC;AAgBpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,MAAM,WAAW,4BAA4B;IAC3C,UAAU,EAAE,uBAAuB,CAAC;IACpC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC,iGAAiG;IACjG,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAUD,wBAAgB,uBAAuB,CAAC,EACtC,UAAU,EACV,QAAQ,EACR,SAAS,GACV,EAAE,4BAA4B,GAAG,SAAS,CAgL1C"}
|