@itrocks/list 0.6.0 → 0.7.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/README.md CHANGED
@@ -72,7 +72,7 @@ adds list‑oriented behaviors.
72
72
 
73
73
  #### Methods
74
74
 
75
- ##### `html(request: Request<T>): Promise<HtmlResponse>`
75
+ ##### `html(request: Request<T>, scope?: SearchType<T>): Promise<HtmlResponse>`
76
76
 
77
77
  Builds an HTML response for the list view.
78
78
 
@@ -95,15 +95,14 @@ fastify.get('/users', async (req, reply) => {
95
95
  })
96
96
  ```
97
97
 
98
- ##### `json(request: Request<T>): Promise<JsonResponse>`
98
+ ##### `json(request: Request<T>, scope?: SearchType<T>): Promise<JsonResponse>`
99
99
 
100
- Builds a JSON representation of the same list data.
100
+ Builds a JSON response from the objects returned by the configured data source.
101
101
 
102
102
  The returned
103
103
  [`JsonResponse`](https://github.com/itrocks-ts/core-responses#jsonresponse)
104
- typically contains the current page of results, meta‑data (page, page size,
105
- total count) and any additional information configured via your
106
- `Action`/`List` setup.
104
+ contains those objects. Unlike `html()`, this method does not process the HTML list's
105
+ filters, sorting, pagination, templates or count.
107
106
 
108
107
  This is useful for API‑only endpoints, asynchronous front‑end components or
109
108
  infinite‑scroll lists.
@@ -119,6 +118,18 @@ fastify.get('/api/users', async (req, reply) => {
119
118
  })
120
119
  ```
121
120
 
121
+ ### Mandatory scopes
122
+
123
+ Both `html()` and `json()` accept an optional application scope as a `SearchType<T>`. Build
124
+ the scope from trusted application state rather than passing request data through directly.
125
+
126
+ For `html()`, the scope is merged after user filters, so it takes precedence if both define
127
+ the same property. The resulting search is passed to both `dataSource().search()` and
128
+ `dataSource().count()` without replacing list loading, sorting, pagination, metadata,
129
+ templates or the configured data source.
130
+
131
+ For `json()`, the scope is passed directly to `dataSource().search()`.
132
+
122
133
  ## Typical use cases
123
134
 
124
135
  - Back‑office list screens for any business entity (users, products, orders…).
