@jskit-ai/users-web 0.1.178-oldline.2 → 0.1.178

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 (124) hide show
  1. package/package.json +197 -45
  2. package/patterns/account-settings/PATTERN.md +61 -0
  3. package/src/client/bootstrap/user-bootstrap-handler.js +2 -12
  4. package/src/client/composables/account-settings/accountSettingsAvatarUploadRuntime.js +2 -2
  5. package/src/client/composables/useAccountSettingsRuntime.js +3 -3
  6. package/src/client/index.js +0 -16
  7. package/src/client/providers/UsersWebClientProvider.js +13 -14
  8. package/test/bootstrap.test.js +6 -41
  9. package/test/exportsContract.test.js +3 -29
  10. package/test/packageMetadataOwnership.test.js +19 -0
  11. package/test/settingsPlacementContract.test.js +93 -405
  12. package/fixtures/crud-list-date-filters/App.vue +0 -107
  13. package/fixtures/crud-list-date-filters/index.html +0 -12
  14. package/fixtures/crud-list-date-filters/main.js +0 -24
  15. package/fixtures/crud-list-date-filters/vite.config.mjs +0 -18
  16. package/package.descriptor.mjs +0 -468
  17. package/src/client/bulkActions.js +0 -47
  18. package/src/client/components/CrudAddEditScreen.vue +0 -186
  19. package/src/client/components/CrudListBulkActionSurface.vue +0 -126
  20. package/src/client/components/CrudListDateFilterControl.vue +0 -188
  21. package/src/client/components/CrudListFilterSurface.vue +0 -388
  22. package/src/client/components/CrudListRecordActionMenu.vue +0 -120
  23. package/src/client/components/CrudListScreen.vue +0 -501
  24. package/src/client/components/CrudViewScreen.vue +0 -197
  25. package/src/client/composables/crud/crudBindingSupport.js +0 -75
  26. package/src/client/composables/crud/crudHttpClientSupport.js +0 -57
  27. package/src/client/composables/crud/crudJsonApiTransportSupport.js +0 -145
  28. package/src/client/composables/crud/crudLookupFieldLabelSupport.js +0 -151
  29. package/src/client/composables/crud/crudLookupFieldRuntime.js +0 -251
  30. package/src/client/composables/crud/crudSchemaFormHelpers.js +0 -464
  31. package/src/client/composables/internal/crudListFilterLookupSupport.js +0 -161
  32. package/src/client/composables/internal/crudListParentTitleSupport.js +0 -171
  33. package/src/client/composables/internal/useOperationScope.js +0 -144
  34. package/src/client/composables/records/useAddEdit.js +0 -224
  35. package/src/client/composables/records/useCrudAddEdit.js +0 -227
  36. package/src/client/composables/records/useCrudList.js +0 -101
  37. package/src/client/composables/records/useCrudView.js +0 -47
  38. package/src/client/composables/records/useList.js +0 -500
  39. package/src/client/composables/records/useView.js +0 -164
  40. package/src/client/composables/runtime/addEditUiRuntime.js +0 -130
  41. package/src/client/composables/runtime/listUiRuntime.js +0 -123
  42. package/src/client/composables/runtime/modelStateHelpers.js +0 -90
  43. package/src/client/composables/runtime/operationAdapters.js +0 -34
  44. package/src/client/composables/runtime/operationUiHelpers.js +0 -125
  45. package/src/client/composables/runtime/operationValidationHelpers.js +0 -51
  46. package/src/client/composables/runtime/useAddEditCore.js +0 -112
  47. package/src/client/composables/runtime/useCommandCore.js +0 -123
  48. package/src/client/composables/runtime/useEndpointResource.js +0 -199
  49. package/src/client/composables/runtime/useFieldErrorBag.js +0 -61
  50. package/src/client/composables/runtime/useListCore.js +0 -112
  51. package/src/client/composables/runtime/useUiFeedback.js +0 -98
  52. package/src/client/composables/runtime/useViewCore.js +0 -93
  53. package/src/client/composables/runtime/viewUiRuntime.js +0 -96
  54. package/src/client/composables/support/errorMessageHelpers.js +0 -66
  55. package/src/client/composables/support/listQueryParamSupport.js +0 -473
  56. package/src/client/composables/support/listSearchSupport.js +0 -70
  57. package/src/client/composables/support/refValueHelpers.js +0 -19
  58. package/src/client/composables/support/requestQueryRuntimeSupport.js +0 -141
  59. package/src/client/composables/support/resourceLoadStateHelpers.js +0 -229
  60. package/src/client/composables/support/routeTemplateHelpers.js +0 -285
  61. package/src/client/composables/support/scopeHelpers.js +0 -145
  62. package/src/client/composables/useAccess.js +0 -109
  63. package/src/client/composables/useCommand.js +0 -118
  64. package/src/client/composables/useCrudAddEditScreen.js +0 -88
  65. package/src/client/composables/useCrudDeleteAction.js +0 -160
  66. package/src/client/composables/useCrudListBulkActions.js +0 -147
  67. package/src/client/composables/useCrudListFilterLookups.js +0 -146
  68. package/src/client/composables/useCrudListFilters.js +0 -339
  69. package/src/client/composables/useCrudListParentTitle.js +0 -151
  70. package/src/client/composables/useCrudListRowActions.js +0 -144
  71. package/src/client/composables/useCrudListScreen.js +0 -237
  72. package/src/client/composables/useCrudViewScreen.js +0 -77
  73. package/src/client/composables/usePagedCollection.js +0 -181
  74. package/src/client/composables/usePaths.js +0 -120
  75. package/src/client/composables/useRealtimeQueryInvalidation.js +0 -156
  76. package/src/client/composables/useScopeRuntime.js +0 -135
  77. package/src/client/composables/useSurfaceRouteContext.js +0 -25
  78. package/src/client/filters.js +0 -15
  79. package/src/client/lib/httpClient.js +0 -47
  80. package/src/client/lib/permissions.js +0 -34
  81. package/src/client/rowActions.js +0 -47
  82. package/src/client/support/contractGuards.js +0 -34
  83. package/src/client/support/crudListDateFilterSupport.js +0 -91
  84. package/test/addEditUiRuntime.test.js +0 -110
  85. package/test/crudBindingSupport.test.js +0 -110
  86. package/test/crudHttpClientSupport.test.js +0 -77
  87. package/test/crudJsonApiTransportSupport.test.js +0 -179
  88. package/test/crudListBulkActionSurface.test.js +0 -27
  89. package/test/crudListDateFilterSupport.test.js +0 -92
  90. package/test/crudListDateFilterSurface.browser.test.js +0 -273
  91. package/test/crudListFilterSurface.test.js +0 -90
  92. package/test/crudLookupFieldRuntime.test.js +0 -264
  93. package/test/crudScreenComponents.test.js +0 -108
  94. package/test/errorIntentContract.test.js +0 -31
  95. package/test/errorMessageHelpers.test.js +0 -28
  96. package/test/listQueryParamSupport.test.js +0 -223
  97. package/test/listUiRuntime.test.js +0 -102
  98. package/test/operationValidationHelpers.test.js +0 -64
  99. package/test/packageDescriptorOwnership.test.js +0 -18
  100. package/test/permissions.test.js +0 -35
  101. package/test/refValueHelpers.test.js +0 -14
  102. package/test/requestTransportOptions.test.js +0 -457
  103. package/test/resourceLoadStateHelpers.test.js +0 -189
  104. package/test/routeTemplateHelpers.test.js +0 -85
  105. package/test/scopeHelpers.test.js +0 -57
  106. package/test/useAddEditCore.test.js +0 -124
  107. package/test/useAddEditRequestQueryParams.test.js +0 -190
  108. package/test/useCrudAddEdit.test.js +0 -435
  109. package/test/useCrudDeleteAction.test.js +0 -139
  110. package/test/useCrudListBulkActions.test.js +0 -65
  111. package/test/useCrudListFilterLookups.test.js +0 -114
  112. package/test/useCrudListFilters.test.js +0 -293
  113. package/test/useCrudListParentTitle.test.js +0 -262
  114. package/test/useCrudListRowActions.test.js +0 -77
  115. package/test/useListRouteInitialization.test.js +0 -337
  116. package/test/useListSearchSupport.test.js +0 -61
  117. package/test/usePagedCollection.test.js +0 -53
  118. package/test/useViewRequestQueryParams.test.js +0 -20
  119. package/test/viewCoreLoading.test.js +0 -44
  120. package/test/viewUiRuntime.test.js +0 -95
  121. /package/{templates → patterns/account-settings/example}/src/components/account/settings/AccountSettingsNotificationsSection.vue +0 -0
  122. /package/{templates → patterns/account-settings/example}/src/components/account/settings/AccountSettingsPreferencesSection.vue +0 -0
  123. /package/{templates → patterns/account-settings/example}/src/components/account/settings/AccountSettingsProfileSection.vue +0 -0
  124. /package/{templates → patterns/account-settings/example}/src/pages/account/index.vue +0 -0
