@things-factory/dataset 9.1.18 → 10.0.0-beta.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.
Files changed (81) hide show
  1. package/EXPLORATION_INDEX.md +252 -0
  2. package/FRONTEND_ARCHITECTURE.md +732 -0
  3. package/QUICK_REFERENCE.md +365 -0
  4. package/dist-client/pages/data-archive/data-archive-list-page.d.ts +1 -7
  5. package/dist-client/pages/data-archive/data-archive-list-page.js +42 -77
  6. package/dist-client/pages/data-archive/data-archive-list-page.js.map +1 -1
  7. package/dist-client/pages/data-entry/data-entry-list-page.d.ts +1 -7
  8. package/dist-client/pages/data-entry/data-entry-list-page.js +77 -143
  9. package/dist-client/pages/data-entry/data-entry-list-page.js.map +1 -1
  10. package/dist-client/pages/data-key-set/data-key-set-list-page.d.ts +1 -7
  11. package/dist-client/pages/data-key-set/data-key-set-list-page.js +69 -131
  12. package/dist-client/pages/data-key-set/data-key-set-list-page.js.map +1 -1
  13. package/dist-client/pages/data-ooc/data-ooc-list-page.d.ts +0 -6
  14. package/dist-client/pages/data-ooc/data-ooc-list-page.js +87 -166
  15. package/dist-client/pages/data-ooc/data-ooc-list-page.js.map +1 -1
  16. package/dist-client/pages/data-report/data-report-list-page.d.ts +1 -7
  17. package/dist-client/pages/data-report/data-report-list-page.js +71 -132
  18. package/dist-client/pages/data-report/data-report-list-page.js.map +1 -1
  19. package/dist-client/pages/data-report/data-report-samples-page.d.ts +1 -7
  20. package/dist-client/pages/data-report/data-report-samples-page.js +17 -30
  21. package/dist-client/pages/data-report/data-report-samples-page.js.map +1 -1
  22. package/dist-client/pages/data-sample/data-sample-list-page.d.ts +0 -6
  23. package/dist-client/pages/data-sample/data-sample-list-page.js +68 -130
  24. package/dist-client/pages/data-sample/data-sample-list-page.js.map +1 -1
  25. package/dist-client/pages/data-sample/data-sample-search-page.d.ts +1 -7
  26. package/dist-client/pages/data-sample/data-sample-search-page.js +63 -116
  27. package/dist-client/pages/data-sample/data-sample-search-page.js.map +1 -1
  28. package/dist-client/pages/data-sensor/data-sensor-list-page.d.ts +0 -6
  29. package/dist-client/pages/data-sensor/data-sensor-list-page.js +89 -167
  30. package/dist-client/pages/data-sensor/data-sensor-list-page.js.map +1 -1
  31. package/dist-client/pages/data-set/data-item-list.js +15 -1
  32. package/dist-client/pages/data-set/data-item-list.js.map +1 -1
  33. package/dist-client/pages/data-set/data-set-list-page.d.ts +0 -6
  34. package/dist-client/pages/data-set/data-set-list-page.js +2 -4
  35. package/dist-client/pages/data-set/data-set-list-page.js.map +1 -1
  36. package/dist-client/pages/data-summary/data-summary-list-page.d.ts +1 -7
  37. package/dist-client/pages/data-summary/data-summary-list-page.js +56 -105
  38. package/dist-client/pages/data-summary/data-summary-list-page.js.map +1 -1
  39. package/dist-client/pages/data-summary/data-summary-period-page.d.ts +1 -7
  40. package/dist-client/pages/data-summary/data-summary-period-page.js +50 -90
  41. package/dist-client/pages/data-summary/data-summary-period-page.js.map +1 -1
  42. package/dist-client/pages/data-summary/data-summary-search-page.d.ts +1 -7
  43. package/dist-client/pages/data-summary/data-summary-search-page.js +61 -111
  44. package/dist-client/pages/data-summary/data-summary-search-page.js.map +1 -1
  45. package/dist-client/tsconfig.tsbuildinfo +1 -1
  46. package/dist-server/activities/activity-data-review.js +5 -2
  47. package/dist-server/activities/activity-data-review.js.map +1 -1
  48. package/dist-server/activities/activity-ooc-review.js +4 -1
  49. package/dist-server/activities/activity-ooc-review.js.map +1 -1
  50. package/dist-server/controllers/create-data-ooc.js +2 -1
  51. package/dist-server/controllers/create-data-ooc.js.map +1 -1
  52. package/dist-server/controllers/create-data-sample.js +59 -7
  53. package/dist-server/controllers/create-data-sample.js.map +1 -1
  54. package/dist-server/controllers/issue-data-collection-task.js +9 -5
  55. package/dist-server/controllers/issue-data-collection-task.js.map +1 -1
  56. package/dist-server/controllers/issue-ooc-resolve.js +11 -6
  57. package/dist-server/controllers/issue-ooc-resolve.js.map +1 -1
  58. package/dist-server/controllers/issue-ooc-review.js +9 -6
  59. package/dist-server/controllers/issue-ooc-review.js.map +1 -1
  60. package/dist-server/service/data-set/data-item-type.d.ts +259 -0
  61. package/dist-server/service/data-set/data-item-type.js +259 -0
  62. package/dist-server/service/data-set/data-item-type.js.map +1 -1
  63. package/dist-server/service/index.d.ts +1 -1
  64. package/dist-server/tsconfig.tsbuildinfo +1 -1
  65. package/dist-server/utils/index.d.ts +1 -0
  66. package/dist-server/utils/index.js +1 -0
  67. package/dist-server/utils/index.js.map +1 -1
  68. package/dist-server/utils/media-validation.d.ts +51 -0
  69. package/dist-server/utils/media-validation.js +148 -0
  70. package/dist-server/utils/media-validation.js.map +1 -0
  71. package/package.json +26 -26
  72. package/spec/integration/debug.spec.ts +42 -0
  73. package/spec/integration/ooc-lifecycle.spec.ts +484 -0
  74. package/spec/integration/ooc-workflow.spec.ts +276 -0
  75. package/spec/integration/simple.spec.ts +62 -0
  76. package/spec/unit/controllers/activity-callbacks.spec.ts +609 -0
  77. package/spec/unit/controllers/create-data-ooc.spec.ts +310 -0
  78. package/spec/unit/controllers/issue-ooc-resolve.spec.ts +431 -0
  79. package/spec/unit/controllers/issue-ooc-review.spec.ts +288 -0
  80. package/spec/unit/data-use-case.spec.ts +150 -0
  81. package/spec/unit/ooc-state-transition.spec.ts +233 -0
