@plutocms/supabase 0.30.0 → 0.31.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.
- package/CHANGELOG.md +14 -0
- package/app/components/EnvPersistWarning.vue +11 -9
- package/app/components/SupabaseLogo.vue +47 -0
- package/app/components/backend/SupabaseBackendDetails.vue +1 -1
- package/app/components/mail/AuthEmailsPanel.vue +3 -2
- package/app/pages/admin/migrations.vue +24 -22
- package/app/pages/admin/roles.vue +117 -119
- package/app/pages/admin/setup.vue +160 -271
- package/app/pages/admin/users.vue +191 -189
- package/app/utils/auth-error.ts +1 -1
- package/i18n/locales/en.json +17 -19
- package/i18n/locales/pt-BR.json +17 -19
- package/modules/internal/supabase-types-shim.ts +27 -0
- package/modules/pluto-migrations.ts +17 -10
- package/package.json +2 -2
- package/app/layouts/setup.vue +0 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.31.1](https://github.com/plutocms/supabase/compare/v0.31.0...v0.31.1) (2026-11-14)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **supabase, supabase-blog:** type the translate helpers with the t of core ([#318](https://github.com/plutocms/supabase/issues/318)) ([ccdecaf](https://github.com/plutocms/supabase/commit/ccdecafea563fe43e29874b8ffb101d4cf8b8a75))
|
|
9
|
+
|
|
10
|
+
## [0.31.0](https://github.com/plutocms/supabase/compare/v0.30.0...v0.31.0) (2026-11-12)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* admin UI round 5: tooltips, a playground site, new tab links; core 0.68 ([#302](https://github.com/plutocms/supabase/issues/302)) ([441d322](https://github.com/plutocms/supabase/commit/441d322a52cf31712cd7510b0876ca885698fda7))
|
|
16
|
+
|
|
3
17
|
## [0.30.0](https://github.com/plutocms/supabase/compare/v0.29.0...v0.30.0) (2026-11-10)
|
|
4
18
|
|
|
5
19
|
|
|
@@ -43,7 +43,7 @@ async function copyEnvLine() {
|
|
|
43
43
|
<UAlert
|
|
44
44
|
:title="t('supabase.envWarning.title')"
|
|
45
45
|
color="warning"
|
|
46
|
-
variant="
|
|
46
|
+
variant="subtle"
|
|
47
47
|
icon="lucide:triangle-alert"
|
|
48
48
|
>
|
|
49
49
|
<template #description>
|
|
@@ -84,14 +84,16 @@ async function copyEnvLine() {
|
|
|
84
84
|
{{ envLine }}
|
|
85
85
|
</code>
|
|
86
86
|
|
|
87
|
-
<
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
87
|
+
<UTooltip :text="t('supabase.envWarning.copyLine')">
|
|
88
|
+
<UButton
|
|
89
|
+
:aria-label="t('supabase.envWarning.copyLine')"
|
|
90
|
+
icon="lucide:copy"
|
|
91
|
+
variant="soft"
|
|
92
|
+
color="neutral"
|
|
93
|
+
size="sm"
|
|
94
|
+
@click="copyEnvLine"
|
|
95
|
+
/>
|
|
96
|
+
</UTooltip>
|
|
95
97
|
</div>
|
|
96
98
|
</div>
|
|
97
99
|
</template>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// The mark of Supabase, in its brand colors, for a page that connects Pluto to it (the database
|
|
3
|
+
// setup). Size it with a class, such as `size-6`.
|
|
4
|
+
const id = useId()
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<svg viewBox="0 0 109 113" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
9
|
+
<path
|
|
10
|
+
:fill="`url(#${id}-a)`"
|
|
11
|
+
d="M63.7076 110.284C60.8481 113.885 55.0502 111.912 54.9813 107.314L53.9738 40.0627L99.1935 40.0627C107.384 40.0627 111.952 49.5228 106.859 55.9374L63.7076 110.284Z"
|
|
12
|
+
/>
|
|
13
|
+
<path
|
|
14
|
+
:fill="`url(#${id}-b)`"
|
|
15
|
+
d="M63.7076 110.284C60.8481 113.885 55.0502 111.912 54.9813 107.314L53.9738 40.0627L99.1935 40.0627C107.384 40.0627 111.952 49.5228 106.859 55.9374L63.7076 110.284Z"
|
|
16
|
+
fill-opacity="0.2"
|
|
17
|
+
/>
|
|
18
|
+
<path
|
|
19
|
+
d="M45.317 2.07103C48.1765 -1.53037 53.9745 0.442937 54.0434 5.041L54.4849 72.2922H9.83113C1.64038 72.2922 -2.92775 62.8321 2.1655 56.4175L45.317 2.07103Z"
|
|
20
|
+
fill="#3ECF8E"
|
|
21
|
+
/>
|
|
22
|
+
<defs>
|
|
23
|
+
<linearGradient
|
|
24
|
+
:id="`${id}-a`"
|
|
25
|
+
x1="53.9738"
|
|
26
|
+
y1="54.974"
|
|
27
|
+
x2="94.1635"
|
|
28
|
+
y2="71.8295"
|
|
29
|
+
gradientUnits="userSpaceOnUse"
|
|
30
|
+
>
|
|
31
|
+
<stop stop-color="#249361" />
|
|
32
|
+
<stop offset="1" stop-color="#3ECF8E" />
|
|
33
|
+
</linearGradient>
|
|
34
|
+
<linearGradient
|
|
35
|
+
:id="`${id}-b`"
|
|
36
|
+
x1="36.1558"
|
|
37
|
+
y1="30.578"
|
|
38
|
+
x2="54.4844"
|
|
39
|
+
y2="65.0806"
|
|
40
|
+
gradientUnits="userSpaceOnUse"
|
|
41
|
+
>
|
|
42
|
+
<stop />
|
|
43
|
+
<stop offset="1" stop-opacity="0" />
|
|
44
|
+
</linearGradient>
|
|
45
|
+
</defs>
|
|
46
|
+
</svg>
|
|
47
|
+
</template>
|
|
@@ -72,7 +72,7 @@ const dashboardLinks = computed(() =>
|
|
|
72
72
|
key: 'project',
|
|
73
73
|
label: t('supabase.mail.authEmails.dashboardHome'),
|
|
74
74
|
to: links.value.project,
|
|
75
|
-
icon: 'lucide:
|
|
75
|
+
icon: 'lucide:layout-dashboard',
|
|
76
76
|
},
|
|
77
77
|
]
|
|
78
78
|
: []
|
|
@@ -95,7 +95,7 @@ const dashboardLinks = computed(() =>
|
|
|
95
95
|
:to="RESEND_SUPABASE_INTEGRATION_URL"
|
|
96
96
|
target="_blank"
|
|
97
97
|
rel="noopener noreferrer"
|
|
98
|
-
icon="lucide
|
|
98
|
+
trailing-icon="i-lucide-arrow-up-right"
|
|
99
99
|
color="neutral"
|
|
100
100
|
variant="outline"
|
|
101
101
|
>
|
|
@@ -149,6 +149,7 @@ const dashboardLinks = computed(() =>
|
|
|
149
149
|
:icon="link.icon"
|
|
150
150
|
target="_blank"
|
|
151
151
|
rel="noopener noreferrer"
|
|
152
|
+
trailing-icon="i-lucide-arrow-up-right"
|
|
152
153
|
color="neutral"
|
|
153
154
|
variant="outline"
|
|
154
155
|
size="sm"
|
|
@@ -18,14 +18,14 @@ const { status, fetchStatus, pendingCount, refresh, runMigrations } =
|
|
|
18
18
|
const isDev = import.meta.dev
|
|
19
19
|
|
|
20
20
|
// The text of each result status that the server returns.
|
|
21
|
-
const statusLabels
|
|
21
|
+
const statusLabels = {
|
|
22
22
|
applied: 'supabase.migrations.status.applied',
|
|
23
23
|
skipped: 'supabase.migrations.status.skipped',
|
|
24
24
|
failed: 'supabase.migrations.status.failed',
|
|
25
|
-
}
|
|
25
|
+
} as const
|
|
26
26
|
|
|
27
27
|
function statusText(status: string): string {
|
|
28
|
-
const key = statusLabels[status]
|
|
28
|
+
const key = statusLabels[status as keyof typeof statusLabels]
|
|
29
29
|
|
|
30
30
|
return key ? t(key) : status
|
|
31
31
|
}
|
|
@@ -188,17 +188,20 @@ async function applyMigrations(useForm: boolean) {
|
|
|
188
188
|
</script>
|
|
189
189
|
|
|
190
190
|
<template>
|
|
191
|
-
<
|
|
192
|
-
<
|
|
193
|
-
|
|
194
|
-
|
|
191
|
+
<PlutoViewAdminPanel>
|
|
192
|
+
<template #toolbar>
|
|
193
|
+
<PlutoViewToolbar
|
|
194
|
+
:title="t('supabase.migrations.title')"
|
|
195
|
+
icon="lucide:database-zap"
|
|
196
|
+
/>
|
|
197
|
+
</template>
|
|
195
198
|
|
|
196
199
|
<UAlert
|
|
197
200
|
v-if="isReconnecting"
|
|
198
201
|
:title="t('supabase.connection.restarting')"
|
|
199
202
|
:description="t('supabase.migrations.reconnectingBanner')"
|
|
200
203
|
color="info"
|
|
201
|
-
variant="
|
|
204
|
+
variant="subtle"
|
|
202
205
|
icon="lucide:refresh-cw"
|
|
203
206
|
/>
|
|
204
207
|
|
|
@@ -218,7 +221,7 @@ async function applyMigrations(useForm: boolean) {
|
|
|
218
221
|
:title="t('supabase.migrations.upToDate')"
|
|
219
222
|
:description="t('supabase.migrations.upToDateDescription')"
|
|
220
223
|
color="success"
|
|
221
|
-
variant="
|
|
224
|
+
variant="subtle"
|
|
222
225
|
icon="lucide:check-circle"
|
|
223
226
|
/>
|
|
224
227
|
|
|
@@ -284,14 +287,12 @@ async function applyMigrations(useForm: boolean) {
|
|
|
284
287
|
:message="t('supabase.connection.connectionStringHelp')"
|
|
285
288
|
>
|
|
286
289
|
<template #link>
|
|
287
|
-
<
|
|
290
|
+
<PlutoExternalLink
|
|
288
291
|
:to="`https://supabase.com/dashboard/project/${projectId}/database/settings?showConnect=true&connectTab=direct&method=transaction`"
|
|
289
|
-
target="_blank"
|
|
290
292
|
class="underline"
|
|
291
|
-
external
|
|
292
293
|
>
|
|
293
294
|
{{ t('supabase.connection.connectionStringHelpLink') }}
|
|
294
|
-
</
|
|
295
|
+
</PlutoExternalLink>
|
|
295
296
|
</template>
|
|
296
297
|
</SupabaseMessageParts>
|
|
297
298
|
</template>
|
|
@@ -310,19 +311,18 @@ async function applyMigrations(useForm: boolean) {
|
|
|
310
311
|
<UAlert
|
|
311
312
|
color="secondary"
|
|
312
313
|
icon="lucide:badge-info"
|
|
313
|
-
variant="
|
|
314
|
+
variant="subtle"
|
|
314
315
|
>
|
|
315
316
|
<template #description>
|
|
316
317
|
<SupabaseMessageParts
|
|
317
318
|
:message="t('supabase.connection.passwordInfo')"
|
|
318
319
|
>
|
|
319
320
|
<template #link>
|
|
320
|
-
<
|
|
321
|
+
<PlutoExternalLink
|
|
321
322
|
to="https://supabase.com/dashboard/project/_/database/settings"
|
|
322
|
-
target="_blank"
|
|
323
323
|
>
|
|
324
324
|
{{ t('supabase.connection.passwordInfoLink') }}
|
|
325
|
-
</
|
|
325
|
+
</PlutoExternalLink>
|
|
326
326
|
</template>
|
|
327
327
|
</SupabaseMessageParts>
|
|
328
328
|
</template>
|
|
@@ -332,7 +332,7 @@ async function applyMigrations(useForm: boolean) {
|
|
|
332
332
|
:title="t('supabase.connection.whyTitle')"
|
|
333
333
|
:description="t('supabase.migrations.why')"
|
|
334
334
|
color="warning"
|
|
335
|
-
variant="
|
|
335
|
+
variant="subtle"
|
|
336
336
|
icon="lucide:info"
|
|
337
337
|
/>
|
|
338
338
|
|
|
@@ -341,7 +341,7 @@ async function applyMigrations(useForm: boolean) {
|
|
|
341
341
|
:title="t('supabase.connection.restartTitle')"
|
|
342
342
|
:description="t('supabase.migrations.restartDescription')"
|
|
343
343
|
color="info"
|
|
344
|
-
variant="
|
|
344
|
+
variant="subtle"
|
|
345
345
|
icon="lucide:refresh-cw"
|
|
346
346
|
/>
|
|
347
347
|
|
|
@@ -374,11 +374,13 @@ async function applyMigrations(useForm: boolean) {
|
|
|
374
374
|
</UCard>
|
|
375
375
|
|
|
376
376
|
<UCard v-if="lastRun">
|
|
377
|
-
<
|
|
377
|
+
<template #header>
|
|
378
378
|
<h2 class="font-semibold">
|
|
379
379
|
{{ t('supabase.migrations.lastRun') }}
|
|
380
380
|
</h2>
|
|
381
|
+
</template>
|
|
381
382
|
|
|
383
|
+
<div class="flex flex-col gap-y-4">
|
|
382
384
|
<EnvPersistWarning
|
|
383
385
|
v-if="lastRun.success && lastRun.persisted === false"
|
|
384
386
|
:connection-string="lastConnectionString"
|
|
@@ -410,7 +412,7 @@ async function applyMigrations(useForm: boolean) {
|
|
|
410
412
|
:title="t('supabase.migrations.loadFailed')"
|
|
411
413
|
:description="t('supabase.migrations.loadFailedDescription')"
|
|
412
414
|
color="error"
|
|
413
|
-
variant="
|
|
415
|
+
variant="subtle"
|
|
414
416
|
icon="lucide:circle-x"
|
|
415
417
|
>
|
|
416
418
|
<template #actions>
|
|
@@ -424,5 +426,5 @@ async function applyMigrations(useForm: boolean) {
|
|
|
424
426
|
</UButton>
|
|
425
427
|
</template>
|
|
426
428
|
</UAlert>
|
|
427
|
-
</
|
|
429
|
+
</PlutoViewAdminPanel>
|
|
428
430
|
</template>
|
|
@@ -124,140 +124,138 @@ function menuItems(role: AccessRole): DropdownMenuItem[][] {
|
|
|
124
124
|
</script>
|
|
125
125
|
|
|
126
126
|
<template>
|
|
127
|
-
<
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
<
|
|
131
|
-
|
|
132
|
-
|
|
127
|
+
<PlutoViewAdminPanel>
|
|
128
|
+
<!-- The section (the Users item of the menu) and its tabs, like Settings. -->
|
|
129
|
+
<template #toolbar>
|
|
130
|
+
<PlutoViewToolbar
|
|
131
|
+
:title="t('supabase.access.users.title')"
|
|
132
|
+
icon="lucide:users"
|
|
133
|
+
>
|
|
134
|
+
<template #right>
|
|
135
|
+
<UButton icon="lucide:plus" @click="openRole(null)">
|
|
136
|
+
{{ t('supabase.access.roles.create') }}
|
|
137
|
+
</UButton>
|
|
138
|
+
</template>
|
|
139
|
+
</PlutoViewToolbar>
|
|
133
140
|
|
|
134
141
|
<PlutoAdminNavTabs />
|
|
142
|
+
</template>
|
|
135
143
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
{{ t('supabase.access.roles.title') }}
|
|
140
|
-
</h2>
|
|
141
|
-
<p class="text-muted text-sm">
|
|
142
|
-
{{ t('supabase.access.roles.description') }}
|
|
143
|
-
</p>
|
|
144
|
-
</div>
|
|
144
|
+
<p class="text-muted text-sm">
|
|
145
|
+
{{ t('supabase.access.roles.description') }}
|
|
146
|
+
</p>
|
|
145
147
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
<UAlert
|
|
149
|
+
v-if="!allowed"
|
|
150
|
+
:title="t('pluto.settings.noPermission.title')"
|
|
151
|
+
:description="
|
|
152
|
+
t('pluto.settings.noPermission.description', {
|
|
153
|
+
page: t('supabase.access.roles.title'),
|
|
154
|
+
})
|
|
155
|
+
"
|
|
156
|
+
icon="lucide:lock"
|
|
157
|
+
color="warning"
|
|
158
|
+
/>
|
|
150
159
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
icon="lucide:lock"
|
|
160
|
-
color="warning"
|
|
161
|
-
/>
|
|
162
|
-
|
|
163
|
-
<!-- Loading -->
|
|
164
|
-
<div
|
|
165
|
-
v-else-if="status === 'loading'"
|
|
166
|
-
class="flex flex-col gap-y-3"
|
|
167
|
-
aria-busy="true"
|
|
168
|
-
>
|
|
169
|
-
<USkeleton v-for="row in 3" :key="row" class="h-12 w-full" />
|
|
170
|
-
</div>
|
|
160
|
+
<!-- Loading -->
|
|
161
|
+
<div
|
|
162
|
+
v-else-if="status === 'loading'"
|
|
163
|
+
class="flex flex-col gap-y-3"
|
|
164
|
+
aria-busy="true"
|
|
165
|
+
>
|
|
166
|
+
<USkeleton v-for="row in 3" :key="row" class="h-12 w-full" />
|
|
167
|
+
</div>
|
|
171
168
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
169
|
+
<!-- Error -->
|
|
170
|
+
<UAlert
|
|
171
|
+
v-else-if="status === 'error'"
|
|
172
|
+
:title="t('supabase.access.roles.error.title')"
|
|
173
|
+
:description="loadError"
|
|
174
|
+
:actions="[
|
|
175
|
+
{
|
|
176
|
+
label: t('pluto.common.tryAgain'),
|
|
177
|
+
color: 'neutral',
|
|
178
|
+
variant: 'outline',
|
|
179
|
+
onClick: load,
|
|
180
|
+
},
|
|
181
|
+
]"
|
|
182
|
+
color="error"
|
|
183
|
+
variant="subtle"
|
|
184
|
+
icon="lucide:circle-x"
|
|
185
|
+
/>
|
|
189
186
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
</span>
|
|
211
|
-
<code class="text-muted truncate font-mono text-xs">{{
|
|
212
|
-
row.original.key
|
|
213
|
-
}}</code>
|
|
214
|
-
</div>
|
|
215
|
-
</template>
|
|
216
|
-
|
|
217
|
-
<template #permissions-cell="{ row }">
|
|
218
|
-
<span v-if="isFullAccess(row.original)" class="text-sm">
|
|
219
|
-
{{ t('supabase.access.roles.fullAccess') }}
|
|
220
|
-
</span>
|
|
221
|
-
<span v-else class="text-sm">
|
|
222
|
-
{{
|
|
223
|
-
t(
|
|
224
|
-
'supabase.access.roles.permissionCount',
|
|
225
|
-
row.original.capabilities.length
|
|
226
|
-
)
|
|
227
|
-
}}
|
|
187
|
+
<!-- The list -->
|
|
188
|
+
<UTable
|
|
189
|
+
v-else
|
|
190
|
+
:data="roles"
|
|
191
|
+
:columns="columns"
|
|
192
|
+
class="border-default rounded-lg border"
|
|
193
|
+
>
|
|
194
|
+
<template #role-cell="{ row }">
|
|
195
|
+
<div class="flex min-w-0 flex-col">
|
|
196
|
+
<span class="flex items-center gap-2">
|
|
197
|
+
<span class="text-highlighted truncate font-medium">{{
|
|
198
|
+
row.original.label
|
|
199
|
+
}}</span>
|
|
200
|
+
<UBadge
|
|
201
|
+
v-if="row.original.is_builtin"
|
|
202
|
+
:label="t('supabase.access.roles.builtin')"
|
|
203
|
+
color="neutral"
|
|
204
|
+
variant="subtle"
|
|
205
|
+
size="sm"
|
|
206
|
+
/>
|
|
228
207
|
</span>
|
|
229
|
-
|
|
208
|
+
<code class="text-muted truncate font-mono text-xs">{{
|
|
209
|
+
row.original.key
|
|
210
|
+
}}</code>
|
|
211
|
+
</div>
|
|
212
|
+
</template>
|
|
230
213
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
214
|
+
<template #permissions-cell="{ row }">
|
|
215
|
+
<span v-if="isFullAccess(row.original)" class="text-sm">
|
|
216
|
+
{{ t('supabase.access.roles.fullAccess') }}
|
|
217
|
+
</span>
|
|
218
|
+
<span v-else class="text-sm">
|
|
219
|
+
{{
|
|
220
|
+
t(
|
|
221
|
+
'supabase.access.roles.permissionCount',
|
|
222
|
+
row.original.capabilities.length
|
|
223
|
+
)
|
|
224
|
+
}}
|
|
225
|
+
</span>
|
|
226
|
+
</template>
|
|
227
|
+
|
|
228
|
+
<template #users-cell="{ row }">
|
|
229
|
+
<span class="text-sm">{{
|
|
230
|
+
t('supabase.access.roles.userCount', row.original.user_count)
|
|
231
|
+
}}</span>
|
|
232
|
+
</template>
|
|
236
233
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
234
|
+
<template #actions-cell="{ row }">
|
|
235
|
+
<div class="flex justify-end">
|
|
236
|
+
<UDropdownMenu
|
|
237
|
+
:items="menuItems(row.original)"
|
|
238
|
+
:content="{ align: 'end' }"
|
|
239
|
+
>
|
|
240
|
+
<UTooltip :text="row.original.label">
|
|
243
241
|
<UButton
|
|
244
242
|
:aria-label="row.original.label"
|
|
245
243
|
icon="lucide:ellipsis"
|
|
246
244
|
color="neutral"
|
|
247
245
|
variant="ghost"
|
|
248
246
|
/>
|
|
249
|
-
</
|
|
250
|
-
</
|
|
251
|
-
</
|
|
252
|
-
</
|
|
247
|
+
</UTooltip>
|
|
248
|
+
</UDropdownMenu>
|
|
249
|
+
</div>
|
|
250
|
+
</template>
|
|
251
|
+
</UTable>
|
|
253
252
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
</main>
|
|
253
|
+
<!-- Lazy: the chunk loads on the first open. -->
|
|
254
|
+
<RoleSlideover
|
|
255
|
+
v-if="slideoverMounted"
|
|
256
|
+
v-model:open="slideoverOpen"
|
|
257
|
+
:role="editing"
|
|
258
|
+
@saved="load"
|
|
259
|
+
/>
|
|
260
|
+
</PlutoViewAdminPanel>
|
|
263
261
|
</template>
|