@@ -1,388 +0,0 @@
1
- <script setup>
2
- import { computed, ref } from "vue";
3
- import { useDisplay } from "vuetify";
4
- import CrudListDateFilterControl from "./CrudListDateFilterControl.vue";
5
-
6
- const props = defineProps({
7
- filters: {
8
- type: Object,
9
- default: () => ({})
10
- },
11
- runtime: {
12
- type: Object,
13
- default: null
14
- },
15
- title: {
16
- type: String,
17
- default: "Filters"
18
- }
19
- });
20
-
21
- const display = useDisplay();
22
- const sheetOpen = ref(false);
23
-
24
- const filterEntries = computed(() =>
25
- Object.values(props.filters && typeof props.filters === "object" && !Array.isArray(props.filters)
26
- ? props.filters
27
- : {})
28
- .filter((filter) => filter?.key && filter?.type)
29
- );
30
- const runtimeValues = computed(() => props.runtime?.values || {});
31
- const activeChips = computed(() => Array.isArray(props.runtime?.activeChips?.value) ? props.runtime.activeChips.value : []);
32
- const hasActiveFilters = computed(() => Boolean(props.runtime?.hasActiveFilters?.value));
33
- const shouldRender = computed(() => filterEntries.value.length > 0 && Boolean(props.runtime?.values));
34
- const isCompactLayout = computed(() => {
35
- const displayName = String(display?.name?.value || "").trim().toLowerCase();
36
- return displayName === "xs" || displayName === "sm";
37
- });
38
-
39
- function optionItems(filter = {}) {
40
- return Array.isArray(filter.options) ? filter.options : [];
41
- }
42
-
43
- function placeholder(filter = {}, fallback = "") {
44
- return String(filter?.ui?.placeholder || fallback || "").trim();
45
- }
46
-
47
- function clearChip(chip = {}) {
48
- props.runtime?.clearChip?.(chip);
49
- }
50
-
51
- function clearFilters() {
52
- props.runtime?.clearFilters?.();
53
- }
54
- </script>
55
-
56
- <template>
57
- <section v-if="shouldRender" class="crud-list-filter-surface">
58
- <div class="crud-list-filter-surface__summary">
59
- <v-btn
60
- v-if="isCompactLayout"
61
- color="primary"
62
- variant="tonal"
63
- class="crud-list-filter-surface__open"
64
- @click="sheetOpen = true"
65
- >
66
- {{ title }}
67
- <v-chip v-if="activeChips.length > 0" class="ml-2" size="x-small" color="primary" variant="flat">
68
- {{ activeChips.length }}
69
- </v-chip>
70
- </v-btn>
71
-
72
- <div v-if="hasActiveFilters" class="crud-list-filter-surface__chips">
73
- <v-chip
74
- v-for="chip in activeChips"
75
- :key="chip.id"
76
- closable
77
- size="small"
78
- variant="tonal"
79
- @click:close="clearChip(chip)"
80
- >
81
- {{ chip.label }}
82
- </v-chip>
83
- <v-btn size="small" variant="text" @click="clearFilters">Clear all</v-btn>
84
- </div>
85
- </div>
86
-
87
- <v-sheet v-if="!isCompactLayout" rounded="lg" border class="crud-list-filter-surface__panel">
88
- <div class="crud-list-filter-surface__controls">
89
- <template v-for="filter in filterEntries" :key="filter.key">
90
- <v-switch
91
- v-if="filter.type === 'flag'"
92
- v-model="runtimeValues[filter.key]"
93
- :label="filter.label"
94
- color="primary"
95
- density="comfortable"
96
- hide-details
97
- class="crud-list-filter-surface__control"
98
- />
99
- <v-select
100
- v-else-if="filter.type === 'enum' || filter.type === 'enumMany' || filter.type === 'presence'"
101
- v-model="runtimeValues[filter.key]"
102
- :items="optionItems(filter)"
103
- :label="filter.label"
104
- :placeholder="placeholder(filter)"
105
- :multiple="filter.type === 'enumMany'"
106
- :chips="filter.type === 'enumMany'"
107
- :closable-chips="filter.type === 'enumMany'"
108
- clearable
109
- item-title="label"
110
- item-value="value"
111
- variant="outlined"
112
- density="comfortable"
113
- hide-details="auto"
114
- class="crud-list-filter-surface__control"
115
- />
116
- <v-combobox
117
- v-else-if="filter.type === 'recordIdMany'"
118
- v-model="runtimeValues[filter.key]"
119
- :label="filter.label"
120
- :placeholder="placeholder(filter, 'Enter ids')"
121
- multiple
122
- chips
123
- closable-chips
124
- clearable
125
- variant="outlined"
126
- density="comfortable"
127
- hide-details="auto"
128
- class="crud-list-filter-surface__control"
129
- />
130
- <v-text-field
131
- v-else-if="filter.type === 'recordId'"
132
- v-model="runtimeValues[filter.key]"
133
- :label="filter.label"
134
- :placeholder="placeholder(filter, 'Enter id')"
135
- clearable
136
- variant="outlined"
137
- density="comfortable"
138
- hide-details="auto"
139
- class="crud-list-filter-surface__control"
140
- />
141
- <div
142
- v-else-if="filter.type === 'dateRange'"
143
- class="crud-list-filter-surface__range crud-list-filter-surface__range--date"
144
- role="group"
145
- :aria-label="`${filter.label} date range`"
146
- :data-filter-key="filter.key"
147
- data-filter-type="date-range"
148
- >
149
- <CrudListDateFilterControl
150
- v-model="runtimeValues[filter.key].from"
151
- :label="`${filter.label} from`"
152
- :control-id="`${filter.key}-from`"
153
- :placeholder="placeholder(filter, 'Select start date')"
154
- />
155
- <CrudListDateFilterControl
156
- v-model="runtimeValues[filter.key].to"
157
- :label="`${filter.label} to`"
158
- :control-id="`${filter.key}-to`"
159
- :placeholder="placeholder(filter, 'Select end date')"
160
- />
161
- </div>
162
- <div v-else-if="filter.type === 'numberRange'" class="crud-list-filter-surface__range">
163
- <v-text-field
164
- v-model="runtimeValues[filter.key].min"
165
- :label="`${filter.label} min`"
166
- type="number"
167
- variant="outlined"
168
- density="comfortable"
169
- hide-details="auto"
170
- />
171
- <v-text-field
172
- v-model="runtimeValues[filter.key].max"
173
- :label="`${filter.label} max`"
174
- type="number"
175
- variant="outlined"
176
- density="comfortable"
177
- hide-details="auto"
178
- />
179
- </div>
180
- <CrudListDateFilterControl
181
- v-else-if="filter.type === 'date'"
182
- v-model="runtimeValues[filter.key]"
183
- :label="filter.label"
184
- :control-id="filter.key"
185
- :placeholder="placeholder(filter, 'Select date')"
186
- class="crud-list-filter-surface__control"
187
- />
188
- </template>
189
- </div>
190
- </v-sheet>
191
-
192
- <v-dialog v-model="sheetOpen" max-width="640" location="bottom">
193
- <v-card rounded="lg" class="crud-list-filter-surface__sheet">
194
- <v-card-title class="d-flex align-center justify-space-between">
195
- <span>{{ title }}</span>
196
- <v-btn variant="text" @click="sheetOpen = false">Close</v-btn>
197
- </v-card-title>
198
- <v-card-text>
199
- <div class="crud-list-filter-surface__controls crud-list-filter-surface__controls--stacked">
200
- <template v-for="filter in filterEntries" :key="filter.key">
201
- <v-switch
202
- v-if="filter.type === 'flag'"
203
- v-model="runtimeValues[filter.key]"
204
- :label="filter.label"
205
- color="primary"
206
- density="comfortable"
207
- hide-details
208
- />
209
- <v-select
210
- v-else-if="filter.type === 'enum' || filter.type === 'enumMany' || filter.type === 'presence'"
211
- v-model="runtimeValues[filter.key]"
212
- :items="optionItems(filter)"
213
- :label="filter.label"
214
- :placeholder="placeholder(filter)"
215
- :multiple="filter.type === 'enumMany'"
216
- :chips="filter.type === 'enumMany'"
217
- :closable-chips="filter.type === 'enumMany'"
218
- clearable
219
- item-title="label"
220
- item-value="value"
221
- variant="outlined"
222
- density="comfortable"
223
- hide-details="auto"
224
- />
225
- <v-combobox
226
- v-else-if="filter.type === 'recordIdMany'"
227
- v-model="runtimeValues[filter.key]"
228
- :label="filter.label"
229
- :placeholder="placeholder(filter, 'Enter ids')"
230
- multiple
231
- chips
232
- closable-chips
233
- clearable
234
- variant="outlined"
235
- density="comfortable"
236
- hide-details="auto"
237
- />
238
- <v-text-field
239
- v-else-if="filter.type === 'recordId'"
240
- v-model="runtimeValues[filter.key]"
241
- :label="filter.label"
242
- :placeholder="placeholder(filter, 'Enter id')"
243
- clearable
244
- variant="outlined"
245
- density="comfortable"
246
- hide-details="auto"
247
- />
248
- <div
249
- v-else-if="filter.type === 'dateRange'"
250
- class="crud-list-filter-surface__range crud-list-filter-surface__range--date"
251
- role="group"
252
- :aria-label="`${filter.label} date range`"
253
- :data-filter-key="filter.key"
254
- data-filter-type="date-range"
255
- >
256
- <CrudListDateFilterControl
257
- v-model="runtimeValues[filter.key].from"
258
- :label="`${filter.label} from`"
259
- :control-id="`${filter.key}-from`"
260
- :placeholder="placeholder(filter, 'Select start date')"
261
- />
262
- <CrudListDateFilterControl
263
- v-model="runtimeValues[filter.key].to"
264
- :label="`${filter.label} to`"
265
- :control-id="`${filter.key}-to`"
266
- :placeholder="placeholder(filter, 'Select end date')"
267
- />
268
- </div>
269
- <div v-else-if="filter.type === 'numberRange'" class="crud-list-filter-surface__range">
270
- <v-text-field
271
- v-model="runtimeValues[filter.key].min"
272
- :label="`${filter.label} min`"
273
- type="number"
274
- variant="outlined"
275
- density="comfortable"
276
- hide-details="auto"
277
- />
278
- <v-text-field
279
- v-model="runtimeValues[filter.key].max"
280
- :label="`${filter.label} max`"
281
- type="number"
282
- variant="outlined"
283
- density="comfortable"
284
- hide-details="auto"
285
- />
286
- </div>
287
- <CrudListDateFilterControl
288
- v-else-if="filter.type === 'date'"
289
- v-model="runtimeValues[filter.key]"
290
- :label="filter.label"
291
- :control-id="filter.key"
292
- :placeholder="placeholder(filter, 'Select date')"
293
- />
294
- </template>
295
- </div>
296
- </v-card-text>
297
- <v-card-actions class="justify-space-between">
298
- <v-btn variant="text" @click="clearFilters">Clear all</v-btn>
299
- <v-btn color="primary" variant="flat" @click="sheetOpen = false">Apply</v-btn>
300
- </v-card-actions>
301
- </v-card>
302
- </v-dialog>
303
- </section>
304
- </template>
305
-
306
- <style scoped>
307
- .crud-list-filter-surface {
308
- display: flex;
309
- flex-direction: column;
310
- gap: 0.75rem;
311
- min-width: 0;
312
- }
313
-
314
- .crud-list-filter-surface__summary {
315
- align-items: center;
316
- display: flex;
317
- flex-wrap: wrap;
318
- gap: 0.75rem;
319
- justify-content: space-between;
320
- }
321
-
322
- .crud-list-filter-surface__open {
323
- min-height: 48px;
324
- }
325
-
326
- .crud-list-filter-surface__chips {
327
- align-items: center;
328
- display: flex;
329
- flex-wrap: wrap;
330
- gap: 0.5rem;
331
- min-width: 0;
332
- }
333
-
334
- .crud-list-filter-surface__panel {
335
- padding: 1rem;
336
- }
337
-
338
- .crud-list-filter-surface__controls {
339
- display: grid;
340
- gap: 0.75rem;
341
- grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
342
- }
343
-
344
- .crud-list-filter-surface__controls--stacked {
345
- grid-template-columns: 1fr;
346
- }
347
-
348
- .crud-list-filter-surface__control {
349
- min-width: 0;
350
- }
351
-
352
- .crud-list-filter-surface__range {
353
- display: grid;
354
- gap: 0.75rem;
355
- grid-template-columns: repeat(2, minmax(0, 1fr));
356
- min-width: 0;
357
- }
358
-
359
- .crud-list-filter-surface__range--date {
360
- grid-column: span 2;
361
- grid-template-columns: repeat(2, minmax(14rem, 1fr));
362
- }
363
-
364
- .crud-list-filter-surface__controls--stacked .crud-list-filter-surface__range--date {
365
- grid-column: auto;
366
- }
367
-
368
- .crud-list-filter-surface__sheet {
369
- margin: 0.75rem;
370
- }
371
-
372
- .crud-list-filter-surface :deep(.v-field),
373
- .crud-list-filter-surface :deep(.v-btn),
374
- .crud-list-filter-surface :deep(.v-selection-control) {
375
- min-height: 48px;
376
- }
377
-
378
- @media (max-width: 640px) {
379
- .crud-list-filter-surface__summary {
380
- align-items: stretch;
381
- flex-direction: column;
382
- }
383
-
384
- .crud-list-filter-surface__range {
385
- grid-template-columns: 1fr;
386
- }
387
- }
388
- </style>
@@ -1,120 +0,0 @@
1
- <script setup>
2
- import { computed } from "vue";
3
-
4
- const props = defineProps({
5
- record: {
6
- type: Object,
7
- default: () => ({})
8
- },
9
- index: {
10
- type: Number,
11
- default: 0
12
- },
13
- rowActions: {
14
- type: Object,
15
- default: null
16
- },
17
- viewLocation: {
18
- type: Object,
19
- default: null
20
- },
21
- editLocation: {
22
- type: Object,
23
- default: null
24
- },
25
- showView: {
26
- type: Boolean,
27
- default: false
28
- },
29
- showEdit: {
30
- type: Boolean,
31
- default: false
32
- },
33
- buttonLabel: {
34
- type: String,
35
- default: "Actions"
36
- },
37
- buttonVariant: {
38
- type: String,
39
- default: "text"
40
- },
41
- buttonSize: {
42
- type: String,
43
- default: "small"
44
- }
45
- });
46
-
47
- const visibleRowActions = computed(() => {
48
- if (typeof props.rowActions?.visibleActionsFor !== "function") {
49
- return [];
50
- }
51
- return props.rowActions.visibleActionsFor(props.record, props.index);
52
- });
53
- const hasViewAction = computed(() => Boolean(props.showView && props.viewLocation));
54
- const hasEditAction = computed(() => Boolean(props.showEdit && props.editLocation));
55
- const hasActions = computed(() =>
56
- hasViewAction.value || hasEditAction.value || visibleRowActions.value.length > 0
57
- );
58
-
59
- function isRowActionLoading(action = {}) {
60
- return typeof props.rowActions?.isActionLoading === "function" &&
61
- props.rowActions.isActionLoading(action, props.record, props.index);
62
- }
63
-
64
- function isRowActionDisabled(action = {}) {
65
- return typeof props.rowActions?.isActionDisabled !== "function" ||
66
- props.rowActions.isActionDisabled(action, props.record, props.index);
67
- }
68
-
69
- function runRowAction(action = {}) {
70
- if (typeof props.rowActions?.execute !== "function") {
71
- return;
72
- }
73
- void props.rowActions.execute(action, props.record, props.index);
74
- }
75
- </script>
76
-
77
- <template>
78
- <v-menu v-if="hasActions" location="bottom end">
79
- <template #activator="{ props: menuProps }">
80
- <v-btn
81
- v-bind="menuProps"
82
- :variant="buttonVariant"
83
- :size="buttonSize"
84
- >
85
- {{ buttonLabel }}
86
- </v-btn>
87
- </template>
88
- <v-list density="compact" min-width="150">
89
- <v-list-item
90
- v-if="hasViewAction"
91
- title="Open"
92
- :to="viewLocation"
93
- />
94
- <v-list-item
95
- v-if="hasEditAction"
96
- title="Edit"
97
- :to="editLocation"
98
- />
99
- <v-divider v-if="(hasViewAction || hasEditAction) && visibleRowActions.length > 0" />
100
- <v-list-item
101
- v-for="action in visibleRowActions"
102
- :key="action.key"
103
- :title="action.label"
104
- :base-color="action.color"
105
- :disabled="isRowActionDisabled(action)"
106
- @click="runRowAction(action)"
107
- >
108
- <template v-if="isRowActionLoading(action) || action.icon" #prepend>
109
- <v-progress-circular
110
- v-if="isRowActionLoading(action)"
111
- indeterminate
112
- size="18"
113
- width="2"
114
- />
115
- <v-icon v-else :icon="action.icon" />
116
- </template>
117
- </v-list-item>
118
- </v-list>
119
- </v-menu>
120
- </template>