package/build.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {};
package/build.js ADDED
@@ -0,0 +1,61 @@
1
+ import { build } from '@itrocks/build/build.js';
2
+ import { TableColumnReorder } from '@itrocks/table/column-reorder.js';
3
+ import { TableColumnReorderFreeze } from '@itrocks/table/column-reorder-freeze.js';
4
+ import { TableFeed } from '@itrocks/table/feed.js';
5
+ import { TableFreeze } from '@itrocks/table/freeze.js';
6
+ import { TableFreezeInheritBackground } from '@itrocks/table/freeze/inherit-background.js';
7
+ import { TableFreezeInheritBorder } from '@itrocks/table/freeze/inherit-border.js';
8
+ import { TableLink } from '@itrocks/table/link.js';
9
+ import { tableByElement } from '@itrocks/table/table.js';
10
+ import { xTargetCall } from '@itrocks/xtarget/xtarget.js';
11
+ build('article[data-action="list"] > form > table.objects', table => {
12
+ const tableColumnReorder = new TableColumnReorder({ onReorder: () => {
13
+ const columns = table.tHead?.rows[0].querySelectorAll(':scope > th[data-property]');
14
+ const form = table.closest('form');
15
+ if (!columns?.length || !form)
16
+ return;
17
+ const properties = Array.from(columns, column => encodeURIComponent(column.dataset.property ?? ''));
18
+ fetch(form.action + '?columns=' + properties.join(','), { keepalive: true }).catch(error => console.error('Column order save error:', error));
19
+ } });
20
+ const tableLink = new TableLink({
21
+ call: url => xTargetCall(url, 'main'),
22
+ id: (element) => {
23
+ const input = element.closest('tr')?.querySelector(':scope > th.select > input[name=id]');
24
+ if (input)
25
+ return { element: input, value: input.value };
26
+ }
27
+ });
28
+ tableByElement(table, {
29
+ plugins: [
30
+ tableColumnReorder, TableColumnReorderFreeze, TableFeed, TableFreeze, TableFreezeInheritBackground,
31
+ TableFreezeInheritBorder, tableLink
32
+ ]
33
+ });
34
+ table.addEventListener('click', event => {
35
+ const element = event.target;
36
+ if ((element instanceof HTMLInputElement) || !(element instanceof HTMLElement))
37
+ return;
38
+ const cell = element.closest('table, th');
39
+ if (!((cell instanceof HTMLTableCellElement) && cell.classList.contains('select')))
40
+ return;
41
+ const input = cell.querySelector('input[type=checkbox]');
42
+ if (!input)
43
+ return;
44
+ input.click();
45
+ input.focus();
46
+ });
47
+ table.tHead?.addEventListener('click', event => {
48
+ const element = event.target;
49
+ if (!(element instanceof HTMLElement))
50
+ return;
51
+ const cell = element.closest('table, th');
52
+ if (!(cell instanceof HTMLTableCellElement) || !cell.dataset.property)
53
+ return;
54
+ const form = cell.closest('form');
55
+ if (!form)
56
+ return;
57
+ const reverse = (cell.dataset.sort === '1') ? !cell.dataset.reverse : !!cell.dataset.reverse;
58
+ const url = form.action + '?sort=' + cell.dataset.property + (reverse ? '&reverse' : '');
59
+ xTargetCall(url, 'main');
60
+ });
61
+ });
@@ -0,0 +1,18 @@
1
+ import { Type } from '@itrocks/class-type';
2
+ import { ReflectProperty } from '@itrocks/reflect';
3
+ import { Request } from '@itrocks/request-response';
4
+ import { Option } from '@itrocks/storage';
5
+ import { Parameter } from './parameter';
6
+ export declare class Columns<T extends object> extends Parameter implements Iterable<ReflectProperty<T>> {
7
+ properties: ReflectProperty<T, keyof T>[];
8
+ [Symbol.iterator](): ArrayIterator<ReflectProperty<T, keyof T>>;
9
+ getParams(request: Request, type: Type<T>): void;
10
+ get length(): number;
11
+ map(callback: (value: ReflectProperty<T>) => any): any[];
12
+ propertiesOf(object: T): ReflectProperty<T, keyof T>[];
13
+ readOptions(options?: Option[]): Option[];
14
+ remove(propertyName: string): void;
15
+ serialize(): (keyof T)[];
16
+ unserialize(data: (keyof T)[], type: Type<T>): void;
17
+ unshift(property: ReflectProperty<T>): number;
18
+ }
package/cjs/columns.js ADDED
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Columns = void 0;
4
+ const list_properties_1 = require("@itrocks/list-properties");
5
+ const reflect_1 = require("@itrocks/reflect");
6
+ const parameter_1 = require("./parameter");
7
+ class Columns extends parameter_1.Parameter {
8
+ properties = new Array;
9
+ [Symbol.iterator]() {
10
+ return this.properties[Symbol.iterator]();
11
+ }
12
+ getParams(request, type) {
13
+ const data = request.data.columns;
14
+ if (data !== undefined) {
15
+ const propertyNames = (Array.isArray(data) ? data : [data]).flatMap(property => (typeof property === 'string') ? property.split(',') : property);
16
+ if (propertyNames.every((property) => typeof property === 'string')) {
17
+ const reflected = new list_properties_1.ListReflectClass(type).listProperties();
18
+ const reordered = propertyNames.map(propertyName => reflected.find(property => property.name.toString() === propertyName));
19
+ const properties = reordered.filter((property) => !!property);
20
+ if ((propertyNames.length === reflected.length)
21
+ && (properties.length === reflected.length)
22
+ && (new Set(properties).size === reflected.length)) {
23
+ this.properties = properties;
24
+ }
25
+ }
26
+ }
27
+ if (!this.length) {
28
+ this.properties = new list_properties_1.ListReflectClass(type).listProperties();
29
+ }
30
+ }
31
+ get length() {
32
+ return this.properties.length;
33
+ }
34
+ map(callback) {
35
+ return this.properties.map(callback);
36
+ }
37
+ propertiesOf(object) {
38
+ return this.properties.map(property => new reflect_1.ReflectProperty(object, property.name));
39
+ }
40
+ readOptions(options = new Array) {
41
+ return options;
42
+ }
43
+ remove(propertyName) {
44
+ for (const property of this.properties) {
45
+ if (property.name !== propertyName)
46
+ continue;
47
+ this.properties.splice(this.properties.indexOf(property), 1);
48
+ return;
49
+ }
50
+ }
51
+ serialize() {
52
+ return this.properties.map(property => property.name);
53
+ }
54
+ unserialize(data, type) {
55
+ this.properties = data.map(property => new reflect_1.ReflectProperty(type, property));
56
+ }
57
+ unshift(property) {
58
+ return this.properties.unshift(property);
59
+ }
60
+ }
61
+ exports.Columns = Columns;
62
+ //# sourceMappingURL=columns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"columns.js","sourceRoot":"","sources":["../src/columns.ts"],"names":[],"mappings":"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"}
package/cjs/feed.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ import { Request } from '@itrocks/request-response';
2
+ import { Option } from '@itrocks/storage';
3
+ import { Parameter } from './parameter';
4
+ export declare class Feed extends Parameter {
5
+ static DEFAULT_LIMIT: number;
6
+ static DEFAULT_LINE_HEIGHT: number;
7
+ static DEFAULT_OFFSET: number;
8
+ limit: number;
9
+ lineHeight: number;
10
+ offset: number;
11
+ template: string;
12
+ getParams(request: Request): void;
13
+ readOptions(options?: Option[]): Option[];
14
+ }
package/cjs/feed.js ADDED
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Feed = void 0;
4
+ const storage_1 = require("@itrocks/storage");
5
+ const parameter_1 = require("./parameter");
6
+ class Feed extends parameter_1.Parameter {
7
+ static DEFAULT_LIMIT = 50;
8
+ static DEFAULT_LINE_HEIGHT = 30;
9
+ static DEFAULT_OFFSET = 0;
10
+ limit = Feed.DEFAULT_LIMIT;
11
+ lineHeight = Feed.DEFAULT_LINE_HEIGHT;
12
+ offset = Feed.DEFAULT_OFFSET;
13
+ template = __dirname + '/feed.html';
14
+ getParams(request) {
15
+ const header = request.headers['xhr-info'];
16
+ const xhrInfo = header ? JSON.parse(header) : {};
17
+ this.limit = xhrInfo.targetHeight
18
+ ? Math.ceil(xhrInfo.targetHeight / this.lineHeight)
19
+ : (xhrInfo.visibleRows ?? Feed.DEFAULT_LIMIT);
20
+ this.offset = +request.data.offset;
21
+ }
22
+ readOptions(options = new Array) {
23
+ options.push(new storage_1.Limit(this.limit, this.offset));
24
+ return options;
25
+ }
26
+ }
27
+ exports.Feed = Feed;
28
+ //# sourceMappingURL=feed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feed.js","sourceRoot":"","sources":["../src/feed.ts"],"names":[],"mappings":";;;AACA,8CAA4C;AAE5C,2CAAuC;AAEvC,MAAa,IAAK,SAAQ,qBAAS;IAGlC,MAAM,CAAC,aAAa,GAAS,EAAE,CAAA;IAC/B,MAAM,CAAC,mBAAmB,GAAG,EAAE,CAAA;IAC/B,MAAM,CAAC,cAAc,GAAQ,CAAC,CAAA;IAE9B,KAAK,GAAQ,IAAI,CAAC,aAAa,CAAA;IAC/B,UAAU,GAAG,IAAI,CAAC,mBAAmB,CAAA;IACrC,MAAM,GAAO,IAAI,CAAC,cAAc,CAAA;IAChC,QAAQ,GAAK,SAAS,GAAG,YAAY,CAAA;IAErC,SAAS,CAAC,OAAgB;QAEzB,MAAM,MAAM,GAAI,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;QAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAChD,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,YAAY;YAChC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC;YACpD,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC,aAAa,CAAC,CAAA;QAC7C,IAAI,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAA;IACnC,CAAC;IAED,WAAW,CAAC,UAAU,IAAI,KAAa;QAEtC,OAAO,CAAC,IAAI,CAAC,IAAI,eAAK,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;QAChD,OAAO,OAAO,CAAA;IACf,CAAC;;AA1BF,oBA4BC"}
@@ -0,0 +1,19 @@
1
+ import { Type } from '@itrocks/class-type';
2
+ import { Request } from '@itrocks/request-response';
3
+ import { Option } from '@itrocks/storage';
4
+ import { Columns } from './columns';
5
+ import { Parameter } from './parameter';
6
+ type Search = {
7
+ [property: string]: string;
8
+ };
9
+ export declare class Filter<T extends object> extends Parameter {
10
+ columns: Columns<T>;
11
+ search: Search;
12
+ constructor(columns: Columns<T>);
13
+ getParams(request: Request): void;
14
+ readOptions(options?: Option[]): Option[];
15
+ searchObject(type: Type): any;
16
+ serialize(): Search;
17
+ unserialize(data: Search): void;
18
+ }
19
+ export {};
package/cjs/filter.js ADDED
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Filter = void 0;
4
+ const parameter_1 = require("./parameter");
5
+ class Filter extends parameter_1.Parameter {
6
+ columns;
7
+ search = {};
8
+ constructor(columns) {
9
+ super();
10
+ this.columns = columns;
11
+ }
12
+ getParams(request) {
13
+ for (const property of this.columns.map(property => property.name)) {
14
+ this.search[property] = '';
15
+ }
16
+ for (const [property, search] of Object.entries(request.data.search ?? {})) {
17
+ if (!(property in this.search))
18
+ continue;
19
+ this.search[property] = search;
20
+ }
21
+ }
22
+ readOptions(options = new Array) {
23
+ return options;
24
+ }
25
+ searchObject(type) {
26
+ const search = {};
27
+ for (const [property, value] of Object.entries(this.search)) {
28
+ if (value === '')
29
+ continue;
30
+ search[property] = value;
31
+ }
32
+ return Object.setPrototypeOf(search, type.prototype);
33
+ }
34
+ serialize() {
35
+ return this.search;
36
+ }
37
+ unserialize(data) {
38
+ this.search = data;
39
+ }
40
+ }
41
+ exports.Filter = Filter;
42
+ //# sourceMappingURL=filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.js","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":";;;AAIA,2CAAuC;AAIvC,MAAa,MAAyB,SAAQ,qBAAS;IAKnC;IAFnB,MAAM,GAAW,EAAE,CAAA;IAEnB,YAAmB,OAAmB;QAErC,KAAK,EAAE,CAAA;QAFW,YAAO,GAAP,OAAO,CAAY;IAGtC,CAAC;IAED,SAAS,CAAC,OAAgB;QAEzB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACpE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAA;QAC3B,CAAC;QACD,KAAK,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;YAC5E,IAAI,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC;gBAAE,SAAQ;YACxC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAA;QAC/B,CAAC;IACF,CAAC;IAED,WAAW,CAAC,UAAU,IAAI,KAAa;QAEtC,OAAO,OAAO,CAAA;IACf,CAAC;IAED,YAAY,CAAC,IAAU;QAEtB,MAAM,MAAM,GAAW,EAAE,CAAA;QACzB,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7D,IAAI,KAAK,KAAK,EAAE;gBAAE,SAAQ;YAC1B,MAAM,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAA;QACzB,CAAC;QACD,OAAO,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;IACrD,CAAC;IAED,SAAS;QAER,OAAO,IAAI,CAAC,MAAM,CAAA;IACnB,CAAC;IAED,WAAW,CAAC,IAAY;QAEvB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;IACnB,CAAC;CAED;AA9CD,wBA8CC"}
package/cjs/list.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { Action } from '@itrocks/action';
2
+ import { Request } from '@itrocks/action-request';
3
+ import { SearchType } from '@itrocks/storage';
4
+ import { Columns } from './columns';
5
+ import { Feed } from './feed';
6
+ import { Filter } from './filter';
7
+ import { Sort } from './sort';
8
+ export declare class List<T extends object = object> extends Action<T> {
9
+ columns: Columns<object>;
10
+ feed: Feed;
11
+ filter: Filter<object>;
12
+ sort: Sort<object>;
13
+ html(request: Request<T>, scope?: SearchType<T>): Promise<import("@itrocks/core-responses").HtmlResponse>;
14
+ json(request: Request<T>, scope?: SearchType<T>): Promise<import("@itrocks/core-responses").JsonResponse>;
15
+ }
package/cjs/list.js ADDED
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
3
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
4
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
5
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
6
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
7
+ var _, done = false;
8
+ for (var i = decorators.length - 1; i >= 0; i--) {
9
+ var context = {};
10
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
11
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
12
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
13
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
14
+ if (kind === "accessor") {
15
+ if (result === void 0) continue;
16
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
17
+ if (_ = accept(result.get)) descriptor.get = _;
18
+ if (_ = accept(result.set)) descriptor.set = _;
19
+ if (_ = accept(result.init)) initializers.unshift(_);
20
+ }
21
+ else if (_ = accept(result)) {
22
+ if (kind === "field") initializers.unshift(_);
23
+ else descriptor[key] = _;
24
+ }
25
+ }
26
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
27
+ done = true;
28
+ };
29
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
30
+ var useValue = arguments.length > 2;
31
+ for (var i = 0; i < initializers.length; i++) {
32
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
33
+ }
34
+ return useValue ? value : void 0;
35
+ };
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.List = void 0;
38
+ const action_1 = require("@itrocks/action");
39
+ const action_2 = require("@itrocks/action");
40
+ const action_3 = require("@itrocks/action");
41
+ const route_1 = require("@itrocks/route");
42
+ const route_2 = require("@itrocks/route");
43
+ const storage_1 = require("@itrocks/storage");
44
+ const columns_1 = require("./columns");
45
+ const feed_1 = require("./feed");
46
+ const filter_1 = require("./filter");
47
+ const persist_1 = require("./persist");
48
+ const persist_2 = require("./persist");
49
+ const sort_1 = require("./sort");
50
+ let List = (() => {
51
+ let _classDecorators = [(0, action_3.Need)('Store', 'new'), (0, route_1.Route)('/list')];
52
+ let _classDescriptor;
53
+ let _classExtraInitializers = [];
54
+ let _classThis;
55
+ let _classSuper = action_1.Action;
56
+ var List = class extends _classSuper {
57
+ static { _classThis = this; }
58
+ static {
59
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
60
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
61
+ List = _classThis = _classDescriptor.value;
62
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
63
+ __runInitializers(_classThis, _classExtraInitializers);
64
+ }
65
+ columns = new columns_1.Columns;
66
+ feed = new feed_1.Feed;
67
+ filter = new filter_1.Filter(this.columns);
68
+ sort = new sort_1.Sort(this.columns);
69
+ async html(request, scope) {
70
+ const columns = this.columns;
71
+ const feed = this.feed;
72
+ const filter = this.filter;
73
+ const sort = this.sort;
74
+ const type = request.type;
75
+ (0, persist_1.load)(this, request.request, type);
76
+ columns.getParams(request.request, type);
77
+ if (request.request.data.columns) {
78
+ (0, persist_2.save)(this, request.request, type);
79
+ return this.htmlResponse('', 204);
80
+ }
81
+ feed.getParams(request.request);
82
+ filter.getParams(request.request);
83
+ sort.getParams(request.request, type);
84
+ (0, persist_2.save)(this, request.request, type);
85
+ const options = feed.readOptions(filter.readOptions(sort.readOptions()));
86
+ const search = Object.assign(filter.searchObject(type), scope);
87
+ const objects = (await (0, storage_1.dataSource)().search(type, search, options)).map(object => ({
88
+ id: object.id,
89
+ properties: columns.propertiesOf(object)
90
+ }));
91
+ if (feed.offset) {
92
+ return this.htmlTemplateResponse({ objects, type }, request, feed.template);
93
+ }
94
+ const count = await (0, storage_1.dataSource)().count(type, search);
95
+ const route = (0, route_2.routeOf)(this);
96
+ const generalActions = [];
97
+ const selectionActions = [];
98
+ for (const action of (0, action_2.getActions)(type, route.slice(route.lastIndexOf('/') + 1))) {
99
+ const actions = (action.need === 'object') ? selectionActions : generalActions;
100
+ actions.push(action);
101
+ }
102
+ return this.htmlTemplateResponse({ columns, count, generalActions, objects, search: filter.search, selectionActions, type }, request, __dirname + '/list.html');
103
+ }
104
+ async json(request, scope) {
105
+ const objects = await (0, storage_1.dataSource)().search(request.type, scope);
106
+ return this.jsonResponse(objects);
107
+ }
108
+ };
109
+ return List = _classThis;
110
+ })();
111
+ exports.List = List;
112
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../src/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { Request } from '@itrocks/request-response';
2
+ import { Option } from '@itrocks/storage';
3
+ import { Type } from '@itrocks/class-type';
4
+ export declare abstract class Parameter {
5
+ abstract getParams(request: Request, type?: Type): void;
6
+ readOptions(options?: Option[]): Option[];
7
+ serialize(): any;
8
+ unserialize(_data: any, _type: Type): void;
9
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Parameter = void 0;
4
+ class Parameter {
5
+ readOptions(options = new Array) {
6
+ return options;
7
+ }
8
+ serialize() { }
9
+ unserialize(_data, _type) { }
10
+ }
11
+ exports.Parameter = Parameter;
12
+ //# sourceMappingURL=parameter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parameter.js","sourceRoot":"","sources":["../src/parameter.ts"],"names":[],"mappings":";;;AAIA,MAAsB,SAAS;IAK9B,WAAW,CAAC,UAAU,IAAI,KAAa;QAEtC,OAAO,OAAO,CAAA;IACf,CAAC;IAED,SAAS,KACR,CAAC;IAEF,WAAW,CAAC,KAAU,EAAE,KAAW,IAClC,CAAC;CAEF;AAhBD,8BAgBC"}
@@ -0,0 +1,8 @@
1
+ import { Type } from '@itrocks/class-type';
2
+ import { Request } from '@itrocks/request-response';
3
+ interface Container {
4
+ [s: string]: any;
5
+ }
6
+ export declare function load(list: Container, request: Request, type: Type): {} | undefined;
7
+ export declare function save(list: Container, request: Request, type: Type): void;
8
+ export {};
package/cjs/persist.js ADDED
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.load = load;
4
+ exports.save = save;
5
+ const route_1 = require("@itrocks/route");
6
+ const parameter_1 = require("./parameter");
7
+ function load(list, request, type) {
8
+ if (!request.session.list)
9
+ return {};
10
+ const serialized = request.session.list[(0, route_1.routeOf)(type)];
11
+ if (!serialized)
12
+ return {};
13
+ for (const key of Object.keys(list)) {
14
+ const parameter = list[key];
15
+ if (!(parameter instanceof parameter_1.Parameter) || !serialized[key])
16
+ continue;
17
+ parameter.unserialize(serialized[key], type);
18
+ }
19
+ }
20
+ function save(list, request, type) {
21
+ if (!request.session.list) {
22
+ request.session.list = {};
23
+ }
24
+ const serialized = {};
25
+ for (const key of Object.keys(list)) {
26
+ const parameter = list[key];
27
+ if (!(parameter instanceof parameter_1.Parameter))
28
+ continue;
29
+ serialized[key] = parameter.serialize();
30
+ }
31
+ request.session.list[(0, route_1.routeOf)(type)] = serialized;
32
+ }
33
+ //# sourceMappingURL=persist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persist.js","sourceRoot":"","sources":["../src/persist.ts"],"names":[],"mappings":";;AAUA,oBAUC;AAED,oBAYC;AAhCD,0CAA0C;AAC1C,2CAAuC;AAOvC,SAAgB,IAAI,CAAC,IAAe,EAAE,OAAgB,EAAE,IAAU;IAEjE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI;QAAE,OAAO,EAAE,CAAA;IACpC,MAAM,UAAU,GAAc,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAA,eAAO,EAAC,IAAI,CAAC,CAAC,CAAA;IACjE,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,CAAA;IAC1B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAA;QAC3B,IAAI,CAAC,CAAC,SAAS,YAAY,qBAAS,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAQ;QACnE,SAAS,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAA;IAC7C,CAAC;AACF,CAAC;AAED,SAAgB,IAAI,CAAC,IAAe,EAAE,OAAgB,EAAE,IAAU;IAEjE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAC3B,OAAO,CAAC,OAAO,CAAC,IAAI,GAAG,EAAE,CAAA;IAC1B,CAAC;IACD,MAAM,UAAU,GAAc,EAAE,CAAA;IAChC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAA;QAC3B,IAAI,CAAC,CAAC,SAAS,YAAY,qBAAS,CAAC;YAAE,SAAQ;QAC/C,UAAU,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,SAAS,EAAE,CAAA;IACxC,CAAC;IACD,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAA,eAAO,EAAC,IAAI,CAAC,CAAC,GAAG,UAAU,CAAA;AACjD,CAAC"}
package/cjs/sort.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ import { Type } from '@itrocks/class-type';
2
+ import { Request } from '@itrocks/request-response';
3
+ import { Option } from '@itrocks/storage';
4
+ import { Sort as SortOption } from '@itrocks/storage';
5
+ import { Columns } from './columns';
6
+ import { Parameter } from './parameter';
7
+ interface Serialized {
8
+ [key: string]: boolean;
9
+ }
10
+ interface Sortable {
11
+ reverse: boolean;
12
+ sort?: number;
13
+ }
14
+ export declare class Sort<T extends object> extends Parameter {
15
+ columns: Columns<T> & Sortable[];
16
+ sorted?: Serialized;
17
+ constructor(columns: Columns<T>);
18
+ getParams(request: Request, type: Type<T>): void;
19
+ readOptions(options?: Option[]): Option[];
20
+ serialize(): Serialized | undefined;
21
+ sortOption(): SortOption | Type<SortOption>;
22
+ unserialize(data: Serialized): void;
23
+ }
24
+ export {};
package/cjs/sort.js ADDED
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Sort = void 0;
4
+ const sort_1 = require("@itrocks/sort");
5
+ const sort_2 = require("@itrocks/sort");
6
+ const storage_1 = require("@itrocks/storage");
7
+ const parameter_1 = require("./parameter");
8
+ class Sort extends parameter_1.Parameter {
9
+ columns;
10
+ sorted;
11
+ constructor(columns) {
12
+ super();
13
+ this.columns = columns;
14
+ }
15
+ getParams(request, type) {
16
+ let sortProperties;
17
+ let sortReverse;
18
+ if (this.sorted) {
19
+ sortProperties = Object.keys(this.sorted);
20
+ sortReverse = Object.values(this.sorted);
21
+ }
22
+ else {
23
+ for (const option of this.readOptions()) {
24
+ if (option instanceof storage_1.Sort) {
25
+ sortProperties = option.properties.map(property => '' + property);
26
+ sortReverse = option.properties.map(property => property instanceof sort_1.Reverse);
27
+ }
28
+ }
29
+ if (!sortProperties || !sortReverse) {
30
+ sortProperties = (0, sort_2.sortOf)(type).map(property => '' + property);
31
+ sortReverse = (0, sort_2.sortOf)(type).map(property => property instanceof sort_1.Reverse);
32
+ }
33
+ }
34
+ if (typeof request.data.sort === 'string') {
35
+ const reverse = 'reverse' in request.data;
36
+ const sort = request.data.sort;
37
+ const index = sortProperties.indexOf(sort);
38
+ if (index >= 0) {
39
+ sortProperties.splice(index, 1);
40
+ sortReverse.splice(index, 1);
41
+ }
42
+ sortProperties.unshift(sort);
43
+ sortReverse.unshift(reverse);
44
+ this.sorted = undefined;
45
+ }
46
+ if (!this.sorted) {
47
+ this.sorted = {};
48
+ for (const index in sortProperties) {
49
+ this.sorted[sortProperties[index]] = sortReverse[index];
50
+ }
51
+ }
52
+ for (const column of this.columns) {
53
+ const sortIndex = sortProperties.indexOf(column.name.toString());
54
+ column.reverse = !!sortReverse[sortIndex];
55
+ column.sort = (sortIndex + 1) || undefined;
56
+ }
57
+ }
58
+ readOptions(options = new Array) {
59
+ options.push(this.sortOption());
60
+ return options;
61
+ }
62
+ serialize() {
63
+ return this.sorted;
64
+ }
65
+ sortOption() {
66
+ if (!this.sorted)
67
+ return storage_1.Sort;
68
+ const properties = new Array;
69
+ for (const [propertyName, reverse] of Object.entries(this.sorted)) {
70
+ properties.push(reverse ? new sort_1.Reverse(propertyName) : propertyName);
71
+ }
72
+ return new storage_1.Sort(properties);
73
+ }
74
+ unserialize(data) {
75
+ this.sorted = data;
76
+ }
77
+ }
78
+ exports.Sort = Sort;
79
+ //# sourceMappingURL=sort.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sort.js","sourceRoot":"","sources":["../src/sort.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -67,7 +67,8 @@
67
67
  "build": "npm run build:cjs && npm run build:css && npm run build:front",
68
68
  "build:cjs": "tsc && node -e \"const fs=require('node:fs'),path=require('node:path');for(const file of fs.readdirSync('src'))if(file.endsWith('.html'))fs.copyFileSync(path.join('src',file),path.join('cjs',file))\"",
69
69
  "build:css": "sass --no-source-map src/list.scss:list.css && node -e \"const fs=require('node:fs'),path=require('node:path');for(const file of fs.readdirSync('src'))if(file.endsWith('.svg'))fs.copyFileSync(path.join('src',file),file)\"",
70
- "build:front": "tsc -p src/front/tsconfig.json"
70
+ "build:front": "tsc -p src/front/tsconfig.json",
71
+ "test": "npm run build:cjs && node --test \"test/**/*.test.mjs\""
71
72
  },
72
- "version": "0.6.0"
73
+ "version": "0.7.0"
73
74
  }