@mongoosejs/studio 0.3.3 → 0.3.4
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/backend/actions/Model/getDocuments.js +16 -7
- package/backend/actions/Model/getDocumentsStream.js +16 -9
- package/backend/actions/Model/getSuggestedProjection.js +33 -0
- package/backend/actions/Model/index.js +1 -0
- package/backend/authorize.js +1 -0
- package/backend/helpers/getSuggestedProjection.js +37 -0
- package/backend/helpers/parseFieldsParam.js +36 -0
- package/frontend/public/app.js +690 -172
- package/frontend/public/dark-theme.css +166 -0
- package/frontend/public/theme-variables.css +30 -0
- package/frontend/public/tw.css +110 -46
- package/frontend/src/api.js +7 -1
- package/frontend/src/dashboard/dashboard.js +1 -1
- package/frontend/src/list-mixed/list-mixed.html +0 -1
- package/frontend/src/list-string/list-string.html +0 -1
- package/frontend/src/models/models.css +25 -90
- package/frontend/src/models/models.html +213 -53
- package/frontend/src/models/models.js +611 -132
- package/frontend/src/navbar/navbar.js +1 -1
- package/frontend/src/task-by-name/task-by-name.html +11 -11
- package/frontend/src/task-single/task-single.html +4 -4
- package/frontend/src/tasks/task-details/task-details.html +6 -6
- package/package.json +1 -1
|
@@ -5,105 +5,30 @@
|
|
|
5
5
|
min-height: calc(100% - 56px);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
.models button.gray {
|
|
9
|
-
color: black;
|
|
10
|
-
background-color: #eee;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
.models .model-selector {
|
|
14
|
-
flex-grow: 0;
|
|
15
|
-
padding: 15px;
|
|
16
|
-
padding-top: 0px;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
.models h1 {
|
|
20
|
-
margin-top: 0px;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
8
|
.models .documents {
|
|
24
9
|
flex-grow: 1;
|
|
25
|
-
overflow:
|
|
10
|
+
overflow: visible;
|
|
26
11
|
max-height: calc(100vh - 56px);
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-direction: column;
|
|
27
14
|
}
|
|
28
15
|
|
|
29
|
-
.models .documents
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
padding: 0;
|
|
36
|
-
margin-right: 1em;
|
|
37
|
-
white-space: nowrap;
|
|
38
|
-
z-index: -1;
|
|
39
|
-
border-collapse: collapse;
|
|
40
|
-
line-height: 1.5em;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.models .documents table th {
|
|
44
|
-
position: sticky;
|
|
45
|
-
top: 42px;
|
|
46
|
-
z-index: 1;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.models .documents table th:after {
|
|
50
|
-
content: "";
|
|
51
|
-
position: absolute;
|
|
52
|
-
left: 0;
|
|
53
|
-
width: 100%;
|
|
54
|
-
bottom: -1px;
|
|
55
|
-
border-bottom: thin solid rgba(0, 0, 0, 0.12);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
.models .documents table tr {
|
|
59
|
-
color: black;
|
|
60
|
-
border-spacing: 0px 0px;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
.models .documents table th {
|
|
64
|
-
border-bottom: thin solid rgba(0, 0, 0, 0.12);
|
|
65
|
-
text-align: left;
|
|
66
|
-
height: 48px;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.models .documents table td {
|
|
70
|
-
border-bottom: thin solid rgba(0, 0, 0, 0.12);
|
|
71
|
-
text-align: left;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.models textarea {
|
|
75
|
-
font-size: 1.2em;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
.models .path-type {
|
|
79
|
-
color: rgba(0, 0, 0, 0.36);
|
|
80
|
-
font-size: 0.8em;
|
|
16
|
+
.models .documents-container {
|
|
17
|
+
flex: 1;
|
|
18
|
+
min-height: 0;
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
overflow-y: auto;
|
|
81
22
|
}
|
|
82
23
|
|
|
83
24
|
.models .documents-menu {
|
|
84
25
|
position: sticky;
|
|
85
26
|
top: 0;
|
|
86
|
-
z-index:
|
|
27
|
+
z-index: 30;
|
|
87
28
|
padding: 4px;
|
|
88
29
|
display: flex;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
.models .documents-menu .search-input {
|
|
92
|
-
flex-grow: 1;
|
|
93
|
-
align-items: center;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
.models .search-input input {
|
|
97
|
-
padding: 0.25em 0.5em;
|
|
98
|
-
font-size: 1.1em;
|
|
99
|
-
border: 1px solid #ddd;
|
|
100
|
-
border-radius: 3px;
|
|
101
|
-
width: calc(100% - 1em);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
.models .sort-arrow {
|
|
105
|
-
padding-left: 10px;
|
|
106
|
-
padding-right: 10px;
|
|
30
|
+
flex-direction: column;
|
|
31
|
+
flex-shrink: 0;
|
|
107
32
|
}
|
|
108
33
|
|
|
109
34
|
.models .loader {
|
|
@@ -115,8 +40,18 @@
|
|
|
115
40
|
height: 4em;
|
|
116
41
|
}
|
|
117
42
|
|
|
118
|
-
.models .
|
|
119
|
-
|
|
120
|
-
|
|
43
|
+
.models .loader-overlay {
|
|
44
|
+
position: absolute;
|
|
45
|
+
inset: 0;
|
|
46
|
+
z-index: 20;
|
|
47
|
+
display: flex;
|
|
121
48
|
align-items: center;
|
|
49
|
+
justify-content: center;
|
|
50
|
+
background: var(--color-page);
|
|
51
|
+
opacity: 0.9;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Table cell: copy icon only copies; rest of cell opens document */
|
|
55
|
+
.models .table-cell-copy {
|
|
56
|
+
cursor: pointer;
|
|
122
57
|
}
|
|
@@ -116,8 +116,11 @@
|
|
|
116
116
|
<button
|
|
117
117
|
@click="stagingSelect"
|
|
118
118
|
type="button"
|
|
119
|
-
:class="{
|
|
120
|
-
|
|
119
|
+
:class="{
|
|
120
|
+
'bg-page0 ring-inset ring-2 ring-gray-300 hover:bg-gray-200 text-content-secondary': selectMultiple,
|
|
121
|
+
'bg-primary hover:bg-primary-hover text-primary-text': !selectMultiple
|
|
122
|
+
}"
|
|
123
|
+
class="rounded px-2 py-2 text-sm font-semibold shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary"
|
|
121
124
|
>
|
|
122
125
|
{{ selectMultiple ? 'Cancel' : 'Select' }}
|
|
123
126
|
</button>
|
|
@@ -149,7 +152,7 @@
|
|
|
149
152
|
</button>
|
|
150
153
|
<div
|
|
151
154
|
v-if="showActionsMenu"
|
|
152
|
-
class="absolute right-0 mt-2 w-48 origin-top-right rounded-md bg-surface shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none z-
|
|
155
|
+
class="absolute right-0 mt-2 w-48 origin-top-right rounded-md bg-surface shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none z-50"
|
|
153
156
|
>
|
|
154
157
|
<div class="py-1">
|
|
155
158
|
<button
|
|
@@ -166,13 +169,6 @@
|
|
|
166
169
|
>
|
|
167
170
|
Create
|
|
168
171
|
</button>
|
|
169
|
-
<button
|
|
170
|
-
@click="openFieldSelection(); showActionsMenu = false"
|
|
171
|
-
type="button"
|
|
172
|
-
class="block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted"
|
|
173
|
-
>
|
|
174
|
-
Projection
|
|
175
|
-
</button>
|
|
176
172
|
<button
|
|
177
173
|
@click="openIndexModal"
|
|
178
174
|
type="button"
|
|
@@ -194,6 +190,44 @@
|
|
|
194
190
|
>
|
|
195
191
|
Find oldest document
|
|
196
192
|
</button>
|
|
193
|
+
<button
|
|
194
|
+
@click="toggleRowNumbers()"
|
|
195
|
+
type="button"
|
|
196
|
+
class="block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted"
|
|
197
|
+
>
|
|
198
|
+
{{ showRowNumbers ? 'Hide row numbers' : 'Show row numbers' }}
|
|
199
|
+
</button>
|
|
200
|
+
<button
|
|
201
|
+
@click="resetFilter()"
|
|
202
|
+
type="button"
|
|
203
|
+
class="block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted"
|
|
204
|
+
>
|
|
205
|
+
Reset Filter
|
|
206
|
+
</button>
|
|
207
|
+
<button
|
|
208
|
+
@click="toggleProjectionMenu(); showActionsMenu = false"
|
|
209
|
+
type="button"
|
|
210
|
+
class="block w-full px-4 py-2 text-left text-sm hover:bg-muted"
|
|
211
|
+
:class="isProjectionMenuSelected ? 'text-primary font-semibold' : 'text-content-secondary'"
|
|
212
|
+
>
|
|
213
|
+
{{ isProjectionMenuSelected ? 'Projection (On)' : 'Projection' }}
|
|
214
|
+
</button>
|
|
215
|
+
<button
|
|
216
|
+
v-if="isProjectionMenuSelected"
|
|
217
|
+
@click="clearProjection()"
|
|
218
|
+
type="button"
|
|
219
|
+
class="block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted"
|
|
220
|
+
>
|
|
221
|
+
Reset Projection
|
|
222
|
+
</button>
|
|
223
|
+
<async-button
|
|
224
|
+
v-if="isProjectionMenuSelected"
|
|
225
|
+
type="button"
|
|
226
|
+
@click="applyDefaultProjectionColumns()"
|
|
227
|
+
class="block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted"
|
|
228
|
+
>
|
|
229
|
+
Default
|
|
230
|
+
</async-button>
|
|
197
231
|
</div>
|
|
198
232
|
</div>
|
|
199
233
|
</div>
|
|
@@ -228,37 +262,176 @@
|
|
|
228
262
|
</button>
|
|
229
263
|
</span>
|
|
230
264
|
</div>
|
|
265
|
+
<div v-if="isProjectionMenuSelected && (outputType === 'table' || outputType === 'json')" class="flex items-center gap-2 w-full mt-2 flex-shrink-0">
|
|
266
|
+
<input
|
|
267
|
+
ref="projectionInput"
|
|
268
|
+
v-model="projectionText"
|
|
269
|
+
type="text"
|
|
270
|
+
placeholder="Projection: name email, or -password"
|
|
271
|
+
class="flex-1 min-w-0 rounded border border-edge bg-surface px-2 py-1.5 text-sm font-mono placeholder:text-content-tertiary focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary"
|
|
272
|
+
@focus="initProjection($event)"
|
|
273
|
+
@keydown.enter="applyProjectionFromInput()"
|
|
274
|
+
/>
|
|
275
|
+
</div>
|
|
231
276
|
</div>
|
|
232
|
-
|
|
277
|
+
<!-- In JSON view, this container is the scrollable element used for infinite scroll. -->
|
|
278
|
+
<div class="documents-container relative" ref="documentsContainerScroll" @scroll="checkIfScrolledToBottom">
|
|
233
279
|
<div v-if="error">
|
|
234
280
|
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 relative m-4 rounded-md" role="alert">
|
|
235
281
|
<span class="block font-bold">Error</span>
|
|
236
282
|
<span class="block">{{ error }}</span>
|
|
237
283
|
</div>
|
|
238
284
|
</div>
|
|
239
|
-
<
|
|
240
|
-
<
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
<
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
285
|
+
<div v-else-if="outputType === 'table'" class="flex-1 min-h-0 flex flex-col overflow-hidden">
|
|
286
|
+
<div
|
|
287
|
+
ref="documentsScrollContainer"
|
|
288
|
+
class="overflow-x-auto overflow-y-auto flex-1 min-h-0 border border-edge rounded-lg bg-surface"
|
|
289
|
+
@scroll="checkIfScrolledToBottom"
|
|
290
|
+
>
|
|
291
|
+
<table class="min-w-full border-collapse text-sm">
|
|
292
|
+
<thead class="sticky top-0 z-10 bg-slate-100 dark:bg-shark-800 border-b border-edge">
|
|
293
|
+
<tr>
|
|
294
|
+
<th v-if="showRowNumbers" class="px-3 py-2.5 text-left font-medium text-content border-r border-edge whitespace-nowrap align-middle w-0">
|
|
295
|
+
#
|
|
296
|
+
</th>
|
|
297
|
+
<th
|
|
298
|
+
v-for="path in tableDisplayPaths"
|
|
299
|
+
:key="path.path"
|
|
300
|
+
class="px-3 py-2.5 text-left font-medium text-content border-r border-edge last:border-r-0 whitespace-nowrap align-middle"
|
|
301
|
+
>
|
|
302
|
+
<div class="flex items-center gap-2">
|
|
303
|
+
<span
|
|
304
|
+
@click="addPathFilter(path.path)"
|
|
305
|
+
class="cursor-pointer hover:text-primary truncate min-w-0"
|
|
306
|
+
:title="path.path"
|
|
307
|
+
>
|
|
308
|
+
{{ path.path }}
|
|
309
|
+
</span>
|
|
310
|
+
<span class="text-xs text-content-tertiary shrink-0">({{ path.instance || 'unknown' }})</span>
|
|
311
|
+
<span class="inline-flex shrink-0 gap-0.5 items-center">
|
|
312
|
+
<button
|
|
313
|
+
type="button"
|
|
314
|
+
@click.stop="sortDocs(1, path.path)"
|
|
315
|
+
class="p-0.5 rounded text-content-tertiary hover:text-content hover:bg-muted"
|
|
316
|
+
:class="{ 'text-primary font-semibold': sortBy[path.path] === 1 }"
|
|
317
|
+
:title="sortBy[path.path] === 1 ? 'Clear sort' : 'Sort ascending'"
|
|
318
|
+
>
|
|
319
|
+
↑
|
|
320
|
+
</button>
|
|
321
|
+
<button
|
|
322
|
+
type="button"
|
|
323
|
+
@click.stop="sortDocs(-1, path.path)"
|
|
324
|
+
class="p-0.5 rounded text-content-tertiary hover:text-content hover:bg-muted"
|
|
325
|
+
:class="{ 'text-primary font-semibold': sortBy[path.path] === -1 }"
|
|
326
|
+
:title="sortBy[path.path] === -1 ? 'Clear sort' : 'Sort descending'"
|
|
327
|
+
>
|
|
328
|
+
↓
|
|
329
|
+
</button>
|
|
330
|
+
<button
|
|
331
|
+
v-if="filteredPaths.length > 0"
|
|
332
|
+
type="button"
|
|
333
|
+
@click.stop="removeField(path)"
|
|
334
|
+
class="p-1.5 rounded-md border border-transparent text-content-tertiary hover:text-valencia-600 hover:bg-valencia-50 hover:border-valencia-200 focus:outline-none focus:ring-2 focus:ring-valencia-500/30"
|
|
335
|
+
title="Remove column"
|
|
336
|
+
aria-label="Remove column"
|
|
337
|
+
>
|
|
338
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
|
339
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
|
|
340
|
+
</svg>
|
|
341
|
+
</button>
|
|
342
|
+
</span>
|
|
343
|
+
</div>
|
|
344
|
+
</th>
|
|
345
|
+
<th v-if="filteredPaths.length > 0" class="px-2 py-2.5 border-r border-edge last:border-r-0 align-middle w-0 bg-slate-50 dark:bg-shark-800/80">
|
|
346
|
+
<div class="relative" ref="addFieldContainer">
|
|
347
|
+
<button
|
|
348
|
+
type="button"
|
|
349
|
+
@click="toggleAddFieldDropdown()"
|
|
350
|
+
class="flex items-center justify-center w-8 h-8 rounded border border-dashed border-edge text-content-tertiary hover:border-primary hover:text-primary hover:bg-primary-subtle/30"
|
|
351
|
+
title="Add column"
|
|
352
|
+
aria-label="Add column"
|
|
353
|
+
>
|
|
354
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" /> </svg>
|
|
355
|
+
</button>
|
|
356
|
+
<div
|
|
357
|
+
v-if="showAddFieldDropdown"
|
|
358
|
+
class="absolute right-0 top-full mt-1 z-[100] min-w-[180px] max-w-[280px] rounded-md border border-edge bg-surface shadow-lg py-1 max-h-48 overflow-y-auto"
|
|
359
|
+
>
|
|
360
|
+
<input
|
|
361
|
+
v-if="availablePathsToAdd.length > 5"
|
|
362
|
+
ref="addFieldFilterInput"
|
|
363
|
+
v-model="addFieldFilterText"
|
|
364
|
+
type="text"
|
|
365
|
+
placeholder="Filter fields..."
|
|
366
|
+
class="mx-2 mb-1 w-[calc(100%-1rem)] rounded border border-edge px-2 py-1 text-sm"
|
|
367
|
+
@click.stop
|
|
368
|
+
/>
|
|
369
|
+
<button
|
|
370
|
+
v-for="p in filteredPathsToAdd"
|
|
371
|
+
:key="p.path"
|
|
372
|
+
type="button"
|
|
373
|
+
class="w-full px-3 py-1.5 text-left text-sm hover:bg-muted"
|
|
374
|
+
@click.stop="addField(p)"
|
|
375
|
+
>
|
|
376
|
+
{{ p.path }}
|
|
377
|
+
</button>
|
|
378
|
+
<p v-if="filteredPathsToAdd.length === 0" class="px-3 py-2 text-sm text-content-tertiary">
|
|
379
|
+
{{ addFieldFilterText.trim() ? 'No matching fields' : 'All fields added' }}
|
|
380
|
+
</p>
|
|
381
|
+
</div>
|
|
382
|
+
</div>
|
|
383
|
+
</th>
|
|
384
|
+
</tr>
|
|
385
|
+
</thead>
|
|
386
|
+
<tbody class="bg-surface">
|
|
387
|
+
<tr
|
|
388
|
+
v-for="(document, docIndex) in documents"
|
|
389
|
+
:key="document._id"
|
|
390
|
+
@click="handleDocumentClick(document, $event)"
|
|
391
|
+
class="border-b border-edge cursor-pointer transition-colors hover:bg-muted/60"
|
|
392
|
+
:class="{ 'bg-primary-subtle/50 hover:bg-primary-subtle/70': selectedDocuments.some(x => x._id.toString() === document._id.toString()) }"
|
|
393
|
+
>
|
|
394
|
+
<td v-if="showRowNumbers" class="px-3 py-2 border-r border-edge align-top text-content-tertiary whitespace-nowrap">
|
|
395
|
+
{{ docIndex + 1 }}
|
|
396
|
+
</td>
|
|
397
|
+
<td
|
|
398
|
+
v-for="schemaPath in tableDisplayPaths"
|
|
399
|
+
:key="schemaPath.path"
|
|
400
|
+
class="px-3 py-2 border-r border-edge last:border-r-0 align-top max-w-[280px]"
|
|
401
|
+
>
|
|
402
|
+
<div class="table-cell-content flex items-center gap-1.5 min-w-0 group">
|
|
403
|
+
<span class="min-w-0 overflow-hidden text-ellipsis flex-1">
|
|
404
|
+
<component
|
|
405
|
+
:is="getComponentForPath(schemaPath)"
|
|
406
|
+
:value="getValueForPath(document, schemaPath.path)"
|
|
407
|
+
:allude="getReferenceModel(schemaPath)"
|
|
408
|
+
/>
|
|
409
|
+
</span>
|
|
410
|
+
<button
|
|
411
|
+
type="button"
|
|
412
|
+
class="table-cell-copy shrink-0 p-1 rounded text-content-tertiary hover:text-content hover:bg-muted focus:outline-none focus:ring-1 focus:ring-edge"
|
|
413
|
+
aria-label="Copy cell value"
|
|
414
|
+
@click.stop="copyCellValue(getValueForPath(document, schemaPath.path))"
|
|
415
|
+
>
|
|
416
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
|
|
417
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M8 5H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-1M8 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M8 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m0 0h2a2 2 0 0 1 2 2v3m2 4H10m0 0l3-3m-3 3l3 3" />
|
|
418
|
+
</svg>
|
|
419
|
+
</button>
|
|
420
|
+
</div>
|
|
421
|
+
</td>
|
|
422
|
+
<td v-if="filteredPaths.length > 0" class="w-0 px-0 py-0 border-r border-edge last:border-r-0 bg-slate-50/50 dark:bg-shark-800/30"></td>
|
|
423
|
+
</tr>
|
|
424
|
+
</tbody>
|
|
425
|
+
</table>
|
|
426
|
+
</div>
|
|
427
|
+
<div v-if="outputType === 'table' && (loadingMore || (status === 'loading' && documents.length > 0))" class="flex items-center justify-center gap-2 py-3 text-sm text-content-tertiary border-t border-edge bg-surface">
|
|
428
|
+
<img src="images/loader.gif" alt="" class="h-5 w-5">
|
|
429
|
+
<span>Loading documents…</span>
|
|
430
|
+
</div>
|
|
431
|
+
<p v-if="outputType === 'table' && documents.length === 0 && status === 'loaded'" class="mt-2 text-sm text-content-tertiary px-1">
|
|
432
|
+
No documents to show. Use Projection in the menu to choose columns.
|
|
433
|
+
</p>
|
|
434
|
+
</div>
|
|
262
435
|
<div v-else-if="outputType === 'json'" class="flex flex-col space-y-2 p-1 mt-1">
|
|
263
436
|
<div
|
|
264
437
|
v-for="document in documents"
|
|
@@ -279,6 +452,10 @@
|
|
|
279
452
|
<list-json :value="filterDocument(document)" :references="referenceMap">
|
|
280
453
|
</list-json>
|
|
281
454
|
</div>
|
|
455
|
+
<div v-if="outputType === 'json' && (loadingMore || (status === 'loading' && documents.length > 0))" class="flex items-center justify-center gap-2 py-3 text-sm text-content-tertiary">
|
|
456
|
+
<img src="images/loader.gif" alt="" class="h-5 w-5">
|
|
457
|
+
<span>Loading documents…</span>
|
|
458
|
+
</div>
|
|
282
459
|
</div>
|
|
283
460
|
<div v-else-if="outputType === 'map'" class="flex flex-col h-full">
|
|
284
461
|
<div class="p-2 bg-surface border-b flex items-center gap-2">
|
|
@@ -304,8 +481,8 @@
|
|
|
304
481
|
</div>
|
|
305
482
|
<div class="flex-1 min-h-[400px]" ref="modelsMap"></div>
|
|
306
483
|
</div>
|
|
307
|
-
<div v-if="status === 'loading'" class="loader">
|
|
308
|
-
<img src="images/loader.gif">
|
|
484
|
+
<div v-if="status === 'loading' && !loadingMore && documents.length === 0" class="loader loader-overlay" aria-busy="true">
|
|
485
|
+
<img src="images/loader.gif" alt="Loading">
|
|
309
486
|
</div>
|
|
310
487
|
</div>
|
|
311
488
|
</div>
|
|
@@ -385,23 +562,6 @@
|
|
|
385
562
|
</div>
|
|
386
563
|
</template>
|
|
387
564
|
</modal>
|
|
388
|
-
<modal v-if="shouldShowFieldModal">
|
|
389
|
-
<template v-slot:body>
|
|
390
|
-
<div class="modal-exit" @click="shouldShowFieldModal = false; selectedPaths = [...filteredPaths];">×</div>
|
|
391
|
-
<div v-for="(path, index) in schemaPaths" :key="index" class="w-5 flex items-center">
|
|
392
|
-
<input class="mt-0 h-4 w-4 rounded border-edge-strong text-sky-600 focus:ring-sky-600 accent-sky-600" type="checkbox" :id="'path.path'+index" @change="addOrRemove(path)" :value="path.path" :checked="isSelected(path.path)" />
|
|
393
|
-
<div class="ml-2 text-content-secondary grow shrink text-left">
|
|
394
|
-
<label :for="'path.path' + index">{{path.path}}</label>
|
|
395
|
-
</div>
|
|
396
|
-
</div>
|
|
397
|
-
<div class="mt-4 flex gap-2">
|
|
398
|
-
<button type="button" @click="filterDocuments()" class="rounded-md bg-primary px-2.5 py-1.5 text-sm font-semibold text-primary-text shadow-sm hover:bg-primary-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600">Filter Selection</button>
|
|
399
|
-
<button type="button" @click="selectAll()" class="rounded-md bg-forest-green-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600">Select All</button>
|
|
400
|
-
<button type="button" @click="deselectAll()" class="rounded-md bg-valencia-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-valencia-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600">Deselect All</button>
|
|
401
|
-
<button type="button" @click="resetDocuments()" class="rounded-md bg-gray-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-page0 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600" >Cancel</button>
|
|
402
|
-
</div>
|
|
403
|
-
</template>
|
|
404
|
-
</modal>
|
|
405
565
|
<modal v-if="shouldShowCreateModal">
|
|
406
566
|
<template v-slot:body>
|
|
407
567
|
<div class="modal-exit" @click="shouldShowCreateModal = false;">×</div>
|