@operato/dataset 1.0.0-alpha.2 → 1.0.0-alpha.22

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +179 -0
  2. package/demo/data-item-grist.html +343 -0
  3. package/demo/index.html +9 -87
  4. package/demo/ox-data-entry-form.html +110 -0
  5. package/demo/ox-data-item-spec.html +148 -0
  6. package/dist/src/grist-editor/index.d.ts +1 -0
  7. package/dist/src/grist-editor/index.js +7 -0
  8. package/dist/src/grist-editor/index.js.map +1 -0
  9. package/dist/src/grist-editor/ox-data-item-spec-editor-popup.d.ts +12 -0
  10. package/dist/src/grist-editor/ox-data-item-spec-editor-popup.js +94 -0
  11. package/dist/src/grist-editor/ox-data-item-spec-editor-popup.js.map +1 -0
  12. package/dist/src/grist-editor/ox-data-item-spec-editor.d.ts +18 -0
  13. package/dist/src/grist-editor/ox-data-item-spec-editor.js +98 -0
  14. package/dist/src/grist-editor/ox-data-item-spec-editor.js.map +1 -0
  15. package/dist/src/index.d.ts +3 -1
  16. package/dist/src/index.js +3 -1
  17. package/dist/src/index.js.map +1 -1
  18. package/dist/src/ox-data-entry-form.d.ts +2 -24
  19. package/dist/src/ox-data-entry-form.js +67 -8
  20. package/dist/src/ox-data-entry-form.js.map +1 -1
  21. package/dist/src/ox-data-item-spec.d.ts +22 -0
  22. package/dist/src/ox-data-item-spec.js +67 -0
  23. package/dist/src/ox-data-item-spec.js.map +1 -0
  24. package/dist/src/types.d.ts +38 -0
  25. package/dist/src/types.js +2 -0
  26. package/dist/src/types.js.map +1 -0
  27. package/dist/tsconfig.tsbuildinfo +1 -1
  28. package/package.json +16 -10
  29. package/src/grist-editor/index.ts +10 -0
  30. package/src/grist-editor/ox-data-item-spec-editor-popup.ts +93 -0
  31. package/src/grist-editor/ox-data-item-spec-editor.ts +105 -0
  32. package/src/index.ts +3 -1
  33. package/src/ox-data-entry-form.ts +70 -29
  34. package/src/ox-data-item-spec.ts +64 -0
  35. package/src/types.ts +38 -0
  36. package/themes/app-theme.css +142 -0
  37. package/themes/form-theme.css +75 -0
  38. package/themes/grist-theme.css +194 -0
  39. package/themes/oops-theme.css +26 -0
  40. package/themes/report-theme.css +47 -0
  41. package/translations/en.json +1 -0
  42. package/translations/ko.json +1 -0
  43. package/translations/ms.json +1 -0
  44. package/translations/zh.json +1 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,185 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.0.0-alpha.22](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.21...v1.0.0-alpha.22) (2022-03-17)
