@sealcode/sealgen 0.8.52 → 0.9.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/@types/forms/controls/array.d.ts +1 -1
- package/@types/forms/controls/checkbox-group.d.ts +1 -1
- package/@types/forms/controls/collapsible-field-group.d.ts +1 -1
- package/@types/forms/controls/derived-frame.d.ts +1 -0
- package/@types/forms/controls/dropdown.d.ts +2 -2
- package/@types/forms/controls/form-field-control.d.ts +1 -1
- package/@types/forms/controls/html.d.ts +1 -1
- package/@types/forms/controls/multiple-files.d.ts +1 -1
- package/@types/forms/controls/number.d.ts +1 -1
- package/@types/forms/controls/simple-input.d.ts +1 -1
- package/@types/forms/controls/tickable.d.ts +1 -1
- package/@types/forms/fields/field.d.ts +6 -6
- package/@types/forms/fields/file.d.ts +1 -1
- package/@types/forms/form.d.ts +7 -7
- package/@types/index.d.ts +1 -0
- package/@types/page/list.d.ts +13 -17
- package/@types/page/mountable-with-fields.d.ts +2 -2
- package/@types/page/props-parser.d.ts +1 -1
- package/@types/page/sealious-list.d.ts +18 -0
- package/@types/utils/utils.d.ts +3 -3
- package/lib/add-collection.js +7 -7
- package/lib/add-route.js +8 -8
- package/lib/add-route.test.js +4 -4
- package/lib/build.js +44 -11
- package/lib/components/components.js +5 -1
- package/lib/components/tabs.js +2 -2
- package/lib/components/toggle-modal.js +2 -2
- package/lib/find-scss-includes.js +3 -3
- package/lib/forms/controls/array.js +5 -5
- package/lib/forms/controls/big-radio-group.js +2 -2
- package/lib/forms/controls/checkboxed-list-input.js +3 -3
- package/lib/forms/controls/collapsible-field-group.js +1 -1
- package/lib/forms/controls/controls.js +5 -1
- package/lib/forms/controls/derived-frame.js +3 -3
- package/lib/forms/controls/derived.js +2 -2
- package/lib/forms/controls/dropdown.js +2 -2
- package/lib/forms/controls/editable-collection-subset.js +3 -3
- package/lib/forms/controls/field-group.js +1 -1
- package/lib/forms/controls/file.js +1 -1
- package/lib/forms/controls/hidden-input.js +1 -1
- package/lib/forms/controls/multiple-files.js +5 -5
- package/lib/forms/controls/multiple-photos.js +1 -1
- package/lib/forms/controls/photo.js +1 -1
- package/lib/forms/controls/simple-input.js +2 -2
- package/lib/forms/controls/tickable.js +3 -3
- package/lib/forms/fields/boolean.js +3 -3
- package/lib/forms/fields/checkboxed-list.js +3 -3
- package/lib/forms/fields/enum-multiple.js +3 -3
- package/lib/forms/fields/enum.js +2 -2
- package/lib/forms/fields/field.js +6 -2
- package/lib/forms/fields/file.js +6 -6
- package/lib/forms/fields/number.js +5 -5
- package/lib/forms/fields/pick-from-list.js +1 -1
- package/lib/forms/fields/regexp.js +2 -2
- package/lib/forms/fields/simple-form-field.js +4 -4
- package/lib/forms/form.js +9 -9
- package/lib/forms/form.test.js +12 -12
- package/lib/forms/multiform.js +5 -5
- package/lib/forms/multiform.test.js +26 -26
- package/lib/generate-collections.js +9 -5
- package/lib/generate-routes.js +13 -9
- package/lib/index.js +6 -1
- package/lib/make-env.js +1 -1
- package/lib/make-hidden-inputs.js +3 -3
- package/lib/page/list.js +85 -65
- package/lib/page/mountable-with-fields.js +2 -2
- package/lib/page/page.js +1 -1
- package/lib/page/sealious-list.js +53 -0
- package/lib/page/stateful-page.js +9 -9
- package/lib/templates/form.js +1 -1
- package/lib/templates/list.js +10 -9
- package/lib/templates/multiform.js +1 -1
- package/lib/templates/page.js +1 -1
- package/lib/templates/route-test.js +1 -1
- package/lib/templates/stateful-page.js +1 -1
- package/lib/test_utils/locator_is_visible.js +1 -1
- package/lib/utils/exec.js +1 -1
- package/lib/utils/import-path.js +2 -2
- package/lib/utils/input-wrapper.js +1 -1
- package/lib/utils/list-collections.js +2 -2
- package/lib/utils/prettier.js +6 -2
- package/lib/utils/question.js +1 -1
- package/lib/utils/render-attributes.js +1 -1
- package/lib/utils/utils.js +5 -1
- package/lib/utils/walk.js +1 -1
- package/package.json +2 -2
- package/src/add-route.ts +1 -1
- package/src/build.ts +56 -1
- package/src/generate-collections.ts +1 -1
- package/src/generate-routes.ts +1 -1
- package/src/index.ts +1 -0
- package/src/page/list.ts +106 -96
- package/src/page/sealious-list.ts +76 -0
- package/src/templates/list.ts +8 -7
- package/src/utils/import-path.ts +1 -1
package/src/build.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { build, BuildResult } from "esbuild";
|
|
2
|
+
import { promises as fs } from "fs";
|
|
2
3
|
import { sassPlugin } from "esbuild-sass-plugin";
|
|
3
4
|
import * as chokidar from "chokidar";
|
|
4
5
|
import { default as glob } from "tiny-glob";
|
|
@@ -7,6 +8,15 @@ import { sleep } from "./utils/sleep";
|
|
|
7
8
|
import { generateCollections } from "./generate-collections";
|
|
8
9
|
import { generateRoutes } from "./generate-routes";
|
|
9
10
|
|
|
11
|
+
const generate_names = (function* generate_names() {
|
|
12
|
+
let base_name = "______unique_import_";
|
|
13
|
+
let count = 0;
|
|
14
|
+
while (true) {
|
|
15
|
+
yield base_name + count;
|
|
16
|
+
count++;
|
|
17
|
+
}
|
|
18
|
+
})();
|
|
19
|
+
|
|
10
20
|
async function build_ts() {
|
|
11
21
|
await Promise.all([generateCollections(), generateRoutes()]);
|
|
12
22
|
const entryPoints = (await glob("./src/back/**/*.ts")).filter(
|
|
@@ -20,7 +30,52 @@ async function build_ts() {
|
|
|
20
30
|
logLevel: "info",
|
|
21
31
|
platform: "node",
|
|
22
32
|
target: "es2022",
|
|
23
|
-
format: "
|
|
33
|
+
format: "esm",
|
|
34
|
+
plugins: [
|
|
35
|
+
{
|
|
36
|
+
name: "remove-named-imports", // named imports sometime cause some esm incompatibilities, like the "is a CommonJS module, which may not support all module.exports as named exports." error
|
|
37
|
+
setup(build) {
|
|
38
|
+
build.onLoad({ filter: /.*/ }, async ({ path }) => {
|
|
39
|
+
const named_and_default_regex =
|
|
40
|
+
/^import\s+((\S+),\s+)?({\s*[^}]+})\s+from\s+("[^"]+");\s*$/gm;
|
|
41
|
+
|
|
42
|
+
const old_content = await fs.readFile(
|
|
43
|
+
path,
|
|
44
|
+
"utf-8"
|
|
45
|
+
);
|
|
46
|
+
const contents = old_content.replace(
|
|
47
|
+
named_and_default_regex,
|
|
48
|
+
(
|
|
49
|
+
entire_string,
|
|
50
|
+
default_import_name,
|
|
51
|
+
_,
|
|
52
|
+
all_named,
|
|
53
|
+
module_path
|
|
54
|
+
) => {
|
|
55
|
+
const new_name =
|
|
56
|
+
generate_names.next().value;
|
|
57
|
+
return `import * as ${new_name} from ${module_path}; ${
|
|
58
|
+
default_import_name
|
|
59
|
+
? `const ${default_import_name.replace(
|
|
60
|
+
",",
|
|
61
|
+
""
|
|
62
|
+
)} = ${new_name}`
|
|
63
|
+
: ""
|
|
64
|
+
}; const ${all_named.replaceAll(
|
|
65
|
+
/\s+as\s+/g,
|
|
66
|
+
": "
|
|
67
|
+
)} = ${
|
|
68
|
+
/\s+default\s+as/.test(all_named)
|
|
69
|
+
? `${new_name};`
|
|
70
|
+
: `${new_name}.default || ${new_name};`
|
|
71
|
+
}`;
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
return { contents, loader: "ts" };
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
],
|
|
24
79
|
});
|
|
25
80
|
} catch (e) {
|
|
26
81
|
console.error(e.message);
|
package/src/generate-routes.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ export * from "./forms/form";
|
|
|
18
18
|
export * from "./page/props-parser";
|
|
19
19
|
export * from "./utils/utils";
|
|
20
20
|
export * from "./page/list";
|
|
21
|
+
export * from "./page/sealious-list";
|
|
21
22
|
export * from "./utils/translate";
|
|
22
23
|
export * as sanitize from "./sanitize";
|
|
23
24
|
export * from "./forms/multiform";
|
package/src/page/list.ts
CHANGED
|
@@ -1,21 +1,13 @@
|
|
|
1
1
|
import { Context } from "koa";
|
|
2
|
-
import {
|
|
3
|
-
Collection,
|
|
4
|
-
CollectionItem,
|
|
5
|
-
ItemList,
|
|
6
|
-
Context as SealiousContext,
|
|
7
|
-
CollectionInput,
|
|
8
|
-
} from "sealious";
|
|
9
|
-
|
|
10
2
|
import { Templatable, tempstream, FlatTemplatable } from "tempstream";
|
|
11
|
-
import { peopleWhoCan } from "./access-control";
|
|
12
3
|
import { Page } from "./page";
|
|
13
4
|
import { ShapeToType } from "@sealcode/ts-predicates";
|
|
14
5
|
import { FormControl } from "../forms/controls/controls";
|
|
15
|
-
import { FormField, NumberField } from "../forms/fields/field";
|
|
6
|
+
import { FormField, NumberField, SimpleFormField } from "../forms/fields/field";
|
|
16
7
|
import { naturalNumbers, UrlWithNewParams } from "../utils/utils";
|
|
17
8
|
import { FormDataValue } from "..";
|
|
18
9
|
import { makeHiddenInputs } from "../make-hidden-inputs";
|
|
10
|
+
import qs from "qs";
|
|
19
11
|
|
|
20
12
|
export const BasePagePropsShape = <const>{};
|
|
21
13
|
export type BasePageProps = ShapeToType<typeof BasePagePropsShape>;
|
|
@@ -23,8 +15,33 @@ export type BasePageProps = ShapeToType<typeof BasePagePropsShape>;
|
|
|
23
15
|
export const BaseListPageFields = <const>{
|
|
24
16
|
page: new NumberField(false, 1),
|
|
25
17
|
itemsPerPage: new NumberField(false, 12),
|
|
18
|
+
sort: new SimpleFormField(false),
|
|
26
19
|
};
|
|
27
20
|
|
|
21
|
+
const SORT_SEPARATOR = ":";
|
|
22
|
+
function decodeSort(
|
|
23
|
+
s: unknown
|
|
24
|
+
): { field: string; order: "asc" | "desc" } | null {
|
|
25
|
+
if (typeof s !== "string" || !s.includes(SORT_SEPARATOR)) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
let order = s.split(SORT_SEPARATOR)[1];
|
|
29
|
+
const field = s.split(SORT_SEPARATOR)[0];
|
|
30
|
+
if (order !== "asc" && order !== "desc") {
|
|
31
|
+
order = "asc";
|
|
32
|
+
return {
|
|
33
|
+
field,
|
|
34
|
+
order: order as "asc",
|
|
35
|
+
};
|
|
36
|
+
} else {
|
|
37
|
+
return { field, order };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function encodeSort(field: string, order: "asc" | "desc") {
|
|
42
|
+
return [field, order].join(SORT_SEPARATOR);
|
|
43
|
+
}
|
|
44
|
+
|
|
28
45
|
export abstract class ListPage<
|
|
29
46
|
ItemType,
|
|
30
47
|
F extends typeof BaseListPageFields
|
|
@@ -103,35 +120,42 @@ ${this.renderListContainer(ctx, this.renderItems(ctx, values))}`;
|
|
|
103
120
|
const { itemsPerPage, page } = await this.getPaginationConfig(ctx);
|
|
104
121
|
const totalIems = await this.getTotalPages(ctx, itemsPerPage, values);
|
|
105
122
|
|
|
106
|
-
return tempstream/* HTML */ `<
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
123
|
+
return tempstream/* HTML */ `<div class="list-pagination">
|
|
124
|
+
<div class="list-pagination__left">
|
|
125
|
+
${page > 1
|
|
126
|
+
? this.renderPageButton(ctx, 1, "Pierwsza strona")
|
|
127
|
+
: ""}
|
|
128
|
+
${page > 1
|
|
129
|
+
? this.renderPageButton(ctx, page - 1, "Poprzednia strona")
|
|
130
|
+
: ""}
|
|
131
|
+
</div>
|
|
132
|
+
<div class="list-pagination__center">
|
|
133
|
+
<select onchange="if (this.value) Turbo.visit(this.value)">
|
|
134
|
+
${Array.from(naturalNumbers(1, totalIems)).map(
|
|
135
|
+
(n) => /* HTML */ `<option
|
|
136
|
+
value="${UrlWithNewParams(
|
|
137
|
+
ctx,
|
|
138
|
+
//eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
139
|
+
this.propsParser.overwriteProp(ctx, {
|
|
140
|
+
page: n,
|
|
141
|
+
} as Partial<Record<string, unknown>>)
|
|
142
|
+
)}"
|
|
143
|
+
${page === n ? "selected" : ""}
|
|
144
|
+
>
|
|
145
|
+
${n}
|
|
146
|
+
</option>`
|
|
147
|
+
)}
|
|
148
|
+
</select>
|
|
149
|
+
</div>
|
|
150
|
+
<div class="list-pagination__right">
|
|
151
|
+
${page < totalIems
|
|
152
|
+
? this.renderPageButton(ctx, page + 1, "Następna strona")
|
|
153
|
+
: ""}
|
|
154
|
+
${page < totalIems
|
|
155
|
+
? this.renderPageButton(ctx, totalIems, "Ostatnia strona")
|
|
156
|
+
: ""}
|
|
157
|
+
</div>
|
|
158
|
+
</div>`;
|
|
135
159
|
}
|
|
136
160
|
|
|
137
161
|
private renderPageButton(ctx: Context, page: number, text: string) {
|
|
@@ -158,6 +182,21 @@ ${this.renderListContainer(ctx, this.renderItems(ctx, values))}`;
|
|
|
158
182
|
return filter;
|
|
159
183
|
}
|
|
160
184
|
|
|
185
|
+
async getSort(
|
|
186
|
+
ctx: Context
|
|
187
|
+
): Promise<{ field: string; order: "asc" | "desc" } | null> {
|
|
188
|
+
const { sort } = await this.extractRawValues(ctx);
|
|
189
|
+
return decodeSort(sort);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
makeSortLink(ctx: Context, field: string, order: "asc" | "desc"): string {
|
|
193
|
+
const url = new URL(ctx.url, "https://example.com");
|
|
194
|
+
const params = qs.parse(url.search.slice(1));
|
|
195
|
+
params.sort = encodeSort(field, order);
|
|
196
|
+
url.search = qs.stringify(params);
|
|
197
|
+
return url.pathname + url.search;
|
|
198
|
+
}
|
|
199
|
+
|
|
161
200
|
async renderFilters(ctx: Context): Promise<FlatTemplatable> {
|
|
162
201
|
const values = await this.extractRawValues(ctx);
|
|
163
202
|
return tempstream/* HTML */ `<form method="GET">
|
|
@@ -177,64 +216,35 @@ ${this.renderListContainer(ctx, this.renderItems(ctx, values))}`;
|
|
|
177
216
|
})}
|
|
178
217
|
</form>`;
|
|
179
218
|
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export abstract class SealiousItemListPage<
|
|
183
|
-
C extends Collection,
|
|
184
|
-
F extends typeof BaseListPageFields
|
|
185
|
-
> extends ListPage<CollectionItem<C>, F> {
|
|
186
|
-
constructor(public collection: C) {
|
|
187
|
-
super();
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
async getContextForList(ctx: Context): Promise<SealiousContext> {
|
|
191
|
-
return ctx.$context;
|
|
192
|
-
}
|
|
193
219
|
|
|
194
|
-
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
async makeQuery(ctx: Context): Promise<ItemList<C>> {
|
|
215
|
-
return this.collection.list(await this.getContextForList(ctx));
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
async getItems(
|
|
220
|
+
renderHeading(ctx: Context, field: string, label = field): FlatTemplatable {
|
|
221
|
+
const current_sort = decodeSort(
|
|
222
|
+
qs.parse(
|
|
223
|
+
new URL(ctx.url, "https://www.example.com").search.slice(1)
|
|
224
|
+
)["sort"]
|
|
225
|
+
);
|
|
226
|
+
const current_order =
|
|
227
|
+
current_sort?.field == field ? current_sort.order : null;
|
|
228
|
+
const order = current_order == "desc" ? "asc" : "desc";
|
|
229
|
+
return /* HTML */ `<th>
|
|
230
|
+
<a href="${this.makeSortLink(ctx, field, order)}"
|
|
231
|
+
>${label}
|
|
232
|
+
${(current_order && (current_order == "asc" ? "↑" : "↓")) ||
|
|
233
|
+
""}</a
|
|
234
|
+
>
|
|
235
|
+
</th>`;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
renderTableHead(
|
|
219
239
|
ctx: Context,
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
async renderItem(
|
|
232
|
-
_: Context,
|
|
233
|
-
item: CollectionItem<C>,
|
|
234
|
-
index: number
|
|
235
|
-
): Promise<FlatTemplatable> {
|
|
236
|
-
return `<div>${item.id}</div>`;
|
|
240
|
+
fields: { field: string; label?: string }[]
|
|
241
|
+
): FlatTemplatable {
|
|
242
|
+
return tempstream/* HTML */ `<thead>
|
|
243
|
+
<tr>
|
|
244
|
+
${fields.map(({ label, field }) =>
|
|
245
|
+
this.renderHeading(ctx, field, label)
|
|
246
|
+
)}
|
|
247
|
+
</tr>
|
|
248
|
+
</thead>`;
|
|
237
249
|
}
|
|
238
|
-
|
|
239
|
-
canAccess = peopleWhoCan("list", this.collection);
|
|
240
250
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Context } from "koa";
|
|
2
|
+
import { BaseListPageFields, ListPage } from "./list";
|
|
3
|
+
import {
|
|
4
|
+
Collection,
|
|
5
|
+
CollectionItem,
|
|
6
|
+
ItemList,
|
|
7
|
+
Context as SealiousContext,
|
|
8
|
+
CollectionInput,
|
|
9
|
+
} from "sealious";
|
|
10
|
+
import { FlatTemplatable } from "tempstream";
|
|
11
|
+
import { peopleWhoCan } from "./access-control";
|
|
12
|
+
|
|
13
|
+
export abstract class SealiousItemListPage<
|
|
14
|
+
C extends Collection,
|
|
15
|
+
F extends typeof BaseListPageFields
|
|
16
|
+
> extends ListPage<CollectionItem<C>, F> {
|
|
17
|
+
constructor(public collection: C) {
|
|
18
|
+
super();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async getContextForList(ctx: Context): Promise<SealiousContext> {
|
|
22
|
+
return ctx.$context;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async getTotalPages(ctx: Context, itemsPerPage: number): Promise<number> {
|
|
26
|
+
const query = this.collection.list(await this.getContextForList(ctx));
|
|
27
|
+
await this.addFilter(ctx, query);
|
|
28
|
+
const { items } = await query.fetch();
|
|
29
|
+
return Math.ceil(items.length / itemsPerPage);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
protected async addFilter(ctx: Context, list: ItemList<C>): Promise<void> {
|
|
33
|
+
const filters = await this.getFilterValues(ctx);
|
|
34
|
+
|
|
35
|
+
for (const key in filters) {
|
|
36
|
+
if (filters[key] === undefined || filters[key] == "") {
|
|
37
|
+
delete filters[key];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (Object.keys(filters).length) {
|
|
41
|
+
list.filter(filters as Partial<CollectionInput<C>>);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async makeQuery(ctx: Context): Promise<ItemList<C>> {
|
|
46
|
+
const query = this.collection.list(await this.getContextForList(ctx));
|
|
47
|
+
const sort = await this.getSort(ctx);
|
|
48
|
+
if (sort) {
|
|
49
|
+
query.sort({ [sort.field]: sort.order } as any);
|
|
50
|
+
}
|
|
51
|
+
return query;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async getItems(
|
|
55
|
+
ctx: Context,
|
|
56
|
+
page: number,
|
|
57
|
+
itemsPerPage: number
|
|
58
|
+
): Promise<CollectionItem<C>[]> {
|
|
59
|
+
const query = await this.makeQuery(ctx);
|
|
60
|
+
await this.addFilter(ctx, query);
|
|
61
|
+
const { items } = await query
|
|
62
|
+
.paginate({ items: itemsPerPage, page })
|
|
63
|
+
.fetch();
|
|
64
|
+
return items;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async renderItem(
|
|
68
|
+
_: Context,
|
|
69
|
+
item: CollectionItem<C>,
|
|
70
|
+
index: number
|
|
71
|
+
): Promise<FlatTemplatable> {
|
|
72
|
+
return `<div>${item.id}</div>`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
canAccess = peopleWhoCan("list", this.collection);
|
|
76
|
+
}
|
package/src/templates/list.ts
CHANGED
|
@@ -49,13 +49,14 @@ export default new (class ${action_name}Page extends SealiousItemListPage<
|
|
|
49
49
|
"${uppercase_collection}",
|
|
50
50
|
tempstream/* HTML */ \`<div>
|
|
51
51
|
<h2>${uppercase_collection} List</h2>
|
|
52
|
-
<table>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
<table class="sealious-list">
|
|
53
|
+
\${this.renderTableHead(ctx, [
|
|
54
|
+
{ field: "id" },
|
|
55
|
+
...Object.keys(Patrons.fields).map((field) => ({
|
|
56
|
+
field,
|
|
57
|
+
label: field,
|
|
58
|
+
})),
|
|
59
|
+
])}
|
|
59
60
|
<tbody>
|
|
60
61
|
\${super.render(ctx)}
|
|
61
62
|
</tbody>
|
package/src/utils/import-path.ts
CHANGED
|
@@ -8,7 +8,7 @@ export function importPath(
|
|
|
8
8
|
): string {
|
|
9
9
|
let result = relative(
|
|
10
10
|
dirname(target_locreq.resolve(project_module_path)),
|
|
11
|
-
target_locreq.resolve(project_target_path).replace(/.ts$/, "")
|
|
11
|
+
target_locreq.resolve(project_target_path).replace(/.ts$/, ".js")
|
|
12
12
|
);
|
|
13
13
|
if (result[0] != ".") {
|
|
14
14
|
result = "./" + result;
|