@@ -0,0 +1,365 @@
1
+ # Quick Reference: Frontend Component Architecture
2
+
3
+ ## File Locations - Quick Lookup
4
+
5
+ ### Client-Side Components (Your Repo)
6
+ ```
7
+ /Users/super/Documents/GitHub/things-factory/packages/dataset/client/
8
+ ├── components/
9
+ │ ├── data-entry-form.ts - Form wrapper using ox-data-entry-form
10
+ │ └── checklist-entry-form.ts - Checklist wrapper using ox-checklist-entry-form
11
+ └── activities/
12
+ └── activity-data-collect-edit.ts - Workflow activity entry point
13
+ ```
14
+
15
+ ### Server-Side Types & Utils (Your Repo)
16
+ ```
17
+ /Users/super/Documents/GitHub/things-factory/packages/dataset/server/
18
+ ├── service/data-set/
19
+ │ └── data-item-type.ts - DataItemType enum + media options schema
20
+ └── utils/
21
+ └── media-validation.ts - Media file validation utilities
22
+ ```
23
+
24
+ ### Core Components (Dependency - Node Modules)
25
+ ```
26
+ @operato/dataset (in node_modules)
27
+ ├── ox-data-entry-form.js - Main form component
28
+ ├── ox-data-entry-subgroup-form.js - Grouped items in Grist table
29
+ └── ox-data-input-factory.js - Type-to-component mapping factory
30
+
31
+ @operato/input (in node_modules)
32
+ ├── ox-input-file.js - File upload component
33
+ ├── ox-input-image.js - Image upload component
34
+ ├── ox-input-signature.js - Digital signature component
35
+ └── ox-form-field.js - Base class for all input components
36
+ ```
37
+
38
+ ---
39
+
40
+ ## How Data Entry Works - 5 Step Flow
41
+
42
+ ### Step 1: User Opens Activity
43
+ File: `activity-data-collect-edit.ts`
44
+ - Gets `dataSetId` from workflow
45
+ - Fetches DataSet with dataItems via GraphQL
46
+
47
+ ### Step 2: OxDataEntryForm Renders
48
+ File: `@operato/dataset/ox-data-entry-form.js`
49
+ - Iterates through `dataItems.filter(item => item.active)`
50
+ - For grouped items: renders `ox-data-entry-subgroup-form`
51
+ - For non-grouped: calls `OxDataInputFactory.createInputElement()`
52
+
53
+ ### Step 3: OxDataInputFactory Creates Input
54
+ File: `@operato/dataset/ox-data-input-factory.js`
55
+ - Switch statement on `dataItem.type`
56
+ - Currently supports: text, number, boolean, date, datetime, select, radio, file, signature
57
+ - **MISSING:** image, video, audio
58
+
59
+ ### Step 4: User Submits Form
60
+ - Form collects values from all inputs by `name` attribute
61
+ - `buildValue()` extracts values into object: `{ [tag]: any }`
62
+ - GraphQL mutation sends with `context: { hasUpload: true }`
63
+
64
+ ### Step 5: Server Processes Files
65
+ File: `create-data-sample.ts`
66
+ - Iterates `dataItems` looking for `isFileOrMediaType()`
67
+ - If media type: validates with `validateMediaFile()`
68
+ - Creates attachments and stores file paths in data
69
+
70
+ ---
71
+
72
+ ## Type Mapping (OxDataInputFactory)
73
+
74
+ ### Current Types
75
+ ```
76
+ 'select' → <select name=${tag}> with options
77
+ 'radio' → <label><input type="radio"> with options
78
+ 'boolean' → <input type="checkbox">
79
+ 'number' → <input type="number">
80
+ 'date' → <input type="date">
81
+ 'datetime' → <input type="datetime-local">
82
+ 'file' → <ox-input-file multiple>
83
+ 'signature' → <ox-input-signature>
84
+ 'text' → <input type="text"> (default)
85
+ ```
86
+
87
+ ### Missing Types (Need Implementation)
88
+ ```
89
+ 'image' → <ox-input-image> (TO BE CREATED)
90
+ 'video' → <ox-input-video> (TO BE CREATED)
91
+ 'audio' → <ox-input-audio> (TO BE CREATED)
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Key Functions & Classes
97
+
98
+ ### OxFormField (Base Class)
99
+ **Properties:**
100
+ - `name: string` - Form field identifier
101
+ - `value: T` - Field value (generic)
102
+ - `disabled: boolean` - Disabled state
103
+
104
+ **Methods:**
105
+ - `connectedCallback()` - Register with parent form
106
+ - `appendFormData(e: FormDataEvent)` - Add to form submission
107
+
108
+ ### OxDataEntryForm
109
+ **Key Methods:**
110
+ - `buildInputs()` - Generate all input elements
111
+ - `buildValue()` - Extract form values as object
112
+ - `extractValuesFromInputs()` - Query DOM by name attribute
113
+
114
+ ### OxDataInputFactory
115
+ **Static Methods:**
116
+ - `createInputElement(type, tag, value, options, idx)` - Route to correct component
117
+ - `mapGristType(type)` - Convert to Grist column type
118
+ - `getGristRecordOptions(type, options)` - Grid cell configuration
119
+
120
+ ### Media Validation Utils
121
+ **Functions:**
122
+ - `validateMediaFile(file, mediaType, options)` - Main validator
123
+ - `isValidMimeType(mediaType, mimetype)` - Check MIME type
124
+ - `isAcceptedFormat(filename, acceptFormats)` - Check extension
125
+ - `isValidFileSize(fileSize, maxSize)` - Check size
126
+ - `isMediaType(type)` - Check if image/video/audio
127
+
128
+ ---
129
+
130
+ ## Adding New Media Components - Checklist
131
+
132
+ ### 1. Create Component File
133
+ ```
134
+ Location: packages/dataset/client/components/ox-input-image.ts
135
+ Extend: OxFormField
136
+ Pattern: Similar to ox-input-file
137
+ Methods needed:
138
+ - render()
139
+ - updated()
140
+ - firstUpdated()
141
+ - _onChangeValue()
142
+ - _notifyChange()
143
+ ```
144
+
145
+ ### 2. Update OxDataInputFactory
146
+ File: Update @operato/dataset source (or create wrapper)
147
+ Add to switch:
148
+ ```javascript
149
+ case 'image': return html`<ox-input-image ...>`;
150
+ case 'video': return html`<ox-input-video ...>`;
151
+ case 'audio': return html`<ox-input-audio ...>`;
152
+ ```
153
+
154
+ ### 3. Add to mapGristType()
155
+ ```javascript
156
+ case 'image': return 'image';
157
+ case 'video': return 'video';
158
+ case 'audio': return 'audio';
159
+ ```
160
+
161
+ ### 4. Add to getGristRecordOptions()
162
+ ```javascript
163
+ case 'image':
164
+ case 'video':
165
+ case 'audio':
166
+ return { multiple: options.multiple || false };
167
+ ```
168
+
169
+ ### 5. Import in Components
170
+ ```typescript
171
+ import '@operato/dataset/ox-input-image.js'
172
+ import '@operato/dataset/ox-input-video.js'
173
+ import '@operato/dataset/ox-input-audio.js'
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Component Value Extraction (Important!)
179
+
180
+ ### How Form Gets Values
181
+ ```typescript
182
+ // In ox-data-entry-form.js, line ~89
183
+ const editors = Array.from(
184
+ this.renderRoot.querySelectorAll(`[name=${tag}]`)
185
+ )
186
+ // Extracts value from: name="product_image"
187
+ ```
188
+
189
+ ### Why Name Attribute Matters
190
+ - Form values keyed by `name` attribute
191
+ - Must match `dataItem.tag` value
192
+ - All OxInput* components must set name on native input
193
+
194
+ ### File Upload Special Handling
195
+ Files passed as: `[{ file: FileUpload }, ...]`
196
+ Backend converts to: `[{ id, mimetype, name, fullpath }, ...]`
197
+
198
+ ---
199
+
200
+ ## DataItem Configuration Examples
201
+
202
+ ### Image Field Config
203
+ ```typescript
204
+ {
205
+ name: 'Product Image',
206
+ tag: 'product_image', // ← Used as name attribute
207
+ type: 'image', // ← Routes to OxInputImage
208
+ description: 'Upload product photo',
209
+ unit: 'JPG/PNG',
210
+ quota: 3, // Allow up to 3 images
211
+ options: {
212
+ accept: ['jpeg', 'png'],
213
+ maxSize: 10485760, // 10MB
214
+ maxWidth: 4096,
215
+ maxHeight: 4096,
216
+ multiple: true
217
+ }
218
+ }
219
+ ```
220
+
221
+ ### Video Field Config
222
+ ```typescript
223
+ {
224
+ name: 'Demo Video',
225
+ tag: 'demo_video',
226
+ type: 'video',
227
+ quota: 1,
228
+ options: {
229
+ accept: ['mp4', 'webm'],
230
+ maxSize: 104857600, // 100MB
231
+ maxDuration: 300, // 5 minutes
232
+ multiple: false
233
+ }
234
+ }
235
+ ```
236
+
237
+ ### Audio Field Config
238
+ ```typescript
239
+ {
240
+ name: 'Voice Note',
241
+ tag: 'voice_note',
242
+ type: 'audio',
243
+ quota: 1,
244
+ options: {
245
+ accept: ['mp3', 'wav'],
246
+ maxSize: 52428800, // 50MB
247
+ maxDuration: 600, // 10 minutes
248
+ multiple: false
249
+ }
250
+ }
251
+ ```
252
+
253
+ ---
254
+
255
+ ## File Upload GraphQL Context
256
+
257
+ ### Why `hasUpload: true`?
258
+ ```typescript
259
+ // In data-entry-form.ts
260
+ context: {
261
+ hasUpload: true
262
+ }
263
+ ```
264
+ This tells Apollo Client to:
265
+ 1. Use `multipart/form-data` encoding (not JSON)
266
+ 2. Include files in GraphQL variables
267
+ 3. Stream files to server
268
+
269
+ ### GraphQL Variable Structure
270
+ ```typescript
271
+ {
272
+ dataSample: {
273
+ dataSet: { id: '...' },
274
+ data: {
275
+ product_image: [{file: FileUpload}, ...],
276
+ demo_video: [{file: FileUpload}],
277
+ ...
278
+ }
279
+ }
280
+ }
281
+ ```
282
+
283
+ ---
284
+
285
+ ## Common Gotchas
286
+
287
+ ### 1. OxInputImage vs OxInputFile
288
+ - **File**: Generic file upload
289
+ - **Image**: Image-specific with preview/validation
290
+ - Note: OxInputImage exists in @operato/input but not used in factory
291
+
292
+ ### 2. Name Attribute is Critical
293
+ ```typescript
294
+ // CORRECT - matches dataItem.tag
295
+ <ox-input-image name="product_image" ...></ox-input-image>
296
+
297
+ // WRONG - value won't be extracted
298
+ <ox-input-image ...></ox-input-image>
299
+ ```
300
+
301
+ ### 3. Quota vs Multiple
302
+ ```typescript
303
+ quota: 3, options: { multiple: true }
304
+ // Allows user to select 3 times, each time multiple files
305
+
306
+ quota: 1, options: { multiple: false }
307
+ // Single file selection
308
+ ```
309
+
310
+ ### 4. Group vs Subgroup
311
+ ```typescript
312
+ group: 'measurements' // Groups items in table (Grist)
313
+ subgroup: 'length' // Secondary grouping
314
+ // Non-grouped items show in main form
315
+ ```
316
+
317
+ ### 5. Active vs Hidden
318
+ ```typescript
319
+ active: true // Rendered in form
320
+ active: false // Skipped entirely
321
+ hidden: true // Rendered but CSS hidden (for validation specs)
322
+ ```
323
+
324
+ ---
325
+
326
+ ## File Paths in Codebase
327
+
328
+ ### Where to Make Changes
329
+ 1. **New Components**: `packages/dataset/client/components/`
330
+ 2. **Type Updates**: Update @operato/dataset OR create wrapper
331
+ 3. **Media Options**: Already defined in `data-item-type.ts`
332
+ 4. **Validation**: Already implemented in `media-validation.ts`
333
+
334
+ ### Dependencies Already Available
335
+ ```json
336
+ {
337
+ "@operato/input": "^9.0.0",
338
+ "@operato/dataset": "^9.0.0",
339
+ "lit": "^2.x.x"
340
+ }
341
+ ```
342
+
343
+ ### Key Imports for New Components
344
+ ```typescript
345
+ import { css, html } from 'lit'
346
+ import { customElement, property, query } from 'lit/decorators.js'
347
+ import { OxFormField } from '@operato/input'
348
+ ```
349
+
350
+ ---
351
+
352
+ ## Testing Checklist
353
+
354
+ Before deploying new media components:
355
+
356
+ - [ ] Component renders with correct icon/label
357
+ - [ ] File selection works (click and drag-drop)
358
+ - [ ] Value extracted correctly by name attribute
359
+ - [ ] Multiple/single file toggle works
360
+ - [ ] GraphQL mutation includes files
361
+ - [ ] Server-side validation passes
362
+ - [ ] Media validation errors displayed to user
363
+ - [ ] Attachment created in database
364
+ - [ ] File paths stored in DataSample.data
365
+ - [ ] Grist grid column type correct for subgroup items
@@ -4,13 +4,7 @@ import '@operato/context/ox-context-page-toolbar.js';
4
4
  import { FetchOption } from '@operato/data-grist';