7
+
8
+
9
+ ### :bug: Bug Fix
10
+
11
+ * ccp demo ([67b7d65](https://github.com/hatiolab/operato/commit/67b7d65b48d0ca7b3350684a45a396c0538c4902))
12
+
13
+
14
+ ### :rocket: New Features
15
+
16
+ * added data-item-spec-editor for grist ([8376e14](https://github.com/hatiolab/operato/commit/8376e142d894a709e60ed676e917d5a26e01e374))
17
+
18
+
19
+
20
+ ## [1.0.0-alpha.21](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.20...v1.0.0-alpha.21) (2022-03-16)
21
+
22
+
23
+ ### :rocket: New Features
24
+
25
+ * @operato/ccp module added ([f08ba5a](https://github.com/hatiolab/operato/commit/f08ba5a464c04b7fb132c6f18de975997087846a))
26
+ * ccp spec provider ([d72fe7c](https://github.com/hatiolab/operato/commit/d72fe7c497685e7f033ef04e6a866bd86613f397))
27
+
28
+
29
+ ### :bug: Bug Fix
30
+
31
+ * demo ([6fa3eac](https://github.com/hatiolab/operato/commit/6fa3eac612bd98ce25e3ef6d8ce89527d7152fb4))
32
+ * description on ox-data-item-spec view ([47da306](https://github.com/hatiolab/operato/commit/47da306a253a96e0c24c986e4608bfe0713a111a))
33
+
34
+
35
+
36
+ ## [1.0.0-alpha.20](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.19...v1.0.0-alpha.20) (2022-03-15)
37
+
38
+
39
+ ### :bug: Bug Fix
40
+
41
+ * ox-data-entry-form in dataset module ([736fe96](https://github.com/hatiolab/operato/commit/736fe968e292059055d18a4c18a5da979bbb4722))
42
+
43
+
44
+
45
+ ## [1.0.0-alpha.19](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.18...v1.0.0-alpha.19) (2022-03-14)
46
+
47
+ **Note:** Version bump only for package @operato/dataset
48
+
49
+
50
+
51
+
52
+
53
+ ## [1.0.0-alpha.18](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.17...v1.0.0-alpha.18) (2022-03-14)
54
+
55
+ **Note:** Version bump only for package @operato/dataset
56
+
57
+
58
+
59
+
60
+
61
+ ## [1.0.0-alpha.17](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.16...v1.0.0-alpha.17) (2022-03-13)
62
+
63
+ **Note:** Version bump only for package @operato/dataset
64
+
65
+
66
+
67
+
68
+
69
+ ## [1.0.0-alpha.16](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.15...v1.0.0-alpha.16) (2022-03-13)
70
+
71
+ **Note:** Version bump only for package @operato/dataset
72
+
73
+
74
+
75
+
76
+
77
+ ## [1.0.0-alpha.15](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.14...v1.0.0-alpha.15) (2022-03-13)
78
+
79
+ **Note:** Version bump only for package @operato/dataset
80
+
81
+
82
+
83
+
84
+
85
+ ## [1.0.0-alpha.14](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.13...v1.0.0-alpha.14) (2022-03-13)
86
+
87
+ **Note:** Version bump only for package @operato/dataset
88
+
89
+
90
+
91
+
92
+
93
+ ## [1.0.0-alpha.13](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.12...v1.0.0-alpha.13) (2022-03-13)
94
+
95
+ **Note:** Version bump only for package @operato/dataset
96
+
97
+
98
+
99
+
100
+
101
+ ## [1.0.0-alpha.12](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.11...v1.0.0-alpha.12) (2022-03-13)
102
+
103
+ **Note:** Version bump only for package @operato/dataset
104
+
105
+
106
+
107
+
108
+
109
+ ## [1.0.0-alpha.11](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.10...v1.0.0-alpha.11) (2022-03-12)
110
+
111
+ **Note:** Version bump only for package @operato/dataset
112
+
113
+
114
+
115
+
116
+
117
+ ## [1.0.0-alpha.10](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.9...v1.0.0-alpha.10) (2022-03-12)
118
+
119
+ **Note:** Version bump only for package @operato/dataset
120
+
121
+
122
+
123
+
124
+
125
+ ## [1.0.0-alpha.9](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.8...v1.0.0-alpha.9) (2022-03-12)
126
+
127
+ **Note:** Version bump only for package @operato/dataset
128
+
129
+
130
+
131
+
132
+
133
+ ## [1.0.0-alpha.8](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.7...v1.0.0-alpha.8) (2022-03-11)
134
+
135
+ **Note:** Version bump only for package @operato/dataset
136
+
137
+
138
+
139
+
140
+
141
+ ## [1.0.0-alpha.7](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.6...v1.0.0-alpha.7) (2022-03-11)
142
+
143
+ **Note:** Version bump only for package @operato/dataset
144
+
145
+
146
+
147
+
148
+
149
+ ## [1.0.0-alpha.6](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.5...v1.0.0-alpha.6) (2022-03-11)
150
+
151
+
152
+ ### :bug: Bug Fix
153
+
154
+ * ox-data-entry-form style ([c94c833](https://github.com/hatiolab/operato/commit/c94c8338aee8cf3e69c286e6af7cb2b5f081bbc7))
155
+
156
+
157
+
158
+ ## [1.0.0-alpha.5](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.4...v1.0.0-alpha.5) (2022-03-11)
159
+
160
+
161
+ ### :bug: Bug Fix
162
+
163
+ * data entry style ([d3dc3a6](https://github.com/hatiolab/operato/commit/d3dc3a6612c75597162621bd22421fa8d808cb13))
164
+
165
+
166
+
167
+ ## [1.0.0-alpha.4](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.3...v1.0.0-alpha.4) (2022-03-11)
168
+
169
+
170
+ ### :bug: Bug Fix
171
+
172
+ * ox-data-entry-form options and inputs layout ([56987c6](https://github.com/hatiolab/operato/commit/56987c664000d558427ba8dbf77730130061cb1a))
173
+
174
+
175
+
176
+ ## [1.0.0-alpha.3](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.2...v1.0.0-alpha.3) (2022-03-10)
177
+
178
+
179
+ ### :bug: Bug Fix
180
+
181
+ * add file type for data-item ([0177c84](https://github.com/hatiolab/operato/commit/0177c84ef3a91bfe85e6aec796b33b29a0e0f45e))
182
+
183
+
184
+
6
185
  ## [1.0.0-alpha.2](https://github.com/hatiolab/operato/compare/v1.0.0-alpha.1...v1.0.0-alpha.2) (2022-03-10)
7
186
 
8
187
 
@@ -0,0 +1,343 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en-GB">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" />
6
+ <style>
7
+ body {
8
+ /* box-sizing: border-box; */
9
+ margin: 0;
10
+ padding: 0;
11
+ overflow: hidden;
12
+
13
+ /* This is a font-stack that tries to use the system-default sans-serifs first */
14
+ font-family: Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
15
+ line-height: 1.5;
16
+ -webkit-font-smoothing: antialiased;
17
+ }
18
+
19
+ #app {
20
+ width: 100vw;
21
+ height: 100vh;
22
+
23
+ display: flex;
24
+ flex-direction: column;
25
+ }
26
+
27
+ #demo {
28
+ flex: 1;
29
+
30
+ display: flex;
31
+ flex-direction: column;
32
+ overflow: hidden;
33
+ }
34
+
35
+ grist-demo {
36
+ flex: 1;
37
+ overflow: auto;
38
+ }
39
+ </style>
40
+ <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet" />
41
+ <link href="https://fonts.googleapis.com/css?family=Material+Icons&display=block" rel="stylesheet" />
42
+
43
+ <link href="/themes/app-theme.css" rel="stylesheet" />
44
+ <link href="/themes/oops-theme.css" rel="stylesheet" />
45
+ <link href="/themes/grist-theme.css" rel="stylesheet" />
46
+
47
+ <script>
48
+ // HACK(keanulee): The Redux package assumes `process` exists - mock it here before
49
+ // the module is loaded.
50
+ window.process = {
51
+ env: {
52
+ NODE_ENV: 'production'
53
+ }
54
+ }
55
+ </script>
56
+ </head>
57
+
58
+ <body>
59
+ <script type="module">
60
+ import { LitElement, html, css, render } from 'lit'
61
+ import '@operato/data-grist'
62
+ import '@operato/data-grist/ox-filters-form.js'
63
+ import '@operato/data-grist/ox-sorters-control.js'
64
+ import '@material/mwc-icon'
65
+ import { CommonGristStyles } from '@operato/styles'
66
+ import { i18next } from '@operato/i18n'
67
+
68
+ /* set grist-editors */
69
+ import '../dist/src/grist-editor/index.js'
70
+
71
+ const fetchHandler = async ({ page, limit, sorters = [] }) => {
72
+ var total = 10
73
+ var start = (page - 1) * limit
74
+
75
+ return {
76
+ total,
77
+ records: Array(limit * page > total ? total % limit : limit)
78
+ .fill()
79
+ .map((item, idx) => {
80
+ return {
81
+ id: idx,
82
+ name: `name-${start + idx + 1}`,
83
+ description: `description-${start + idx + 1}`,
84
+ sequence: idx + 1,
85
+ active: true,
86
+ tag: `tag-${idx + 1}`,
87
+ type: idx % 3 === 0 ? 'select' : idx % 3 === 1 ? 'number' : 'string',
88
+ createdAt: Date.now(),
89
+ updatedAt: Date.now()
90
+ }
91
+ })
92
+ }
93
+ }
94
+
95
+ var config = {
96
+ list: { fields: ['name', 'description', 'active'] },
97
+ columns: [
98
+ { type: 'gutter', gutterName: 'row-selector', multiple: true },
99
+ {
100
+ type: 'gutter',
101
+ gutterName: 'button',
102
+ icon: 'add',
103
+ handlers: {
104
+ click: 'record-copy'
105
+ }
106
+ },
107
+ { type: 'gutter', gutterName: 'sequence' },
108
+ {
109
+ type: 'gutter',
110
+ gutterName: 'button',
111
+ icon: 'arrow_upward',
112
+ handlers: {
113
+ click: 'move-up'
114
+ }
115
+ },
116
+ {
117
+ type: 'gutter',
118
+ gutterName: 'button',
119
+ icon: 'arrow_downward',
120
+ handlers: {
121
+ click: 'move-down'
122
+ }
123
+ },
124
+ {
125
+ type: 'number',
126
+ name: 'sequence',
127
+ hidden: true
128
+ },
129
+ {
130
+ type: 'string',
131
+ name: 'id',
132
+ hidden: true
133
+ },
134
+ {
135
+ type: 'string',
136
+ name: 'name',
137
+ header: i18next.t('field.name'),
138
+ record: {
139
+ editable: true
140
+ },
141
+ width: 140
142
+ },
143
+ {
144
+ type: 'string',
145
+ name: 'description',
146
+ header: i18next.t('field.description'),
147
+ record: {
148
+ editable: true
149
+ },
150
+ width: 180
151
+ },
152
+ {
153
+ type: 'checkbox',
154
+ name: 'active',
155
+ label: true,
156
+ header: i18next.t('field.active'),
157
+ record: {
158
+ editable: true
159
+ },
160
+ sortable: true,
161
+ width: 60
162
+ },
163
+ {
164
+ type: 'string',
165
+ name: 'tag',
166
+ header: i18next.t('field.tag'),
167
+ record: {
168
+ editable: true
169
+ },
170
+ width: 180
171
+ },
172
+ {
173
+ type: 'select',
174
+ name: 'type',
175
+ header: i18next.t('field.type'),
176
+ record: {
177
+ options: ['', 'number', 'text', 'select', 'boolean', 'file'],
178
+ editable: true
179
+ },
180
+ width: 120
181
+ },
182
+ {
183
+ type: 'parameters',
184
+ name: 'options',
185
+ header: i18next.t('field.options'),
186
+ record: {
187
+ editable: true,
188
+ renderer: (value, column, record, rowIndex, field) => {
189
+ return typeof value === 'string' ? value : typeof value === 'object' ? JSON.stringify(value) : ''
190
+ },
191
+ options: async (value, column, record, row, field) => {
192
+ return {
193
+ name: record.type,
194
+ help: '',
195
+ spec:
196
+ record.type === 'select'
197
+ ? [
198
+ {
199
+ type: 'options',
200
+ name: 'options',
201
+ label: 'options'
202
+ }
203
+ ]
204
+ : [],
205
+ context: this.grist,
206
+ objectified: true
207
+ }
208
+ }
209
+ },
210
+ width: 120
211
+ },
212
+ {
213
+ type: 'string',
214
+ name: 'unit',
215
+ header: i18next.t('field.unit'),
216
+ record: {
217
+ editable: true
218
+ },
219
+ width: 120
220
+ },
221
+ {
222
+ type: 'number',
223
+ name: 'quota',
224
+ header: i18next.t('field.quota'),
225
+ record: {
226
+ editable: true
227
+ },
228
+ width: 60
229
+ },
230
+ {
231
+ type: 'data-item-spec',
232
+ name: 'spec',
233
+ header: i18next.t('field.spec'),
234
+ record: {
235
+ editable: true,
236
+ options: {
237
+ name,
238
+ objectified: true
239
+ }
240
+ },
241
+ width: 200
242
+ }
243
+ ],
244
+ rows: {
245
+ selectable: {
246
+ multiple: true
247
+ }
248
+ },
249
+ pagination: {
250
+ infinite: true
251
+ },
252
+ sorters: [
253
+ {
254
+ name: 'sequence'
255
+ }
256
+ ]
257
+ }
258
+
259
+ class GristDemo extends LitElement {
260
+ static styles = [
261
+ CommonGristStyles,
262
+ css`
263
+ :host {
264
+ display: flex;
265
+ flex-direction: column;
266
+ }
267
+
268
+ #tailer {
269
+ display: flex;
270
+ flex-direction: row;
271
+ margin: 0 var(--margin-default);
272
+ }
273
+
274
+ #tailer a {
275
+ padding: 0 var(--padding-default) 0 var(--padding-default);
276
+ margin: 0 var(--margin-narrow);
277
+ border-right: 1px solid rgba(0, 0, 0, 0.1);
278
+ font-size: var(--fontsize-default);
279
+ color: var(--primary-color);
280
+ }
281
+ `
282
+ ]
283
+
284
+ static get properties() {
285
+ return {
286
+ mode: String
287
+ }
288
+ }
289
+
290
+ get grist() {
291
+ return this.renderRoot.querySelector('ox-grist')
292
+ }
293
+
294
+ render() {
295
+ const mode = this.mode || 'CARD'
296
+
297
+ return html`
298
+ <ox-grist .config=${config} .mode=${mode} auto-fetch .fetchHandler=${fetchHandler}>
299
+ <div id="filters" slot="headroom">
300
+ <ox-filters-form @filters-change=${e => console.log('changed', e.detail)}></ox-filters-form>
301
+ </div>
302
+
303
+ <div slot="headroom" id="headroom">
304
+ <div id="sorters">
305
+ Sort
306
+ <mwc-icon
307
+ @click=${e => {
308
+ const target = e.currentTarget
309
+ this.renderRoot.querySelector('#sorter-control').open({
310
+ right: 0,
311
+ top: target.offsetTop + target.offsetHeight
312
+ })
313
+ }}
314
+ >expand_more</mwc-icon
315
+ >
316
+ <ox-popup id="sorter-control">
317
+ <ox-sorters-control> </ox-sorters-control>
318
+ </ox-popup>
319
+ </div>
320
+
321
+ <div id="modes">
322
+ <mwc-icon @click=${() => (this.mode = 'GRID')} ?active=${mode == 'GRID'}>view_list</mwc-icon>
323
+ <mwc-icon @click=${() => (this.mode = 'LIST')} ?active=${mode == 'LIST'}>menu</mwc-icon>
324
+ <mwc-icon @click=${() => (this.mode = 'CARD')} ?active=${mode == 'CARD'}>apps</mwc-icon>
325
+ </div>
326
+ </div>
327
+ </ox-grist>
328
+ `
329
+ }
330
+ }
331
+
332
+ customElements.define('ox-data-items', GristDemo)
333
+
334
+ setTimeout(() => {
335
+ render(html` <ox-data-items mode="LIST"></ox-data-items> `, document.querySelector('#demo'))
336
+ })
337
+ </script>
338
+
339
+ <div id="app">
340
+ <div id="demo"></div>
341
+ </div>
342
+ </body>
343
+ </html>
package/demo/index.html CHANGED
@@ -2,103 +2,25 @@
2
2
  <html lang="en-GB">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1" />
5
6
  <style>
6
7
  body {
7
- background: #fafafa;
8
8
  --ox-checkbox-size: 12px;
9
9
  }
10
10
 
11
- #demo {
12
- position: relative;
13
- height: 300px;
14
- background-color: lightgray;
15
- vertical-align: middle;
11
+ a {
12
+ display: block;
16
13
  }
17
14
  </style>
15
+
18
16
  <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet" />
19
17
  <link href="https://fonts.googleapis.com/css?family=Material+Icons&display=block" rel="stylesheet" />
18
+ <link href="/themes/app-theme.css" rel="stylesheet" />
19
+ <link href="/themes/form-theme.css" rel="stylesheet" />
20
20
  </head>
21
21
  <body>
22
- <div id="demo"></div>
23
-
24
- <script type="module">
25
- import { html, render } from 'lit'
26
- import '../dist/src/ox-data-entry-form.js'
27
-
28
- const parent = document.querySelector('#demo')
29
- const dataSet = {
30
- name: 'sample',
31
- description: 'sample description',
32
- dataItems: [
33
- {
34
- name: '창고 온도',
35
- description: '창고 온도는 섭씨 0도 이하로 유지되어야 합니다.',
36
- sequence: 1,
37
- tag: 'temp',
38
- type: 'number',
39
- quota: 1
40
- },
41
- {
42
- name: '창고 습도',
43
- description: '창고 습도는 30% 이하로 유지되어야 합니다.',
44
- sequence: 2,
45
- tag: 'humid',
46
- type: 'number',
47
- quota: 5
48
- },
49
- {
50
- name: '육안 검사',
51
- description: '육안 검사는 포장전 30분 내로 실행되어야 합니다.',
52
- sequence: 3,
53
- tag: 'inspection',
54
- type: 'boolean',
55
- quota: 3
56
- },
57
- {
58
- name: '품평',
59
- description: '품평은 최우수/우수/보통/미달을 포함하여 간단히 평가.',
60
- sequence: 4,
61
- tag: 'evaluation',
62
- type: 'select',
63
- options: {
64
- options: [
65
- { text: '최우수', value: '최우수' },
66
- { text: '우수', value: '우수' },
67
- { text: '보통', value: '보통' },
68
- { text: '미달', value: '미달' }
69
- ]
70
- },
71
- quota: 3
72
- },
73
- {
74
- name: '코멘트',
75
- description: '특이사항을 기록함.',
76
- sequence: 4,
77
- tag: 'comment',
78
- type: 'string',
79
- quota: 1
80
- }
81
- ]
82
- }
83
-
84
- var value = {
85
- temp: 1000,
86
- humid: [20, 23, 21, 26, 27],
87
- inspection: [true, false, true],
88
- evaluation: ['최우수', '보통', '우수']
89
- }
90
-
91
- render(
92
- html`<ox-data-entry-form
93
- .dataSet=${dataSet}
94
- .value=${value}
95
- @change=${e => {
96
- value = e.detail
97
- console.log('change', value)
98
- }}
99
- ></ox-data-entry-form>`,
100
- parent
101
- )
102
- </script>
22
+ <a href="./ox-data-entry-form.html">ox-data-entry-form</a>
23
+ <a href="./ox-data-item-spec.html">ox-data-item-spec</a>
24
+ <a href="./data-item-grist.html">data-item-grist</a>
103
25
  </body>
104
26
  </html>