@itrocks/list 0.2.2 → 0.3.1
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/build.js +0 -1
- package/cjs/filter.d.ts +12 -2
- package/cjs/filter.js +28 -2
- package/cjs/list.d.ts +1 -1
- package/cjs/list.html +9 -3
- package/cjs/list.js +4 -3
- package/cjs/sort.js +6 -6
- package/filter-reset.svg +1 -0
- package/list.css +29 -7
- package/package.json +1 -1
package/build.js
CHANGED
|
@@ -9,7 +9,6 @@ import { xTargetCall } from '../xtarget/xtarget.js';
|
|
|
9
9
|
build('article[data-action="list"] > form > table.objects', table => {
|
|
10
10
|
const tableLink = new TableLink({
|
|
11
11
|
call: url => xTargetCall(url, 'main'),
|
|
12
|
-
href: 'action',
|
|
13
12
|
id: (element) => {
|
|
14
13
|
const input = element.closest('tr')?.querySelector(':scope > th.select > input[name=id]');
|
|
15
14
|
if (input)
|
package/cjs/filter.d.ts
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { Type } from '@itrocks/class-type';
|
|
2
2
|
import { Request } from '@itrocks/request-response';
|
|
3
3
|
import { Option } from '@itrocks/storage';
|
|
4
|
+
import { Columns } from './columns';
|
|
4
5
|
import { Parameter } from './parameter';
|
|
5
|
-
|
|
6
|
-
|
|
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;
|
|
7
14
|
readOptions(options?: Option[]): Option[];
|
|
8
15
|
searchObject(type: Type): any;
|
|
16
|
+
serialize(): Search;
|
|
17
|
+
unserialize(data: Search): void;
|
|
9
18
|
}
|
|
19
|
+
export {};
|
package/cjs/filter.js
CHANGED
|
@@ -3,13 +3,39 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Filter = void 0;
|
|
4
4
|
const parameter_1 = require("./parameter");
|
|
5
5
|
class Filter extends parameter_1.Parameter {
|
|
6
|
-
|
|
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
|
+
}
|
|
7
21
|
}
|
|
8
22
|
readOptions(options = new Array) {
|
|
9
23
|
return options;
|
|
10
24
|
}
|
|
11
25
|
searchObject(type) {
|
|
12
|
-
|
|
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;
|
|
13
39
|
}
|
|
14
40
|
}
|
|
15
41
|
exports.Filter = Filter;
|
package/cjs/list.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { Sort } from './sort';
|
|
|
7
7
|
export declare class List<T extends object = object> extends Action<T> {
|
|
8
8
|
columns: Columns<object>;
|
|
9
9
|
feed: Feed;
|
|
10
|
-
filter: Filter
|
|
10
|
+
filter: Filter<object>;
|
|
11
11
|
sort: Sort<object>;
|
|
12
12
|
html(request: Request<T>): Promise<import("@itrocks/core-responses").HtmlResponse>;
|
|
13
13
|
json(request: Request<T>): Promise<import("@itrocks/core-responses").JsonResponse>;
|
package/cjs/list.html
CHANGED
|
@@ -24,15 +24,21 @@
|
|
|
24
24
|
<!--end-->
|
|
25
25
|
</ul>
|
|
26
26
|
</header>
|
|
27
|
-
<form action="app://(type.@route)" autocomplete="off" method="post" target="main">
|
|
28
|
-
<table class="objects">
|
|
29
|
-
|
|
27
|
+
<form action="app://(type.@route)/list" autocomplete="off" method="post" target="main">
|
|
28
|
+
<table class="objects" data-link="{type.@route}">
|
|
29
|
+
<thead>
|
|
30
30
|
<tr class="properties">
|
|
31
31
|
<th class="select"><input name="select" type="checkbox" value="all"></th>
|
|
32
32
|
<!--columns-->
|
|
33
33
|
<th data-property="{name}" data-reverse="{?reverse}" data-sort="{?sort}">{@display}</th>
|
|
34
34
|
<!--end-->
|
|
35
35
|
</tr>
|
|
36
|
+
<tr class="search">
|
|
37
|
+
<th><input name="reset" title="reset search filters" type="submit" value="reset"></th>
|
|
38
|
+
<!--columns-->
|
|
39
|
+
<th><input name="search.{name.toField}" value="{?.search.{name.toField}}"></th>
|
|
40
|
+
<!--end-->
|
|
41
|
+
</tr>
|
|
36
42
|
</thead>
|
|
37
43
|
<tbody>
|
|
38
44
|
{./feed.html}
|
package/cjs/list.js
CHANGED
|
@@ -64,7 +64,7 @@ let List = (() => {
|
|
|
64
64
|
}
|
|
65
65
|
columns = new columns_1.Columns;
|
|
66
66
|
feed = new feed_1.Feed;
|
|
67
|
-
filter = new filter_1.Filter;
|
|
67
|
+
filter = new filter_1.Filter(this.columns);
|
|
68
68
|
sort = new sort_1.Sort(this.columns);
|
|
69
69
|
async html(request) {
|
|
70
70
|
const columns = this.columns;
|
|
@@ -78,7 +78,8 @@ let List = (() => {
|
|
|
78
78
|
filter.getParams(request.request);
|
|
79
79
|
sort.getParams(request.request, type);
|
|
80
80
|
(0, persist_2.save)(this, request.request, type);
|
|
81
|
-
const
|
|
81
|
+
const options = feed.readOptions(filter.readOptions(sort.readOptions()));
|
|
82
|
+
const objects = await (0, storage_1.dataSource)().search(type, filter.searchObject(type), options);
|
|
82
83
|
if (feed.offset) {
|
|
83
84
|
return this.htmlTemplateResponse({ objects, type }, request, feed.template);
|
|
84
85
|
}
|
|
@@ -90,7 +91,7 @@ let List = (() => {
|
|
|
90
91
|
const actions = (action.need === 'object') ? selectionActions : generalActions;
|
|
91
92
|
actions.push(action);
|
|
92
93
|
}
|
|
93
|
-
return this.htmlTemplateResponse({ columns, count, generalActions, objects, selectionActions, type }, request, __dirname + '/list.html');
|
|
94
|
+
return this.htmlTemplateResponse({ columns, count, generalActions, objects, search: filter.search, selectionActions, type }, request, __dirname + '/list.html');
|
|
94
95
|
}
|
|
95
96
|
async json(request) {
|
|
96
97
|
const objects = await (0, storage_1.dataSource)().search(request.type);
|
package/cjs/sort.js
CHANGED
|
@@ -35,11 +35,11 @@ class Sort extends parameter_1.Parameter {
|
|
|
35
35
|
const reverse = 'reverse' in request.data;
|
|
36
36
|
const sort = request.data.sort;
|
|
37
37
|
const index = sortProperties.indexOf(sort);
|
|
38
|
-
if (index
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
if (index >= 0) {
|
|
39
|
+
sortProperties.splice(index, 1);
|
|
40
|
+
sortReverse.splice(index, 1);
|
|
41
|
+
}
|
|
41
42
|
sortProperties.unshift(sort);
|
|
42
|
-
sortReverse.splice(index, 1);
|
|
43
43
|
sortReverse.unshift(reverse);
|
|
44
44
|
this.sorted = undefined;
|
|
45
45
|
}
|
|
@@ -51,8 +51,8 @@ class Sort extends parameter_1.Parameter {
|
|
|
51
51
|
}
|
|
52
52
|
for (const column of this.columns) {
|
|
53
53
|
const sortIndex = sortProperties.indexOf(column.name);
|
|
54
|
-
column.reverse = sortReverse[sortIndex];
|
|
55
|
-
column.sort = (sortIndex
|
|
54
|
+
column.reverse = !!sortReverse[sortIndex];
|
|
55
|
+
column.sort = (sortIndex + 1) || undefined;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
readOptions(options = new Array) {
|
package/filter-reset.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg stroke="#666" stroke-linecap="round" stroke-width="2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle cx="11" cy="11" fill="none" r="7"/><path d="M20 20l-3.5-3.5" /><path d="M8.5 8.5l5 5M13.5 8.5l-5 5"/></svg>
|
package/list.css
CHANGED
|
@@ -56,13 +56,13 @@ table.objects > tbody:first-child > tr:nth-child(even) > td {
|
|
|
56
56
|
table.objects > tbody:first-child > tr:nth-child(odd) > td {
|
|
57
57
|
background: #f8f8f8;
|
|
58
58
|
}
|
|
59
|
-
table.objects > thead > tr > th[data-property] {
|
|
59
|
+
table.objects > thead > tr.properties > th[data-property] {
|
|
60
60
|
cursor: pointer;
|
|
61
61
|
}
|
|
62
|
-
table.objects > thead > tr > th[data-sort] {
|
|
62
|
+
table.objects > thead > tr.properties > th[data-sort] {
|
|
63
63
|
padding-right: calc(0.6em + 16px);
|
|
64
64
|
}
|
|
65
|
-
table.objects > thead > tr > th[data-sort]::after {
|
|
65
|
+
table.objects > thead > tr.properties > th[data-sort]::after {
|
|
66
66
|
content: "";
|
|
67
67
|
height: 24px;
|
|
68
68
|
mask: url("sort.svg") right center/24px 24px no-repeat;
|
|
@@ -71,18 +71,40 @@ table.objects > thead > tr > th[data-sort]::after {
|
|
|
71
71
|
top: calc(50% - 12px);
|
|
72
72
|
width: 24px;
|
|
73
73
|
}
|
|
74
|
-
table.objects > thead > tr > th[data-sort][data-reverse]::after {
|
|
74
|
+
table.objects > thead > tr.properties > th[data-sort][data-reverse]::after {
|
|
75
75
|
transform: scaleY(-1);
|
|
76
76
|
}
|
|
77
|
-
table.objects > thead > tr > th[data-sort][data-sort="1"]::after {
|
|
77
|
+
table.objects > thead > tr.properties > th[data-sort][data-sort="1"]::after {
|
|
78
78
|
background-color: #444;
|
|
79
79
|
}
|
|
80
|
-
table.objects > thead > tr > th[data-sort][data-sort="2"]::after {
|
|
80
|
+
table.objects > thead > tr.properties > th[data-sort][data-sort="2"]::after {
|
|
81
81
|
background-color: #888;
|
|
82
82
|
}
|
|
83
|
-
table.objects > thead > tr > th[data-sort][data-sort="3"]::after {
|
|
83
|
+
table.objects > thead > tr.properties > th[data-sort][data-sort="3"]::after {
|
|
84
84
|
background-color: #ccc;
|
|
85
85
|
}
|
|
86
|
+
table.objects > thead > tr.search > th {
|
|
87
|
+
padding: 0;
|
|
88
|
+
}
|
|
89
|
+
table.objects > thead > tr.search > th > input {
|
|
90
|
+
border: none;
|
|
91
|
+
border-radius: 0;
|
|
92
|
+
width: 100%;
|
|
93
|
+
}
|
|
94
|
+
table.objects > thead > tr.search > th > input[type=submit] {
|
|
95
|
+
background: url("filter-reset.svg") center no-repeat;
|
|
96
|
+
color: transparent;
|
|
97
|
+
font-size: 0;
|
|
98
|
+
height: 26px;
|
|
99
|
+
min-width: 28px;
|
|
100
|
+
}
|
|
101
|
+
table.objects > thead > tr.search > th > input:not([type=submit]) {
|
|
102
|
+
border-left: 1px solid #d8d8d8;
|
|
103
|
+
}
|
|
104
|
+
table.objects > thead > tr.search > th > input:focus {
|
|
105
|
+
outline: none;
|
|
106
|
+
box-shadow: inset 0 0 0 2px Highlight;
|
|
107
|
+
}
|
|
86
108
|
table.objects > thead + tbody > tr:nth-child(even) > td {
|
|
87
109
|
background: #f8f8f8;
|
|
88
110
|
}
|
package/package.json
CHANGED