5
5
  import { PageView } from '@operato/shell';
6
6
  import './data-archive-request-popup.js';
7
- declare const DataArchiveListPage_base: (new (...args: any[]) => {
8
- _storeUnsubscribe: import("redux").Unsubscribe;
9
- connectedCallback(): void;
10
- disconnectedCallback(): void;
11
- stateChanged(_state: unknown): void;
12
- readonly isConnected: boolean;
13
- }) & (new (...args: any[]) => import("lit").LitElement) & typeof PageView;
7
+ declare const DataArchiveListPage_base: (new (...args: any[]) => import("lit").LitElement) & typeof PageView;
14
8
  export declare class DataArchiveListPage extends DataArchiveListPage_base {
15
9
  static styles: import("lit").CSSResult[];
16
10
  gristConfig: any;
@@ -5,16 +5,15 @@ import '@operato/context/ox-context-page-toolbar.js';
5
5
  import gql from 'graphql-tag';
6
6
  import { css, html } from 'lit';
7
7
  import { customElement, query, state } from 'lit/decorators.js';
8
- import { connect } from 'pwa-helpers/connect-mixin';
9
8
  import { DataGrist } from '@operato/data-grist';
10
9
  import { client } from '@operato/graphql';
11
10
  import { i18next, localize } from '@operato/i18n';
12
11
  import { openPopup } from '@operato/layout';
13
- import { PageView, store } from '@operato/shell';
12
+ import { PageView } from '@operato/shell';
14
13
  import { CommonHeaderStyles, ScrollbarStyles } from '@operato/styles';
15
14
  import { isMobileDevice } from '@operato/utils';
16
15
  import './data-archive-request-popup.js';
17
- let DataArchiveListPage = class DataArchiveListPage extends connect(store)(localize(i18next)(PageView)) {
16
+ let DataArchiveListPage = class DataArchiveListPage extends localize(i18next)(PageView) {
18
17
  constructor() {
19
18
  super(...arguments);
20
19
  this.mode = isMobileDevice() ? 'CARD' : 'GRID';
@@ -23,51 +22,41 @@ let DataArchiveListPage = class DataArchiveListPage extends connect(store)(local
23
22
  ScrollbarStyles,
24
23
  CommonHeaderStyles,
25
24
  css `
26
- :host {
27
- display: flex;
25
+ :host { display: flex;
28
26
  flex-direction: column;
29
27
 
30
28
  overflow: hidden;
31
- }
29
+ }
32
30
 
33
- ox-grist {
34
- overflow-y: auto;
31
+ ox-grist { overflow-y: auto;
35
32
  flex: 1;
36
- }
33
+ }
37
34
 
38
- .header {
39
- grid-template-areas: 'filters actions';
40
- }
35
+ .header { grid-template-areas: 'filters actions';
36
+ }
41
37
  `
42
38
  ]; }
43
39
  get context() {
44
- return {
45
- title: i18next.t('title.data-archive list'),
46
- search: {
47
- handler: (search) => {
40
+ return { title: i18next.t('title.data-archive list'),
41
+ search: { handler: (search) => {
48
42
  this.grist.searchText = search;
49
43
  },
50
- value: this.grist?.searchText || ''
51
- },
52
- filter: {
53
- handler: () => {
44
+ value: this.grist?.searchText || '' },
45
+ filter: { handler: () => {
54
46
  this.grist.toggleHeadroom();
55
47
  }
56
48
  },
57
49
  help: 'dataset/data-archive',
58
50
  actions: [
59
- {
60
- title: i18next.t('button.request-archive'),
51
+ { title: i18next.t('button.request-archive'),
61
52
  action: this.openArchivePopup.bind(this),
62
53
  icon: 'archive'
63
54
  }
64
55
  ],
65
- exportable: {
66
- name: i18next.t('title.data-archive list'),
56
+ exportable: { name: i18next.t('title.data-archive list'),
67
57
  data: this._exportableData.bind(this)
68
58
  },
69
- toolbar: false
70
- };
59
+ toolbar: false };
71
60
  }
72
61
  render() {
73
62
  const mode = this.mode || (isMobileDevice() ? 'LIST' : 'GRID');
@@ -89,78 +78,65 @@ let DataArchiveListPage = class DataArchiveListPage extends connect(store)(local
89
78
  `;
90
79
  }
91
80
  async pageInitialized(lifecycle) {
92
- this.gristConfig = {
93
- list: { fields: ['updater', 'updatedAt'] },
81
+ this.gristConfig = { list: { fields: ['updater', 'updatedAt'] },
94
82
  columns: [
95
83
  { type: 'gutter', gutterName: 'sequence' },
96
84
  // { type: 'gutter', gutterName: 'row-selector', multiple: true },
97
- {
98
- type: 'resource-object',
85
+ { type: 'resource-object',
99
86
  name: 'creator',
100
87
  header: i18next.t('field.creator'),
101
88
  sortable: true,
102
89
  width: 120,
103
90
  imex: true
104
91
  },
105
- {
106
- type: 'datetime',
92
+ { type: 'datetime',
107
93
  name: 'createdAt',
108
94
  header: i18next.t('field.created_at'),
109
95
  sortable: true,
110
96
  width: 180,
111
97
  imex: true
112
98
  },
113
- {
114
- type: 'datetime',
99
+ { type: 'datetime',
115
100
  name: 'updatedAt',
116
101
  header: i18next.t('field.updated_at'),
117
102
  sortable: true,
118
103
  width: 180,
119
104
  imex: true
120
105
  },
121
- {
122
- type: 'json5',
106
+ { type: 'json5',
123
107
  name: 'requestParams',
124
108
  header: i18next.t('field.request-params'),
125
- record: {
126
- editable: false
109
+ record: { editable: false
127
110
  },
128
111
  width: 200,
129
112
  imex: true
130
113
  },
131
- {
132
- type: 'string',
114
+ { type: 'string',
133
115
  name: 'downloadUrl',
134
116
  label: true,
135
117
  header: i18next.t('field.download-url'),
136
- record: {
137
- editable: false
118
+ record: { editable: false
138
119
  },
139
120
  width: 240,
140
121
  imex: true
141
122
  },
142
- {
143
- type: 'string',
123
+ { type: 'string',
144
124
  name: 'status',
145
125
  label: true,
146
126
  header: i18next.t('field.status'),
147
- record: {
148
- editable: false
127
+ record: { editable: false
149
128
  },
150
129
  sortable: true,
151
130
  width: 120,
152
131
  imex: true
153
132
  }
154
133
  ],
155
- rows: {
156
- appendable: false,
157
- selectable: {
158
- multiple: true
134
+ rows: { appendable: false,
135
+ selectable: { multiple: true
159
136
  }
160
137
  },
161
138
  sorters: [
162
- {
163
- name: 'createdAt',
139
+ { name: 'createdAt',
164
140
  desc: true
165
141
  }
166
142
  ]
@@ -174,46 +150,37 @@ let DataArchiveListPage = class DataArchiveListPage extends connect(store)(local
174
150
  this.popup = openPopup(html ` <data-archive-request-popup
175
151
  @requested=${this.closePopupAndRefesh.bind(this)}
176
152
  @created=${this.closePopupAndRefesh.bind(this)}
177
- ></data-archive-request-popup>`, {
178
- backdrop: true,
153
+ ></data-archive-request-popup>`, { backdrop: true,
179
154
  size: 'small',
180
155
  title: i18next.t('title.data-archive request popup')
181
156
  });
182
157
  }
183
158
  async fetchHandler({ page, limit, sortings = [], filters = [] }) {
184
- const response = await client.query({
185
- query: gql `
186
- query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
187
- responses: dataArchives(filters: $filters, pagination: $pagination, sortings: $sortings) {
188
- items {
189
- id
159
+ const response = await client.query({ query: gql `
160
+ query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) { responses: dataArchives(filters: $filters, pagination: $pagination, sortings: $sortings) { items { id
190
161
  type
191
162
  requestParams
192
163
  downloadUrl
193
164
  status
194
- creator {
195
- id
165
+ creator { id
196
166
  name
197
- }
198
- updater {
199
- id
167
+ }
168
+ updater { id
200
169
  name
201
- }
170
+ }
202
171
  updatedAt
203
172
  createdAt
204
- }
173
+ }
205
174
  total
206
- }
207
- }
175
+ }
176
+ }
208
177
  `,
209
- variables: {
210
- filters,
178
+ variables: { filters,
211
179
  pagination: { page, limit },
212
180
  sortings
213
181
  }
214
182
  });
215
- return {
216
- total: response.data.responses.total || 0,
183
+ return { total: response.data.responses.total || 0,
217
184
  records: response.data.responses.items || []
218
185
  };
219
186
  }
@@ -229,8 +196,7 @@ let DataArchiveListPage = class DataArchiveListPage extends connect(store)(local
229
196
  .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
230
197
  .map(column => {
231
198
  return column.imex === true
232
- ? {
233
- header: column.header.renderer(column),
199
+ ? { header: column.header.renderer(column),
234
200
  key: column.name,
235
201
  width: column.width,
236
202
  type: column.type
@@ -238,8 +204,7 @@ let DataArchiveListPage = class DataArchiveListPage extends connect(store)(local
238
204
  : column.imex;
239
205
  });
240
206
  var data = records.map(item => {
241
- return {
242
- id: item.id,
207
+ return { id: item.id,
243
208
  ...this.gristConfig.columns
244
209
  .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
245
210
  .reduce((record, column) => {