@sealcode/sealgen 0.10.4 → 0.10.5
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/@types/page/list.d.ts +6 -4
- package/lib/page/list.js +10 -1
- package/lib/templates/list.js +18 -11
- package/package.json +1 -1
- package/src/page/list.ts +15 -8
- package/src/templates/list.ts +18 -11
package/@types/page/list.d.ts
CHANGED
|
@@ -12,6 +12,10 @@ export declare const BaseListPageFields: {
|
|
|
12
12
|
readonly itemsPerPage: NumberField<12, false>;
|
|
13
13
|
readonly sort: SimpleFormField<false>;
|
|
14
14
|
};
|
|
15
|
+
export type ListSort = {
|
|
16
|
+
field: string;
|
|
17
|
+
order: "asc" | "desc";
|
|
18
|
+
};
|
|
15
19
|
export declare abstract class ListPage<ItemType, F extends typeof BaseListPageFields> extends Page<F> {
|
|
16
20
|
abstract getItems(ctx: Context, page: number, itemsPerPage: number, values: Record<string, FormDataValue>): Promise<ItemType[]>;
|
|
17
21
|
abstract getTotalPages(ctx: Context, itemsPerPage: number, values: Record<string, FormDataValue>): Promise<number>;
|
|
@@ -29,13 +33,11 @@ export declare abstract class ListPage<ItemType, F extends typeof BaseListPageFi
|
|
|
29
33
|
renderPagination(ctx: Context, values: Record<string, FormDataValue>): Promise<FlatTemplatable>;
|
|
30
34
|
private renderPageButton;
|
|
31
35
|
getFilterValues(ctx: Context): Promise<Record<string, unknown>>;
|
|
32
|
-
getSort(ctx: Context): Promise<
|
|
33
|
-
field: string;
|
|
34
|
-
order: "asc" | "desc";
|
|
35
|
-
} | null>;
|
|
36
|
+
getSort(ctx: Context): Promise<ListSort | null>;
|
|
36
37
|
makeSortLink(ctx: Context, field: string, order: "asc" | "desc"): string;
|
|
37
38
|
renderFilters(ctx: Context): Promise<FlatTemplatable>;
|
|
38
39
|
renderHeading(ctx: Context, field: string, label?: string): Promise<FlatTemplatable>;
|
|
40
|
+
getDefaultSort(_: Context): ListSort | null;
|
|
39
41
|
renderTableHead(ctx: Context, fields: {
|
|
40
42
|
field: string;
|
|
41
43
|
label?: string;
|
package/lib/page/list.js
CHANGED
|
@@ -135,7 +135,13 @@ ${this.renderListContainer(ctx, this.renderItems(ctx, values))}`;
|
|
|
135
135
|
}
|
|
136
136
|
async getSort(ctx) {
|
|
137
137
|
const { sort } = await this.extractRawValues(ctx);
|
|
138
|
-
|
|
138
|
+
const decoded = decodeSort(sort);
|
|
139
|
+
if (decoded === null) {
|
|
140
|
+
return this.getDefaultSort(ctx);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
return decoded;
|
|
144
|
+
}
|
|
139
145
|
}
|
|
140
146
|
makeSortLink(ctx, field, order) {
|
|
141
147
|
const url = new URL(ctx.url, "https://example.com");
|
|
@@ -169,6 +175,9 @@ ${this.renderListContainer(ctx, this.renderItems(ctx, values))}`;
|
|
|
169
175
|
>
|
|
170
176
|
</th>`;
|
|
171
177
|
}
|
|
178
|
+
getDefaultSort(_) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
172
181
|
renderTableHead(ctx, fields) {
|
|
173
182
|
return (0, tempstream_1.tempstream /* HTML */) `<thead>
|
|
174
183
|
<tr>
|
package/lib/templates/list.js
CHANGED
|
@@ -33,7 +33,12 @@ import { CollectionItem, Field } from "sealious";
|
|
|
33
33
|
import { FlatTemplatable, tempstream } from "tempstream";
|
|
34
34
|
import { ${uppercase_collection} } from "${rel("src/back/collections/collections.js")}";
|
|
35
35
|
import html from "${rel("src/back/html.js")}";
|
|
36
|
-
import {
|
|
36
|
+
import {
|
|
37
|
+
SealiousItemListPage,
|
|
38
|
+
BaseListPageFields,
|
|
39
|
+
DefaultListFilters,
|
|
40
|
+
ListFilterRender,
|
|
41
|
+
} from "@sealcode/sealgen";;
|
|
37
42
|
import qs from "qs";
|
|
38
43
|
import { is, predicates } from "@sealcode/ts-predicates";
|
|
39
44
|
|
|
@@ -47,7 +52,7 @@ ${collection_fields
|
|
|
47
52
|
.join(",\n")}
|
|
48
53
|
] as {
|
|
49
54
|
field: keyof (typeof PatronEvents)["fields"];
|
|
50
|
-
render?:
|
|
55
|
+
render?: ListFilterRender;
|
|
51
56
|
}[];
|
|
52
57
|
|
|
53
58
|
const displayFields = [
|
|
@@ -64,7 +69,11 @@ ${collection_fields
|
|
|
64
69
|
return ` {
|
|
65
70
|
field: "${field.name}",
|
|
66
71
|
label: "${field.name}",
|
|
67
|
-
format: (v: number) => {
|
|
72
|
+
format: (v: number) => {
|
|
73
|
+
const d = new Date();
|
|
74
|
+
d.setTime(v);
|
|
75
|
+
return d.toString().split(" ").slice(1, 5).join(" ");
|
|
76
|
+
},
|
|
68
77
|
}`;
|
|
69
78
|
}
|
|
70
79
|
return ` { field: "${field.name}", label: "${field.name}" }`;
|
|
@@ -109,16 +118,14 @@ export default new (class ${action_name}Page extends SealiousItemListPage<
|
|
|
109
118
|
value="\${value}"
|
|
110
119
|
/>\`;
|
|
111
120
|
})}
|
|
112
|
-
\${filterFields.map((
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
121
|
+
\${filterFields.map(({ field, render }) => {
|
|
122
|
+
if (!render) {
|
|
123
|
+
render = DefaultListFilters.fallback;
|
|
124
|
+
}
|
|
116
125
|
|
|
117
126
|
return (
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
this.collection.fields[field_name]
|
|
121
|
-
) || ""
|
|
127
|
+
render(filter_values[field] || "", this.collection.fields[field]) ||
|
|
128
|
+
""
|
|
122
129
|
);
|
|
123
130
|
})}
|
|
124
131
|
<input type="submit" />
|
package/package.json
CHANGED
package/src/page/list.ts
CHANGED
|
@@ -18,10 +18,10 @@ export const BaseListPageFields = <const>{
|
|
|
18
18
|
sort: new SimpleFormField(false),
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
+
export type ListSort = { field: string; order: "asc" | "desc" };
|
|
22
|
+
|
|
21
23
|
const SORT_SEPARATOR = ":";
|
|
22
|
-
function decodeSort(
|
|
23
|
-
s: unknown
|
|
24
|
-
): { field: string; order: "asc" | "desc" } | null {
|
|
24
|
+
function decodeSort(s: unknown): ListSort | null {
|
|
25
25
|
if (typeof s !== "string" || !s.includes(SORT_SEPARATOR)) {
|
|
26
26
|
return null;
|
|
27
27
|
}
|
|
@@ -38,7 +38,7 @@ function decodeSort(
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
function encodeSort(field: string, order: "asc" | "desc") {
|
|
41
|
+
function encodeSort(field: string, order: "asc" | "desc"): string {
|
|
42
42
|
return [field, order].join(SORT_SEPARATOR);
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -185,11 +185,14 @@ ${this.renderListContainer(ctx, this.renderItems(ctx, values))}`;
|
|
|
185
185
|
return filter;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
async getSort(
|
|
189
|
-
ctx: Context
|
|
190
|
-
): Promise<{ field: string; order: "asc" | "desc" } | null> {
|
|
188
|
+
async getSort(ctx: Context): Promise<ListSort | null> {
|
|
191
189
|
const { sort } = await this.extractRawValues(ctx);
|
|
192
|
-
|
|
190
|
+
const decoded = decodeSort(sort);
|
|
191
|
+
if (decoded === null) {
|
|
192
|
+
return this.getDefaultSort(ctx);
|
|
193
|
+
} else {
|
|
194
|
+
return decoded;
|
|
195
|
+
}
|
|
193
196
|
}
|
|
194
197
|
|
|
195
198
|
makeSortLink(ctx: Context, field: string, order: "asc" | "desc"): string {
|
|
@@ -238,6 +241,10 @@ ${this.renderListContainer(ctx, this.renderItems(ctx, values))}`;
|
|
|
238
241
|
</th>`;
|
|
239
242
|
}
|
|
240
243
|
|
|
244
|
+
getDefaultSort(_: Context): ListSort | null {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
|
|
241
248
|
renderTableHead(
|
|
242
249
|
ctx: Context,
|
|
243
250
|
fields: { field: string; label?: string }[]
|
package/src/templates/list.ts
CHANGED
|
@@ -39,7 +39,12 @@ import { ${uppercase_collection} } from "${rel(
|
|
|
39
39
|
"src/back/collections/collections.js"
|
|
40
40
|
)}";
|
|
41
41
|
import html from "${rel("src/back/html.js")}";
|
|
42
|
-
import {
|
|
42
|
+
import {
|
|
43
|
+
SealiousItemListPage,
|
|
44
|
+
BaseListPageFields,
|
|
45
|
+
DefaultListFilters,
|
|
46
|
+
ListFilterRender,
|
|
47
|
+
} from "@sealcode/sealgen";;
|
|
43
48
|
import qs from "qs";
|
|
44
49
|
import { is, predicates } from "@sealcode/ts-predicates";
|
|
45
50
|
|
|
@@ -58,7 +63,7 @@ ${collection_fields
|
|
|
58
63
|
.join(",\n")}
|
|
59
64
|
] as {
|
|
60
65
|
field: keyof (typeof PatronEvents)["fields"];
|
|
61
|
-
render?:
|
|
66
|
+
render?: ListFilterRender;
|
|
62
67
|
}[];
|
|
63
68
|
|
|
64
69
|
const displayFields = [
|
|
@@ -75,7 +80,11 @@ ${collection_fields
|
|
|
75
80
|
return ` {
|
|
76
81
|
field: "${field.name}",
|
|
77
82
|
label: "${field.name}",
|
|
78
|
-
format: (v: number) => {
|
|
83
|
+
format: (v: number) => {
|
|
84
|
+
const d = new Date();
|
|
85
|
+
d.setTime(v);
|
|
86
|
+
return d.toString().split(" ").slice(1, 5).join(" ");
|
|
87
|
+
},
|
|
79
88
|
}`;
|
|
80
89
|
}
|
|
81
90
|
return ` { field: "${field.name}", label: "${field.name}" }`;
|
|
@@ -120,16 +129,14 @@ export default new (class ${action_name}Page extends SealiousItemListPage<
|
|
|
120
129
|
value="\${value}"
|
|
121
130
|
/>\`;
|
|
122
131
|
})}
|
|
123
|
-
\${filterFields.map((
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
132
|
+
\${filterFields.map(({ field, render }) => {
|
|
133
|
+
if (!render) {
|
|
134
|
+
render = DefaultListFilters.fallback;
|
|
135
|
+
}
|
|
127
136
|
|
|
128
137
|
return (
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
this.collection.fields[field_name]
|
|
132
|
-
) || ""
|
|
138
|
+
render(filter_values[field] || "", this.collection.fields[field]) ||
|
|
139
|
+
""
|
|
133
140
|
);
|
|
134
141
|
})}
|
|
135
142
|
<input type="submit" />
|