@webx-ui/module-services 0.1.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 webx-ui
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,55 @@
1
+ # @webx-ui/module-services
2
+
3
+ The front end of the services section of the [WebX UI](https://github.com/webx-ui/webx-ui) admin
4
+ panel: a catalogue of services, and the categories they are filed under.
5
+
6
+ The other half is the Composer package `webx-ui/module-services`, which owns the services, their
7
+ addresses, their order and the API. A section appears in the panel when both halves are installed.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install @webx-ui/module-services
13
+ ```
14
+
15
+ ```ts
16
+ import { createAdmin } from '@webx-ui/module-admin'
17
+ import { services } from '@webx-ui/module-services'
18
+ import '@webx-ui/module-services/style.css'
19
+
20
+ createAdmin({
21
+ basePath: '/cms',
22
+ modules: [...services()],
23
+ }).mount()
24
+ ```
25
+
26
+ `services()` answers with two sections — the services and their categories — because the panel
27
+ draws one entry per module. The server puts both in the `services` group.
28
+ `services({ path: '/catalogue' })` puts them somewhere else inside the panel.
29
+
30
+ ## The list
31
+
32
+ The whole catalogue on one screen, without pages: a site has dozens of services, and a drag
33
+ cannot cross a page boundary. The row shows the cover, the title with the address under it, the
34
+ categories as chips (the first one is the main one) and the state.
35
+
36
+ The list has two orders, and the filter decides which one you are dragging:
37
+
38
+ - **no category chosen** — the order of the whole list;
39
+ - **a category chosen** — the order inside that category only. Every other category keeps its own.
40
+
41
+ While a search or a state narrows the list, the grips disappear: the gaps between the rows you see
42
+ are rows you do not, and a drop into one is not an order anybody chose.
43
+
44
+ ## The editor
45
+
46
+ The `services.form` screen, described in JSON on the server: **Content** (blocks, autosaved into
47
+ the draft), **Settings** (title, address, categories, lead, cover, and a card for the project's own
48
+ fields), **SEO** and **History**. The categories take effect when saved; everything else waits in
49
+ the draft until it is published. A save over somebody else's is refused with the newer version.
50
+
51
+ The categories are the panel's shared category screens with this module's words.
52
+
53
+ ## Licence
54
+
55
+ MIT
@@ -0,0 +1,4 @@
1
+ declare const _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {
2
+ field: HTMLDivElement;
3
+ }, any>;
4
+ export default _default;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The editor of one service: a head that stays put, the described screen under it, and the bar
3
+ * along the bottom where it is saved and published (§4.6).
4
+ *
5
+ * Everything between the head and the bar is `services.form`, so `module-seo` adds its card and a
6
+ * project its price with a patch rather than a fork of this file. Saving is by autosave — a pause
7
+ * after the last keystroke, and the moment a field is left — into the draft; the site changes
8
+ * only on "Publish". Edits are guarded by a revision: a save over somebody else's is refused with
9
+ * a 409 and the question of which version the site gets.
10
+ */
11
+ type __VLS_Props = {
12
+ base?: string;
13
+ };
14
+ declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
15
+ base: string;
16
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
17
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, HTMLDivElement>;
2
+ export default _default;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The catalogue: every service at once, in the order the site shows them (§4.6).
3
+ *
4
+ * No paginator and no table. There are dozens of services, not thousands, and this list is where
5
+ * they are put in order — a drag cannot cross a page boundary. The order is decision 5 of the
6
+ * spec: without a filter the rows are the whole list and a drag moves the common order; narrowed
7
+ * to one category they come in that category's own order and a drag moves only it; any other
8
+ * narrowing (a search, a status, the bin) shows a selection with invisible gaps in it, so the
9
+ * grips go away and the line under the list says why.
10
+ *
11
+ * A row is a card rather than a line of cells, which is what makes the same list work on a
12
+ * phone: the picture, the name and the address on one side, the categories and the state beside
13
+ * them on a wide screen and under them on a narrow one.
14
+ */
15
+ type __VLS_Props = {
16
+ base?: string;
17
+ };
18
+ declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
19
+ base: string;
20
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
21
+ export default _default;
package/dist/api.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ import { AdminContext } from '@webx-ui/module-admin';
2
+ import { ServiceDetail, ServiceInput, ServiceQuery, ServiceRow, ServiceSave, ServicesList, ServiceVersion } from './types';
3
+ export interface ServicesApi {
4
+ /** Every service, with the categories the list can be narrowed to. */
5
+ list(query?: ServiceQuery): Promise<ServicesList>;
6
+ /** One service as its editor opens it: the record, the screen's values and the revision. */
7
+ get(id: number): Promise<ServiceDetail>;
8
+ create(input: ServiceInput): Promise<ServiceRow>;
9
+ /**
10
+ * Save the draft. Refused with a 409 when the revision is stale — the body is a
11
+ * {@link ServiceConflict} with the service as it now is.
12
+ */
13
+ save(id: number, input: ServiceSave): Promise<ServiceDetail>;
14
+ /** Throw away what is waiting and keep what the site is showing. */
15
+ discard(id: number): Promise<ServiceDetail>;
16
+ publish(id: number): Promise<ServiceRow>;
17
+ unpublish(id: number): Promise<ServiceRow>;
18
+ remove(id: number): Promise<void>;
19
+ restore(id: number): Promise<ServiceRow>;
20
+ /** The publications, newest first. */
21
+ versions(id: number): Promise<ServiceVersion[]>;
22
+ /** An old publication becomes the draft; putting it on the site is a separate step. */
23
+ restoreVersion(id: number, number: number): Promise<ServiceDetail>;
24
+ /** The order on screen: of the whole list, or — with `category` — of that category alone. */
25
+ reorder(ids: number[], category?: number | null): Promise<void>;
26
+ }
27
+ /** The path of the list under the panel's API, and of its order (`CategoryRoutes::items()`). */
28
+ export declare const SERVICES_API = "services";
29
+ /**
30
+ * Everything under `/services`, below the panel's API path — except the categories, which are the
31
+ * panel's shared ones and are asked for with `createCategoriesApi(admin, 'services/categories')`.
32
+ */
33
+ export declare function createServicesApi(admin: AdminContext): ServicesApi;
@@ -0,0 +1,19 @@
1
+ import { InjectionKey, Ref } from 'vue';
2
+ import { ServiceRow } from './types';
3
+ /**
4
+ * What the editor knows and the nodes of `services.form` do not: the service being edited, and a
5
+ * way to read it again. The history needs both — its list is keyed by the service, and a restored
6
+ * version has to reach the fields the form is bound to.
7
+ */
8
+ export interface ServiceEditorContext {
9
+ /** The service as the server last answered it, or `null` while the first request is out. */
10
+ service: Ref<ServiceRow | null>;
11
+ /** Whether this administrator may write at all. */
12
+ canManage: boolean;
13
+ /** Ask the server for the service again — after a restore, a publication, a discard. */
14
+ reload(): Promise<void>;
15
+ }
16
+ export declare const serviceEditorKey: InjectionKey<ServiceEditorContext>;
17
+ export declare function provideServiceEditor(editor: ServiceEditorContext): void;
18
+ /** The editor above this node, or `null` outside one — a demo or a test draws nothing. */
19
+ export declare function useServiceEditor(): ServiceEditorContext | null;
package/dist/i18n.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ /** Puts this package's English under the panel's dictionary, once per panel. */
2
+ export declare function useServicesMessages(): void;
@@ -0,0 +1,9 @@
1
+ export { services, serviceCategoriesOptions, type ServicesOptions } from './module';
2
+ export { createServicesApi, SERVICES_API, type ServicesApi } from './api';
3
+ export { servicesMessages } from './messages';
4
+ export { provideServiceEditor, serviceEditorKey, useServiceEditor, type ServiceEditorContext, } from './editor';
5
+ export { default as WxServicesPage } from './ServicesPage';
6
+ export { default as WxServiceCreateDialog } from './ServiceCreateDialog';
7
+ export { default as WxServiceEditorPage } from './ServiceEditorPage';
8
+ export { default as WxServiceHistory } from './ServiceHistory';
9
+ export type { ServiceCategoryRef, ServiceConflict, ServiceCover, ServiceDetail, ServiceInput, ServiceQuery, ServiceRow, ServiceSave, ServicesList, ServiceStatus, ServiceVersion, } from './types';