@mmlogic/components 0.5.13 → 0.5.15
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/dist/cjs/{cell-renderer-BBebjBVz.js → cell-renderer-CLVKTVVQ.js} +113 -1
- package/dist/cjs/{client-layout-CqVuJumR.js → client-layout-Eg2VwW-7.js} +2 -0
- package/dist/cjs/index.cjs.js +2 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/mosterdcomponents.cjs.js +1 -1
- package/dist/cjs/{mrd-boolean-field_25.cjs.entry.js → mrd-boolean-field_28.cjs.entry.js} +1163 -356
- package/dist/cjs/mrd-merge-view.cjs.entry.js +4 -4
- package/dist/collection/collection-manifest.json +3 -0
- package/dist/collection/components/fields/mrd-textarea-field/mrd-textarea-field.js +47 -2
- package/dist/collection/components/form/mrd-form/mrd-form.css +29 -0
- package/dist/collection/components/form/mrd-form/mrd-form.js +44 -8
- package/dist/collection/components/layout/mrd-layout-section/mrd-layout-section.js +126 -13
- package/dist/collection/components/memo/mrd-memo-container/mrd-memo-container.css +204 -0
- package/dist/collection/components/memo/mrd-memo-container/mrd-memo-container.js +694 -0
- package/dist/collection/components/memo/mrd-memo-list/mrd-memo-list.css +150 -0
- package/dist/collection/components/memo/mrd-memo-list/mrd-memo-list.js +511 -0
- package/dist/collection/components/memo/mrd-memo-view/mrd-memo-view.css +108 -0
- package/dist/collection/components/memo/mrd-memo-view/mrd-memo-view.js +204 -0
- package/dist/collection/components/merge/mrd-merge-view/mrd-merge-view.js +2 -2
- package/dist/collection/components/table/mrd-table/mrd-table.css +36 -0
- package/dist/collection/components/table/mrd-table/mrd-table.js +146 -31
- package/dist/collection/components/table/mrd-table/table-parts.js +6 -2
- package/dist/collection/components/table/mrd-table/table-query.js +6 -0
- package/dist/collection/dev/app.js +17 -0
- package/dist/collection/types/client-layout.js +1 -0
- package/dist/collection/utils/i18n.js +112 -0
- package/dist/collection/utils/query-params.js +9 -0
- package/dist/components/client-layout.js +1 -1
- package/dist/components/i18n.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/mrd-form.js +1 -1
- package/dist/components/mrd-layout-section.js +1 -1
- package/dist/components/mrd-memo-container.d.ts +11 -0
- package/dist/components/mrd-memo-container.js +1 -0
- package/dist/components/mrd-memo-container2.js +1 -0
- package/dist/components/mrd-memo-list.d.ts +11 -0
- package/dist/components/mrd-memo-list.js +1 -0
- package/dist/components/mrd-memo-list2.js +1 -0
- package/dist/components/mrd-memo-view.d.ts +11 -0
- package/dist/components/mrd-memo-view.js +1 -0
- package/dist/components/mrd-memo-view2.js +1 -0
- package/dist/components/mrd-merge-view.js +1 -1
- package/dist/components/mrd-table2.js +1 -1
- package/dist/components/mrd-textarea-field2.js +1 -1
- package/dist/components/query-params.js +1 -1
- package/dist/components/table-query.js +1 -0
- package/dist/esm/{cell-renderer-CC8-MtvQ.js → cell-renderer-4NKEzZWw.js} +113 -1
- package/dist/esm/{client-layout-Bc42CfJB.js → client-layout-BJkVeSq6.js} +2 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/mosterdcomponents.js +1 -1
- package/dist/esm/{mrd-boolean-field_25.entry.js → mrd-boolean-field_28.entry.js} +1161 -357
- package/dist/esm/mrd-merge-view.entry.js +4 -4
- package/dist/mosterdcomponents/index.esm.js +1 -1
- package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
- package/dist/mosterdcomponents/{p-Bc42CfJB.js → p-BJkVeSq6.js} +1 -1
- package/dist/mosterdcomponents/p-BMx6VAJ6.js +1 -0
- package/dist/mosterdcomponents/p-d64ba1f2.entry.js +3 -0
- package/dist/mosterdcomponents/{p-a7e8f6a3.entry.js → p-e68dfbb0.entry.js} +1 -1
- package/dist/types/components/fields/mrd-textarea-field/mrd-textarea-field.d.ts +10 -0
- package/dist/types/components/form/mrd-form/mrd-form.d.ts +6 -0
- package/dist/types/components/layout/mrd-layout-section/mrd-layout-section.d.ts +20 -1
- package/dist/types/components/memo/mrd-memo-container/mrd-memo-container.d.ts +152 -0
- package/dist/types/components/memo/mrd-memo-list/mrd-memo-list.d.ts +79 -0
- package/dist/types/components/memo/mrd-memo-view/mrd-memo-view.d.ts +33 -0
- package/dist/types/components/table/mrd-table/mrd-table.d.ts +48 -1
- package/dist/types/components/table/mrd-table/table-parts.d.ts +15 -0
- package/dist/types/components/table/mrd-table/table-query.d.ts +6 -0
- package/dist/types/components.d.ts +528 -1
- package/dist/types/types/client-layout.d.ts +1 -0
- package/dist/types/utils/query-params.d.ts +16 -0
- package/package.json +1 -1
- package/dist/mosterdcomponents/p-07b148b2.entry.js +0 -3
- package/dist/mosterdcomponents/p-D5ZPfX3-.js +0 -1
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
@charset "UTF-8";
|
|
2
|
+
:host {
|
|
3
|
+
display: block;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.mrd-memo-view {
|
|
7
|
+
max-width: 720px;
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-direction: column;
|
|
10
|
+
gap: var(--mrd-space-3);
|
|
11
|
+
}
|
|
12
|
+
.mrd-memo-view__header {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: baseline;
|
|
15
|
+
flex-wrap: wrap;
|
|
16
|
+
gap: var(--mrd-space-3);
|
|
17
|
+
}
|
|
18
|
+
.mrd-memo-view__title {
|
|
19
|
+
font-size: var(--mrd-font-size-2xl);
|
|
20
|
+
font-weight: var(--mrd-font-weight-bold);
|
|
21
|
+
color: var(--mrd-color-neutral-900);
|
|
22
|
+
letter-spacing: -0.02em;
|
|
23
|
+
margin: 0;
|
|
24
|
+
}
|
|
25
|
+
.mrd-memo-view__important {
|
|
26
|
+
display: inline-flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
gap: var(--mrd-space-1);
|
|
29
|
+
font-size: var(--mrd-font-size-xs);
|
|
30
|
+
font-weight: var(--mrd-font-weight-semibold);
|
|
31
|
+
color: var(--mrd-color-warning);
|
|
32
|
+
text-transform: uppercase;
|
|
33
|
+
letter-spacing: 0.04em;
|
|
34
|
+
}
|
|
35
|
+
.mrd-memo-view__important svg {
|
|
36
|
+
width: 0.875rem;
|
|
37
|
+
height: 0.875rem;
|
|
38
|
+
}
|
|
39
|
+
.mrd-memo-view__meta {
|
|
40
|
+
display: flex;
|
|
41
|
+
align-items: center;
|
|
42
|
+
gap: var(--mrd-space-2);
|
|
43
|
+
font-size: var(--mrd-font-size-sm);
|
|
44
|
+
color: var(--mrd-color-neutral-400);
|
|
45
|
+
}
|
|
46
|
+
.mrd-memo-view__meta-author {
|
|
47
|
+
background: none;
|
|
48
|
+
border: none;
|
|
49
|
+
padding: 0;
|
|
50
|
+
font-family: var(--mrd-font-family);
|
|
51
|
+
font-size: inherit;
|
|
52
|
+
font-weight: var(--mrd-font-weight-medium);
|
|
53
|
+
color: var(--mrd-color-neutral-500);
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
}
|
|
56
|
+
.mrd-memo-view__meta-author:hover {
|
|
57
|
+
color: var(--mrd-color-primary);
|
|
58
|
+
text-decoration: underline;
|
|
59
|
+
}
|
|
60
|
+
.mrd-memo-view__meta-date::before {
|
|
61
|
+
content: "·";
|
|
62
|
+
margin-right: var(--mrd-space-2);
|
|
63
|
+
}
|
|
64
|
+
.mrd-memo-view__meta-author + .mrd-memo-view__meta-date::before {
|
|
65
|
+
content: "·";
|
|
66
|
+
}
|
|
67
|
+
.mrd-memo-view__labels {
|
|
68
|
+
display: flex;
|
|
69
|
+
flex-wrap: wrap;
|
|
70
|
+
gap: var(--mrd-space-2);
|
|
71
|
+
}
|
|
72
|
+
.mrd-memo-view__badge {
|
|
73
|
+
display: inline-flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
height: 1.375rem;
|
|
76
|
+
padding: 0 var(--mrd-space-2);
|
|
77
|
+
border-radius: var(--mrd-border-radius-full, 999px);
|
|
78
|
+
font-size: var(--mrd-font-size-xs);
|
|
79
|
+
font-weight: var(--mrd-font-weight-medium);
|
|
80
|
+
}
|
|
81
|
+
.mrd-memo-view__badge--plain {
|
|
82
|
+
background: var(--mrd-color-neutral-100);
|
|
83
|
+
color: var(--mrd-color-neutral-600);
|
|
84
|
+
}
|
|
85
|
+
.mrd-memo-view__container-link {
|
|
86
|
+
align-self: flex-start;
|
|
87
|
+
background: none;
|
|
88
|
+
border: none;
|
|
89
|
+
padding: 0;
|
|
90
|
+
font-family: var(--mrd-font-family);
|
|
91
|
+
font-size: var(--mrd-font-size-sm);
|
|
92
|
+
font-weight: var(--mrd-font-weight-semibold);
|
|
93
|
+
color: var(--mrd-color-primary);
|
|
94
|
+
cursor: pointer;
|
|
95
|
+
}
|
|
96
|
+
.mrd-memo-view__container-link:hover {
|
|
97
|
+
text-decoration: underline;
|
|
98
|
+
}
|
|
99
|
+
.mrd-memo-view__divider {
|
|
100
|
+
height: var(--mrd-border-width);
|
|
101
|
+
background: var(--mrd-color-neutral-200);
|
|
102
|
+
}
|
|
103
|
+
.mrd-memo-view__body {
|
|
104
|
+
font-size: var(--mrd-font-size-base);
|
|
105
|
+
color: var(--mrd-color-neutral-800);
|
|
106
|
+
line-height: var(--mrd-line-height-relaxed);
|
|
107
|
+
word-break: break-word;
|
|
108
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { Host, h } from "@stencil/core";
|
|
2
|
+
import DOMPurify from "dompurify";
|
|
3
|
+
import { t } from "../../../utils/i18n";
|
|
4
|
+
import { formatDateTime } from "../../../utils/format";
|
|
5
|
+
/**
|
|
6
|
+
* Archetype-driven single-memo view. Given a `commons.memo` binding and a data
|
|
7
|
+
* record, renders the memo the way a note should read: the title and body are
|
|
8
|
+
* the prominent content, author and timestamp sit below as a subtle metadata
|
|
9
|
+
* line — not the other way around.
|
|
10
|
+
*/
|
|
11
|
+
export class MrdMemoView {
|
|
12
|
+
constructor() {
|
|
13
|
+
/** The data record from the /data endpoint. Fields keyed by name; relations under `_links`. */
|
|
14
|
+
this.data = {};
|
|
15
|
+
this.locale = navigator.language;
|
|
16
|
+
/** listItems of the FIELD bound to the `labels` slot, resolved by mrd-layout-section
|
|
17
|
+
* from its own items array (archetype metadata does not publish listItems), so the
|
|
18
|
+
* label badges get a real label/color instead of the raw stored key. */
|
|
19
|
+
this.labelsListItems = null;
|
|
20
|
+
}
|
|
21
|
+
/** Value of a value-slot: reads data[field] via the slot→field map. */
|
|
22
|
+
slotValue(slot) {
|
|
23
|
+
var _a, _b;
|
|
24
|
+
const field = (_b = (_a = this.archetype) === null || _a === void 0 ? void 0 : _a.slots) === null || _b === void 0 ? void 0 : _b[slot];
|
|
25
|
+
if (!field)
|
|
26
|
+
return undefined;
|
|
27
|
+
return this.data[field];
|
|
28
|
+
}
|
|
29
|
+
/** Relation link for a relation-slot: reads data._links[field]. */
|
|
30
|
+
slotLink(slot) {
|
|
31
|
+
var _a, _b, _c, _d;
|
|
32
|
+
const field = (_b = (_a = this.archetype) === null || _a === void 0 ? void 0 : _a.slots) === null || _b === void 0 ? void 0 : _b[slot];
|
|
33
|
+
if (!field)
|
|
34
|
+
return undefined;
|
|
35
|
+
const links = ((_d = (_c = this.data) === null || _c === void 0 ? void 0 : _c._links) !== null && _d !== void 0 ? _d : {});
|
|
36
|
+
return links[field];
|
|
37
|
+
}
|
|
38
|
+
renderAuthor() {
|
|
39
|
+
const link = this.slotLink('author');
|
|
40
|
+
if (!(link === null || link === void 0 ? void 0 : link.href) || !link.name)
|
|
41
|
+
return null;
|
|
42
|
+
return (h("button", { type: "button", class: "mrd-memo-view__meta-author", onClick: () => this.mrdNavigate.emit({ href: link.href, label: link.name }) }, link.name));
|
|
43
|
+
}
|
|
44
|
+
renderContainer() {
|
|
45
|
+
const link = this.slotLink('container');
|
|
46
|
+
if (!(link === null || link === void 0 ? void 0 : link.href) || !link.name)
|
|
47
|
+
return null;
|
|
48
|
+
return (h("button", { type: "button", class: "mrd-memo-view__container-link", onClick: () => this.mrdNavigate.emit({ href: link.href, label: link.name }) }, link.name));
|
|
49
|
+
}
|
|
50
|
+
renderLabels() {
|
|
51
|
+
const raw = this.slotValue('labels');
|
|
52
|
+
const keys = Array.isArray(raw) ? raw.map(String) : (raw != null && raw !== '' ? [String(raw)] : []);
|
|
53
|
+
if (!keys.length)
|
|
54
|
+
return null;
|
|
55
|
+
return (h("div", { class: "mrd-memo-view__labels" }, keys.map(key => {
|
|
56
|
+
var _a, _b;
|
|
57
|
+
const listItem = ((_a = this.labelsListItems) !== null && _a !== void 0 ? _a : []).find(li => li.key === key);
|
|
58
|
+
const label = (_b = listItem === null || listItem === void 0 ? void 0 : listItem.label) !== null && _b !== void 0 ? _b : key;
|
|
59
|
+
if ((listItem === null || listItem === void 0 ? void 0 : listItem.color) && (listItem === null || listItem === void 0 ? void 0 : listItem.backgroundColor)) {
|
|
60
|
+
return (h("span", { key: key, class: "mrd-memo-view__badge", style: { color: listItem.color, backgroundColor: listItem.backgroundColor } }, label));
|
|
61
|
+
}
|
|
62
|
+
return h("span", { key: key, class: "mrd-memo-view__badge mrd-memo-view__badge--plain" }, label);
|
|
63
|
+
})));
|
|
64
|
+
}
|
|
65
|
+
renderBody() {
|
|
66
|
+
const bodyRaw = this.slotValue('body');
|
|
67
|
+
if (bodyRaw == null || bodyRaw === '')
|
|
68
|
+
return null;
|
|
69
|
+
return h("div", { class: "mrd-memo-view__body", innerHTML: DOMPurify.sanitize(String(bodyRaw)) });
|
|
70
|
+
}
|
|
71
|
+
render() {
|
|
72
|
+
const titleRaw = this.slotValue('title');
|
|
73
|
+
const title = titleRaw != null && titleRaw !== '' ? String(titleRaw) : null;
|
|
74
|
+
const dateRaw = this.slotValue('date');
|
|
75
|
+
const important = !!this.slotValue('important');
|
|
76
|
+
return (h(Host, { key: '4d8ed14c54449fbcfddc94a34dcfb220338f8bba' }, h("div", { key: '0e0456277715607580e5373ada10706db1067c7d', class: "mrd-memo-view" }, h("div", { key: 'd5c548617eca9a99eb34409b2082be025cfce2f4', class: "mrd-memo-view__header" }, title && h("h1", { key: '2ecd2eae3f8fdba310679515aa2fe76e02f0c2b2', class: "mrd-memo-view__title" }, title), important && (h("span", { key: 'e5e8284310ab6040f1677bc1241d04d65784c2da', class: "mrd-memo-view__important", title: t('memo_important', this.locale) }, h("svg", { key: 'babe987244b384330533721276b5392c9fe72c5a', viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true" }, h("path", { key: '511956710ae8e440328f9e477551ba1c2d478f1a', d: "M12 2l2.9 6.26L22 9.27l-5 4.87L18.18 21 12 17.27 5.82 21 7 14.14l-5-4.87 7.1-1.01z" })), t('memo_important', this.locale)))), h("div", { key: '41c25e5376d94078debaf62121b8bdf400511d16', class: "mrd-memo-view__meta" }, this.renderAuthor(), dateRaw != null && dateRaw !== '' && (h("span", { key: 'caff8047249745ca98da77b374438e58d150ad7f', class: "mrd-memo-view__meta-date" }, formatDateTime(dateRaw, this.locale)))), this.renderLabels(), this.renderContainer(), h("div", { key: 'bfa4c55458ea19fb920338df9478006b1883e606', class: "mrd-memo-view__divider" }), this.renderBody())));
|
|
77
|
+
}
|
|
78
|
+
static get is() { return "mrd-memo-view"; }
|
|
79
|
+
static get encapsulation() { return "scoped"; }
|
|
80
|
+
static get originalStyleUrls() {
|
|
81
|
+
return {
|
|
82
|
+
"$": ["mrd-memo-view.scss"]
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
static get styleUrls() {
|
|
86
|
+
return {
|
|
87
|
+
"$": ["mrd-memo-view.css"]
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
static get properties() {
|
|
91
|
+
return {
|
|
92
|
+
"archetype": {
|
|
93
|
+
"type": "unknown",
|
|
94
|
+
"mutable": false,
|
|
95
|
+
"complexType": {
|
|
96
|
+
"original": "ClientArchetype",
|
|
97
|
+
"resolved": "ClientArchetype",
|
|
98
|
+
"references": {
|
|
99
|
+
"ClientArchetype": {
|
|
100
|
+
"location": "import",
|
|
101
|
+
"path": "../../../types/client-layout",
|
|
102
|
+
"id": "src/types/client-layout.ts::ClientArchetype",
|
|
103
|
+
"referenceLocation": "ClientArchetype"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"required": true,
|
|
108
|
+
"optional": false,
|
|
109
|
+
"docs": {
|
|
110
|
+
"tags": [],
|
|
111
|
+
"text": "Resolved `commons.memo` binding: slot name \u2192 concrete field/relation name."
|
|
112
|
+
},
|
|
113
|
+
"getter": false,
|
|
114
|
+
"setter": false
|
|
115
|
+
},
|
|
116
|
+
"data": {
|
|
117
|
+
"type": "unknown",
|
|
118
|
+
"mutable": false,
|
|
119
|
+
"complexType": {
|
|
120
|
+
"original": "Record<string, unknown>",
|
|
121
|
+
"resolved": "string | unknown",
|
|
122
|
+
"references": {
|
|
123
|
+
"Record": {
|
|
124
|
+
"location": "global",
|
|
125
|
+
"id": "global::Record"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"required": false,
|
|
130
|
+
"optional": false,
|
|
131
|
+
"docs": {
|
|
132
|
+
"tags": [],
|
|
133
|
+
"text": "The data record from the /data endpoint. Fields keyed by name; relations under `_links`."
|
|
134
|
+
},
|
|
135
|
+
"getter": false,
|
|
136
|
+
"setter": false,
|
|
137
|
+
"defaultValue": "{}"
|
|
138
|
+
},
|
|
139
|
+
"locale": {
|
|
140
|
+
"type": "string",
|
|
141
|
+
"mutable": false,
|
|
142
|
+
"complexType": {
|
|
143
|
+
"original": "string",
|
|
144
|
+
"resolved": "string",
|
|
145
|
+
"references": {}
|
|
146
|
+
},
|
|
147
|
+
"required": false,
|
|
148
|
+
"optional": false,
|
|
149
|
+
"docs": {
|
|
150
|
+
"tags": [],
|
|
151
|
+
"text": ""
|
|
152
|
+
},
|
|
153
|
+
"getter": false,
|
|
154
|
+
"setter": false,
|
|
155
|
+
"reflect": false,
|
|
156
|
+
"attribute": "locale",
|
|
157
|
+
"defaultValue": "navigator.language"
|
|
158
|
+
},
|
|
159
|
+
"labelsListItems": {
|
|
160
|
+
"type": "unknown",
|
|
161
|
+
"mutable": false,
|
|
162
|
+
"complexType": {
|
|
163
|
+
"original": "ClientListValue[] | null",
|
|
164
|
+
"resolved": "ClientListValue[] | null",
|
|
165
|
+
"references": {
|
|
166
|
+
"ClientListValue": {
|
|
167
|
+
"location": "import",
|
|
168
|
+
"path": "../../../types/client-layout",
|
|
169
|
+
"id": "src/types/client-layout.ts::ClientListValue",
|
|
170
|
+
"referenceLocation": "ClientListValue"
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"required": false,
|
|
175
|
+
"optional": false,
|
|
176
|
+
"docs": {
|
|
177
|
+
"tags": [],
|
|
178
|
+
"text": "listItems of the FIELD bound to the `labels` slot, resolved by mrd-layout-section\nfrom its own items array (archetype metadata does not publish listItems), so the\nlabel badges get a real label/color instead of the raw stored key."
|
|
179
|
+
},
|
|
180
|
+
"getter": false,
|
|
181
|
+
"setter": false,
|
|
182
|
+
"defaultValue": "null"
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
static get events() {
|
|
187
|
+
return [{
|
|
188
|
+
"method": "mrdNavigate",
|
|
189
|
+
"name": "mrdNavigate",
|
|
190
|
+
"bubbles": true,
|
|
191
|
+
"cancelable": true,
|
|
192
|
+
"composed": true,
|
|
193
|
+
"docs": {
|
|
194
|
+
"tags": [],
|
|
195
|
+
"text": "Navigate to the author or the container. Host resolves the href and routes."
|
|
196
|
+
},
|
|
197
|
+
"complexType": {
|
|
198
|
+
"original": "{ href?: string; label: string }",
|
|
199
|
+
"resolved": "{ href?: string | undefined; label: string; }",
|
|
200
|
+
"references": {}
|
|
201
|
+
}
|
|
202
|
+
}];
|
|
203
|
+
}
|
|
204
|
+
}
|
|
@@ -121,14 +121,14 @@ export class MrdMergeView {
|
|
|
121
121
|
var _a, _b;
|
|
122
122
|
let stepContent;
|
|
123
123
|
if (this.step === 'search') {
|
|
124
|
-
stepContent = (h(MergeSearchStep, { key: '
|
|
124
|
+
stepContent = (h(MergeSearchStep, { key: '88ddac4f8f60a736bc6bc898b553e24771023b82', locale: this.locale, searchQuery: this.searchQuery, searchResults: this.searchResults, isLoading: this.isLoading, onSearchInput: this.handleSearchInput, onSelect: this.handleSelect }));
|
|
125
125
|
}
|
|
126
126
|
else {
|
|
127
127
|
const diff = diffFields(this.fields, this.currentRecord, this.candidate);
|
|
128
128
|
const bLabel = candidateLabel(this.candidate);
|
|
129
129
|
stepContent = this.step === 'compare' ? (h(MergeCompareStep, { locale: this.locale, currentLabel: this.currentLabel, candidateLabel: bLabel, conflicts: diff.conflicts, autoFilled: diff.autoFilled, recordA: this.currentRecord, recordB: (_a = this.candidate) !== null && _a !== void 0 ? _a : {}, resolutions: this.resolutions, openHistoryKey: this.openHistoryKey, onResolve: this.handleResolve, onToggleHistory: this.handleToggleHistory, onChangeCandidate: this.handleChangeCandidate, onContinue: this.handleContinue })) : (h(MergeConfirmStep, { locale: this.locale, candidateLabel: bLabel, conflicts: diff.conflicts, autoFilled: diff.autoFilled, resolutions: this.resolutions, recordB: (_b = this.candidate) !== null && _b !== void 0 ? _b : {}, openHistoryKey: this.openHistoryKey, onToggleHistory: this.handleToggleHistory, onBack: this.handleBack, onConfirm: this.handleConfirm }));
|
|
130
130
|
}
|
|
131
|
-
return (h(Host, { key: '
|
|
131
|
+
return (h(Host, { key: '3606faba4c86ae1d981b7c40e4f1cb9cde19cf50' }, h("div", { key: '9605009fec0a7c79a5cd32141d930ea04e5efaad', class: "mrd-merge-view" }, stepContent)));
|
|
132
132
|
}
|
|
133
133
|
static get is() { return "mrd-merge-view"; }
|
|
134
134
|
static get encapsulation() { return "scoped"; }
|
|
@@ -321,6 +321,42 @@
|
|
|
321
321
|
pointer-events: none;
|
|
322
322
|
z-index: 10;
|
|
323
323
|
}
|
|
324
|
+
.mrd-table__search-box {
|
|
325
|
+
display: inline-flex;
|
|
326
|
+
align-items: center;
|
|
327
|
+
gap: var(--mrd-space-1);
|
|
328
|
+
height: 2rem;
|
|
329
|
+
padding: 0 var(--mrd-space-2);
|
|
330
|
+
border: 1px solid var(--mrd-border-color-focus, var(--mrd-color-primary));
|
|
331
|
+
border-radius: var(--mrd-border-radius);
|
|
332
|
+
background: var(--mrd-color-white, #fff);
|
|
333
|
+
box-shadow: var(--mrd-shadow-focus, none);
|
|
334
|
+
color: var(--mrd-color-neutral-400);
|
|
335
|
+
}
|
|
336
|
+
.mrd-table__search-input {
|
|
337
|
+
border: none;
|
|
338
|
+
outline: none;
|
|
339
|
+
background: transparent;
|
|
340
|
+
font-size: var(--mrd-font-size-sm);
|
|
341
|
+
font-family: var(--mrd-font-family);
|
|
342
|
+
color: var(--mrd-color-neutral-800);
|
|
343
|
+
width: 12rem;
|
|
344
|
+
}
|
|
345
|
+
.mrd-table__search-clear {
|
|
346
|
+
display: inline-flex;
|
|
347
|
+
align-items: center;
|
|
348
|
+
justify-content: center;
|
|
349
|
+
background: none;
|
|
350
|
+
border: none;
|
|
351
|
+
padding: 0;
|
|
352
|
+
cursor: pointer;
|
|
353
|
+
color: var(--mrd-color-neutral-400);
|
|
354
|
+
font-size: var(--mrd-font-size-xs);
|
|
355
|
+
line-height: 1;
|
|
356
|
+
}
|
|
357
|
+
.mrd-table__search-clear:hover {
|
|
358
|
+
color: var(--mrd-color-neutral-700);
|
|
359
|
+
}
|
|
324
360
|
.mrd-table__create-picker-wrap {
|
|
325
361
|
position: relative;
|
|
326
362
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { h, Host, writeTask } from "@stencil/core";
|
|
2
2
|
import { t } from "../../../utils/i18n";
|
|
3
|
-
import { buildListPath } from "../../../utils/query-params";
|
|
4
|
-
import { TEXT_TYPES, NON_INTERACTIVE_TYPES, parseDefaultSort, buildSortParam, buildTableQueryParams, buildAggregationQs, filterHasValue, normalizeDatetimeFilter, datetimeFilterToDisplay, } from "./table-query";
|
|
3
|
+
import { buildCreateActionDetail, buildListPath } from "../../../utils/query-params";
|
|
4
|
+
import { TEXT_TYPES, NON_INTERACTIVE_TYPES, SEARCH_DEBOUNCE_MS, parseDefaultSort, buildSortParam, buildTableQueryParams, buildAggregationQs, filterHasValue, normalizeDatetimeFilter, datetimeFilterToDisplay, } from "./table-query";
|
|
5
5
|
import { FilterIcon, TableCell, TotalsRow, TextblockModal, JsonModal, Toolbar } from "./table-parts";
|
|
6
6
|
import { FilterPopup } from "./table-filter-popup";
|
|
7
7
|
import { REQUEST_DEBOUNCE_MS, REQUEST_TIMEOUT_MS, MAX_RETRY_ATTEMPTS, visibleCount, computeWindow, pageRange, getRowFromPages, computeEffectiveTotal, isTotalKnownFromPages, getStalePages, } from "./virtual-scroll";
|
|
@@ -27,6 +27,17 @@ export class MrdTable {
|
|
|
27
27
|
this.keydownHandler = null;
|
|
28
28
|
this.createPickerClickHandler = null;
|
|
29
29
|
this.viewPopoverClickHandler = null;
|
|
30
|
+
/** Debounce timer for the free-text search box — separate from debounceTimer
|
|
31
|
+
* (pending-page requests), since typing and scrolling debounce independently. */
|
|
32
|
+
this.searchDebounceTimer = null;
|
|
33
|
+
/** The rendered search <input>, captured so it can be focused the instant it mounts. */
|
|
34
|
+
this.searchInputEl = null;
|
|
35
|
+
/** Set by toggleSearch() when the box just expanded; consumed and cleared in componentDidRender(). */
|
|
36
|
+
this.searchNeedsFocus = false;
|
|
37
|
+
/** Column filters stashed by stashFiltersForSearch() while the search box is open — the
|
|
38
|
+
* backend can't combine `q` with column filters. Restored by restoreFiltersAfterSearch()
|
|
39
|
+
* on close, unless the user applied a fresh filter of their own in the meantime. */
|
|
40
|
+
this.stashedFilters = null;
|
|
30
41
|
/** Watches the host for gaining a box (e.g. its tab pane being shown) — see componentDidLoad. */
|
|
31
42
|
this.resizeObserver = null;
|
|
32
43
|
/** Guards against scheduling more than one column-width measurement per freeze. */
|
|
@@ -81,6 +92,10 @@ export class MrdTable {
|
|
|
81
92
|
this.sortDir = 'asc';
|
|
82
93
|
/** Active filters keyed by field name. */
|
|
83
94
|
this.activeFilters = new Map();
|
|
95
|
+
/** True while the toolbar's magnifying glass is expanded into the search input. */
|
|
96
|
+
this.searchOpen = false;
|
|
97
|
+
/** Current free-text search query — sent as `q` on every mrdLoadPage/aggregations request. */
|
|
98
|
+
this.searchQuery = '';
|
|
84
99
|
/** Field name of the currently open filter popup (null = closed). */
|
|
85
100
|
this.openFilterCol = null;
|
|
86
101
|
/** Filter state being edited in the open popup. */
|
|
@@ -134,6 +149,11 @@ export class MrdTable {
|
|
|
134
149
|
this.colWidthMeasureScheduled = false;
|
|
135
150
|
this.colWidthsUserSet = false;
|
|
136
151
|
this.fixedContentMeasured = false;
|
|
152
|
+
// A new item is a different table (possibly not even a VIEW any more) — a leftover
|
|
153
|
+
// query from the old one should not silently keep filtering it.
|
|
154
|
+
this.searchOpen = false;
|
|
155
|
+
this.searchQuery = '';
|
|
156
|
+
this.stashedFilters = null;
|
|
137
157
|
}
|
|
138
158
|
// ── Lifecycle ──────────────────────────────────────────────────────────────
|
|
139
159
|
componentWillLoad() {
|
|
@@ -241,7 +261,12 @@ export class MrdTable {
|
|
|
241
261
|
if (pageNumber === 0 && this.aggregationsPending) {
|
|
242
262
|
this.aggregationsPending = false;
|
|
243
263
|
const hasAggColumns = this.columns.some(c => c.type === 'FIELD' && c.aggregate);
|
|
244
|
-
|
|
264
|
+
// The aggregations endpoint doesn't support the `q` free-text param, so a request
|
|
265
|
+
// sent while searching would silently return unfiltered totals. Leave aggregations
|
|
266
|
+
// (and aggregationsTotal) at null instead — TotalsRow already renders nothing when
|
|
267
|
+
// aggregations is null, so the totals row just disappears for the duration of the
|
|
268
|
+
// search rather than showing numbers that don't match the filtered rows.
|
|
269
|
+
if (!this.searchQuery && (!isLastPage || hasAggColumns)) {
|
|
245
270
|
this.emitLoadAggregations();
|
|
246
271
|
}
|
|
247
272
|
}
|
|
@@ -280,10 +305,18 @@ export class MrdTable {
|
|
|
280
305
|
document.removeEventListener('click', this.viewPopoverClickHandler);
|
|
281
306
|
this.viewPopoverClickHandler = null;
|
|
282
307
|
}
|
|
308
|
+
if (this.searchDebounceTimer !== null) {
|
|
309
|
+
clearTimeout(this.searchDebounceTimer);
|
|
310
|
+
this.searchDebounceTimer = null;
|
|
311
|
+
}
|
|
283
312
|
}
|
|
284
313
|
componentDidRender() {
|
|
285
314
|
this.freezeColWidths();
|
|
286
315
|
this.growToFixedContent();
|
|
316
|
+
if (this.searchNeedsFocus && this.searchInputEl) {
|
|
317
|
+
this.searchInputEl.focus();
|
|
318
|
+
this.searchNeedsFocus = false;
|
|
319
|
+
}
|
|
287
320
|
}
|
|
288
321
|
/** Freeze the column widths once the first data page has rendered.
|
|
289
322
|
*
|
|
@@ -574,16 +607,19 @@ export class MrdTable {
|
|
|
574
607
|
});
|
|
575
608
|
}
|
|
576
609
|
buildActionDetail(action, basicType) {
|
|
577
|
-
var _a
|
|
610
|
+
var _a;
|
|
578
611
|
if (action === 'export') {
|
|
579
612
|
return { action, path: this.buildExcelPath(), qs: this.buildQueryParams(0) };
|
|
580
613
|
}
|
|
581
614
|
if (action === 'create') {
|
|
582
615
|
const v = this.allViews[this.activeViewIdx];
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
: null
|
|
586
|
-
|
|
616
|
+
return buildCreateActionDetail({
|
|
617
|
+
isRelatedView: ((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'RELATED_VIEW',
|
|
618
|
+
fromClass: v === null || v === void 0 ? void 0 : v.fromClass,
|
|
619
|
+
parentId: this.parentId,
|
|
620
|
+
dataClass: v === null || v === void 0 ? void 0 : v.dataClass,
|
|
621
|
+
basicType,
|
|
622
|
+
});
|
|
587
623
|
}
|
|
588
624
|
return { action };
|
|
589
625
|
}
|
|
@@ -602,7 +638,13 @@ export class MrdTable {
|
|
|
602
638
|
dataClass: v.dataClass,
|
|
603
639
|
});
|
|
604
640
|
}
|
|
605
|
-
/** Build query params for a page request from current sort, view filters, filterClass and active column filters.
|
|
641
|
+
/** Build query params for a page request from current sort, view filters, filterClass and active column filters.
|
|
642
|
+
*
|
|
643
|
+
* `q` and column filters are mutually exclusive on the backend — combining them breaks
|
|
644
|
+
* the search. stashFiltersForSearch() already empties activeFilters for the duration of
|
|
645
|
+
* a search, but this guard is the actual guarantee: even if a filter is applied through
|
|
646
|
+
* a column header while the search box is still open (before the query is cleared),
|
|
647
|
+
* activeFilters is dropped from the request rather than sent alongside `q`. */
|
|
606
648
|
buildQueryParams(page) {
|
|
607
649
|
var _a;
|
|
608
650
|
const v = this.allViews[this.activeViewIdx];
|
|
@@ -611,7 +653,8 @@ export class MrdTable {
|
|
|
611
653
|
sort: this.sortParam(),
|
|
612
654
|
filterClass: v === null || v === void 0 ? void 0 : v.filterClass,
|
|
613
655
|
viewFilters: (_a = v === null || v === void 0 ? void 0 : v.view) === null || _a === void 0 ? void 0 : _a.filter,
|
|
614
|
-
activeFilters: this.activeFilters.values(),
|
|
656
|
+
activeFilters: this.searchQuery ? [] : this.activeFilters.values(),
|
|
657
|
+
query: this.searchQuery,
|
|
615
658
|
});
|
|
616
659
|
}
|
|
617
660
|
/** True when the table is in paginated / virtual-scroll mode rather than driven by the
|
|
@@ -917,6 +960,18 @@ export class MrdTable {
|
|
|
917
960
|
const current = (_b = (_a = this.pendingFilter) === null || _a === void 0 ? void 0 : _a.values) !== null && _b !== void 0 ? _b : [];
|
|
918
961
|
this.pendingFilter = Object.assign(Object.assign({}, this.pendingFilter), { values: checked ? [...current, key] : current.filter(k => k !== key) });
|
|
919
962
|
}
|
|
963
|
+
/** Common reload after activeFilters or searchQuery changed: drop stale aggregations
|
|
964
|
+
* (the next setPage(0) re-requests them, guarded against `q` in setPage() itself) and
|
|
965
|
+
* re-fetch page 0. Shared by the filter popup, clear-all, and free-text search. */
|
|
966
|
+
reloadAfterQueryChange() {
|
|
967
|
+
this.aggregations = null;
|
|
968
|
+
this.aggregationsTotal = null;
|
|
969
|
+
this.aggregationsPending = true;
|
|
970
|
+
if (this.isPaginated) {
|
|
971
|
+
this.resetPages();
|
|
972
|
+
this.emitPagesForWindow(this.renderStart, this.renderEnd);
|
|
973
|
+
}
|
|
974
|
+
}
|
|
920
975
|
applyFilter() {
|
|
921
976
|
const f = this.pendingFilter;
|
|
922
977
|
if (!(f === null || f === void 0 ? void 0 : f.field)) {
|
|
@@ -933,13 +988,7 @@ export class MrdTable {
|
|
|
933
988
|
}
|
|
934
989
|
this.activeFilters = next;
|
|
935
990
|
this.closeFilterPopup();
|
|
936
|
-
this.
|
|
937
|
-
this.aggregationsTotal = null;
|
|
938
|
-
this.aggregationsPending = true;
|
|
939
|
-
if (this.isPaginated) {
|
|
940
|
-
this.resetPages();
|
|
941
|
-
this.emitPagesForWindow(this.renderStart, this.renderEnd);
|
|
942
|
-
}
|
|
991
|
+
this.reloadAfterQueryChange();
|
|
943
992
|
}
|
|
944
993
|
clearFilter() {
|
|
945
994
|
const name = this.openFilterCol;
|
|
@@ -948,23 +997,80 @@ export class MrdTable {
|
|
|
948
997
|
next.delete(name);
|
|
949
998
|
this.activeFilters = next;
|
|
950
999
|
this.closeFilterPopup();
|
|
951
|
-
this.
|
|
952
|
-
this.aggregationsTotal = null;
|
|
953
|
-
this.aggregationsPending = true;
|
|
954
|
-
if (this.isPaginated) {
|
|
955
|
-
this.resetPages();
|
|
956
|
-
this.emitPagesForWindow(this.renderStart, this.renderEnd);
|
|
957
|
-
}
|
|
1000
|
+
this.reloadAfterQueryChange();
|
|
958
1001
|
}
|
|
959
1002
|
clearAllFilters() {
|
|
960
1003
|
this.activeFilters = new Map();
|
|
961
|
-
this.
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
1004
|
+
this.reloadAfterQueryChange();
|
|
1005
|
+
}
|
|
1006
|
+
// ── Free-text search ───────────────────────────────────────────────────────
|
|
1007
|
+
/** Search is a VIEW-only affordance — a RELATED_VIEW table is already scoped to
|
|
1008
|
+
* its parent record, so a free-text box there would invite confusion about what
|
|
1009
|
+
* it searches across. */
|
|
1010
|
+
get searchEnabled() {
|
|
1011
|
+
var _a;
|
|
1012
|
+
return ((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'VIEW';
|
|
1013
|
+
}
|
|
1014
|
+
toggleSearch() {
|
|
1015
|
+
if (this.searchOpen) {
|
|
1016
|
+
this.closeSearch();
|
|
1017
|
+
}
|
|
1018
|
+
else {
|
|
1019
|
+
this.searchOpen = true;
|
|
1020
|
+
this.searchNeedsFocus = true;
|
|
1021
|
+
this.stashFiltersForSearch();
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
/** Collapses the box back to the icon. Clearing a non-empty query and restoring any
|
|
1025
|
+
* stashed filters can each independently require a reload — reloadAfterQueryChange()
|
|
1026
|
+
* is called at most once here regardless of how many of the two actually changed. */
|
|
1027
|
+
closeSearch() {
|
|
1028
|
+
this.searchOpen = false;
|
|
1029
|
+
if (this.searchDebounceTimer !== null) {
|
|
1030
|
+
clearTimeout(this.searchDebounceTimer);
|
|
1031
|
+
this.searchDebounceTimer = null;
|
|
967
1032
|
}
|
|
1033
|
+
const hadQuery = this.searchQuery !== '';
|
|
1034
|
+
this.searchQuery = '';
|
|
1035
|
+
const filtersRestored = this.restoreFiltersAfterSearch();
|
|
1036
|
+
if (hadQuery || filtersRestored)
|
|
1037
|
+
this.reloadAfterQueryChange();
|
|
1038
|
+
}
|
|
1039
|
+
handleSearchInput(value) {
|
|
1040
|
+
this.searchQuery = value;
|
|
1041
|
+
if (this.searchDebounceTimer !== null)
|
|
1042
|
+
clearTimeout(this.searchDebounceTimer);
|
|
1043
|
+
this.searchDebounceTimer = setTimeout(() => this.applySearch(), SEARCH_DEBOUNCE_MS);
|
|
1044
|
+
}
|
|
1045
|
+
/** Reloads from page 0 with the current searchQuery, same reset as applyFilter(). */
|
|
1046
|
+
applySearch() {
|
|
1047
|
+
this.searchDebounceTimer = null;
|
|
1048
|
+
this.reloadAfterQueryChange();
|
|
1049
|
+
}
|
|
1050
|
+
/** Column filters and the free-text `q` param are mutually exclusive on the backend —
|
|
1051
|
+
* sending both breaks the search. Opening the search box stashes any active filters
|
|
1052
|
+
* and clears them (the header filter icons and the clear-all button disappear along
|
|
1053
|
+
* with activeFilters, so there is nothing extra to hide) and reloads unfiltered. */
|
|
1054
|
+
stashFiltersForSearch() {
|
|
1055
|
+
if (this.activeFilters.size === 0)
|
|
1056
|
+
return;
|
|
1057
|
+
this.stashedFilters = this.activeFilters;
|
|
1058
|
+
this.activeFilters = new Map();
|
|
1059
|
+
this.reloadAfterQueryChange();
|
|
1060
|
+
}
|
|
1061
|
+
/** Restores filters stashed by stashFiltersForSearch(), unless the user applied a fresh
|
|
1062
|
+
* filter of their own while the search box was open — that explicit choice wins over
|
|
1063
|
+
* reinstating the old one. Returns whether activeFilters actually changed, so the
|
|
1064
|
+
* caller can decide whether a reload is needed. */
|
|
1065
|
+
restoreFiltersAfterSearch() {
|
|
1066
|
+
if (!this.stashedFilters)
|
|
1067
|
+
return false;
|
|
1068
|
+
const stashed = this.stashedFilters;
|
|
1069
|
+
this.stashedFilters = null;
|
|
1070
|
+
if (this.activeFilters.size > 0)
|
|
1071
|
+
return false;
|
|
1072
|
+
this.activeFilters = stashed;
|
|
1073
|
+
return true;
|
|
968
1074
|
}
|
|
969
1075
|
// ── View switcher ──────────────────────────────────────────────────────────
|
|
970
1076
|
handleViewSwitch(targetIdx) {
|
|
@@ -975,6 +1081,9 @@ export class MrdTable {
|
|
|
975
1081
|
this.activeViewIdx = targetIdx;
|
|
976
1082
|
this.applyDefaultSort((_b = (_a = target.view) === null || _a === void 0 ? void 0 : _a.defaultSort) !== null && _b !== void 0 ? _b : '');
|
|
977
1083
|
this.activeFilters = new Map();
|
|
1084
|
+
this.searchOpen = false;
|
|
1085
|
+
this.searchQuery = '';
|
|
1086
|
+
this.stashedFilters = null;
|
|
978
1087
|
this.init();
|
|
979
1088
|
}
|
|
980
1089
|
toggleViewPopover(e) {
|
|
@@ -997,7 +1106,7 @@ export class MrdTable {
|
|
|
997
1106
|
// ── Render: toolbar ────────────────────────────────────────────────────────
|
|
998
1107
|
renderToolbar() {
|
|
999
1108
|
var _a;
|
|
1000
|
-
return (h(Toolbar, { locale: this.locale, filterCount: this.activeFilters.size, actions: this.tableActions, views: this.allViews, activeViewIdx: this.activeViewIdx, viewPopoverOpen: this.viewPopoverOpen, createPickerOpen: this.createPickerOpen, createTypes: (_a = this.item) === null || _a === void 0 ? void 0 : _a.createTypes, readOnly: this.readOnly, cb: {
|
|
1109
|
+
return (h(Toolbar, { locale: this.locale, filterCount: this.activeFilters.size, actions: this.tableActions, views: this.allViews, activeViewIdx: this.activeViewIdx, viewPopoverOpen: this.viewPopoverOpen, createPickerOpen: this.createPickerOpen, createTypes: (_a = this.item) === null || _a === void 0 ? void 0 : _a.createTypes, readOnly: this.readOnly, searchEnabled: this.searchEnabled, searchOpen: this.searchOpen, searchQuery: this.searchQuery, cb: {
|
|
1001
1110
|
onClearAllFilters: () => this.clearAllFilters(),
|
|
1002
1111
|
onViewSwitch: idx => this.handleViewSwitch(idx),
|
|
1003
1112
|
onToggleViewPopover: e => this.toggleViewPopover(e),
|
|
@@ -1008,6 +1117,10 @@ export class MrdTable {
|
|
|
1008
1117
|
this.closeCreatePicker();
|
|
1009
1118
|
},
|
|
1010
1119
|
onAction: action => this.mrdAction.emit(this.buildActionDetail(action)),
|
|
1120
|
+
onToggleSearch: () => this.toggleSearch(),
|
|
1121
|
+
onSearchInput: value => this.handleSearchInput(value),
|
|
1122
|
+
onCloseSearch: () => this.closeSearch(),
|
|
1123
|
+
onSearchInputRef: el => (this.searchInputEl = el !== null && el !== void 0 ? el : null),
|
|
1011
1124
|
} }));
|
|
1012
1125
|
}
|
|
1013
1126
|
// ── Render: filter popup ───────────────────────────────────────────────────
|
|
@@ -1378,6 +1491,8 @@ export class MrdTable {
|
|
|
1378
1491
|
"sortField": {},
|
|
1379
1492
|
"sortDir": {},
|
|
1380
1493
|
"activeFilters": {},
|
|
1494
|
+
"searchOpen": {},
|
|
1495
|
+
"searchQuery": {},
|
|
1381
1496
|
"openFilterCol": {},
|
|
1382
1497
|
"pendingFilter": {},
|
|
1383
1498
|
"popupPos": {},
|