@motor-cms/ui-admin 1.1.0-alpha.4 → 1.1.0-alpha.5
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/app/assets/css/v-onboarding.css +64 -0
- package/app/components/OnboardingStep.vue +42 -0
- package/app/components/UsersOnboarding.vue +84 -0
- package/app/components/client/FooterSlotCard.vue +313 -0
- package/app/components/client/GlobalComponentsSection.vue +65 -0
- package/app/components/dashboard/DashboardActivity.vue +71 -0
- package/app/components/dashboard/DashboardActivityItem.vue +96 -0
- package/app/components/dashboard/DashboardAnnouncementModal.vue +327 -0
- package/app/components/dashboard/DashboardAnnouncements.vue +93 -0
- package/app/components/dashboard/DashboardOnboarding.vue +285 -0
- package/app/components/dashboard/DashboardPublishingQueue.vue +47 -0
- package/app/components/dashboard/DashboardQuickActions.vue +44 -0
- package/app/components/dashboard/DashboardStats.vue +63 -0
- package/app/components/form/inputs/CategoryTreePicker.vue +265 -109
- package/app/components/form/inputs/EntityConfigurationsPanel.vue +235 -0
- package/app/composables/useClientFormExtensions.ts +89 -0
- package/app/composables/useClientLanguages.ts +81 -0
- package/app/composables/useDashboardData.ts +169 -0
- package/app/composables/useOnboardingState.ts +151 -0
- package/app/data/footerTemplate.ts +283 -0
- package/app/lang/de/motor-admin/ai_system_prompts.json +1 -0
- package/app/lang/de/motor-admin/categories.json +1 -0
- package/app/lang/de/motor-admin/category_trees.json +2 -1
- package/app/lang/de/motor-admin/clients.json +17 -1
- package/app/lang/de/motor-admin/config_variables.json +1 -0
- package/app/lang/de/motor-admin/dashboard.json +83 -0
- package/app/lang/de/motor-admin/domains.json +6 -1
- package/app/lang/de/motor-admin/email_templates.json +1 -0
- package/app/lang/de/motor-admin/entity_configurations.json +12 -0
- package/app/lang/de/motor-admin/languages.json +1 -0
- package/app/lang/de/motor-admin/onboarding.json +60 -0
- package/app/lang/de/motor-admin/permissions.json +1 -0
- package/app/lang/de/motor-admin/roles.json +1 -0
- package/app/lang/de/motor-admin/users.json +1 -0
- package/app/lang/en/motor-admin/ai_system_prompts.json +1 -0
- package/app/lang/en/motor-admin/categories.json +1 -0
- package/app/lang/en/motor-admin/category_trees.json +2 -1
- package/app/lang/en/motor-admin/clients.json +17 -1
- package/app/lang/en/motor-admin/config_variables.json +1 -0
- package/app/lang/en/motor-admin/dashboard.json +83 -0
- package/app/lang/en/motor-admin/domains.json +6 -1
- package/app/lang/en/motor-admin/email_templates.json +1 -0
- package/app/lang/en/motor-admin/entity_configurations.json +12 -0
- package/app/lang/en/motor-admin/languages.json +1 -0
- package/app/lang/en/motor-admin/onboarding.json +60 -0
- package/app/lang/en/motor-admin/permissions.json +1 -0
- package/app/lang/en/motor-admin/roles.json +1 -0
- package/app/lang/en/motor-admin/users.json +1 -0
- package/app/pages/index.vue +119 -22
- package/app/pages/login.vue +6 -0
- package/app/pages/motor-admin/ai-system-prompts/[id]/edit.vue +4 -4
- package/app/pages/motor-admin/category-trees/[id]/categories/[categoryId]/edit.vue +4 -3
- package/app/pages/motor-admin/category-trees/[id]/edit.vue +4 -4
- package/app/pages/motor-admin/clients/[id]/edit.vue +146 -6
- package/app/pages/motor-admin/clients/create.vue +34 -2
- package/app/pages/motor-admin/config-variables/[id]/edit.vue +4 -4
- package/app/pages/motor-admin/domains/[id]/edit.vue +18 -5
- package/app/pages/motor-admin/email-templates/[id]/edit.vue +4 -4
- package/app/pages/motor-admin/email-templates/index.vue +36 -25
- package/app/pages/motor-admin/languages/[id]/edit.vue +17 -4
- package/app/pages/motor-admin/languages/create.vue +13 -0
- package/app/pages/motor-admin/permission-groups/[id]/edit.vue +4 -4
- package/app/pages/motor-admin/roles/[id]/edit.vue +4 -4
- package/app/pages/motor-admin/roles/create.vue +4 -1
- package/app/pages/motor-admin/users/[id]/edit.vue +4 -3
- package/app/pages/motor-admin/users/index.vue +1 -0
- package/app/pages/profile.vue +47 -1
- package/app/pages/search.vue +13 -3
- package/app/types/generated/form-meta.ts +24 -20
- package/app/types/generated/grid-meta.ts +5 -3
- package/nuxt.config.ts +15 -1
- package/package.json +6 -2
- package/app/pages/dashboard.vue +0 -5
package/app/pages/profile.vue
CHANGED
|
@@ -9,8 +9,10 @@ definePageMeta({
|
|
|
9
9
|
})
|
|
10
10
|
|
|
11
11
|
const { t } = useI18n()
|
|
12
|
+
const router = useRouter()
|
|
12
13
|
const { user, refreshIdentity } = useSanctumAuth<User>()
|
|
13
|
-
const { updateProfile } = useProfileApi()
|
|
14
|
+
const { updateProfile, resetOnboarding } = useProfileApi()
|
|
15
|
+
const { resetAll: resetOnboardingState } = useOnboardingResetAll()
|
|
14
16
|
const { success, error: notifyError, info } = useNotify()
|
|
15
17
|
|
|
16
18
|
// Test function to demonstrate error notifications
|
|
@@ -172,6 +174,34 @@ const passwordState = reactive({
|
|
|
172
174
|
|
|
173
175
|
const passwordLoading = ref(false)
|
|
174
176
|
|
|
177
|
+
// ============================================
|
|
178
|
+
// Onboarding Tour
|
|
179
|
+
// ============================================
|
|
180
|
+
|
|
181
|
+
const onboardingLoading = ref(false)
|
|
182
|
+
|
|
183
|
+
async function onRestartTour() {
|
|
184
|
+
onboardingLoading.value = true
|
|
185
|
+
try {
|
|
186
|
+
await resetOnboarding()
|
|
187
|
+
resetOnboardingState()
|
|
188
|
+
await refreshIdentity()
|
|
189
|
+
success(t('motor-core.profile.toast_tour_reset_title'), t('motor-core.profile.toast_tour_reset_message'))
|
|
190
|
+
await router.push('/')
|
|
191
|
+
}
|
|
192
|
+
catch (err: unknown) {
|
|
193
|
+
const message = err instanceof Error ? err.message : t('motor-core.profile.toast_tour_reset_error')
|
|
194
|
+
notifyError(t('motor-core.profile.toast_tour_reset_error'), message, {
|
|
195
|
+
message,
|
|
196
|
+
stack: err instanceof Error ? err.stack : undefined,
|
|
197
|
+
url: '/api/profile/reset-onboarding',
|
|
198
|
+
})
|
|
199
|
+
}
|
|
200
|
+
finally {
|
|
201
|
+
onboardingLoading.value = false
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
175
205
|
async function onPasswordSubmit(event: FormSubmitEvent<PasswordSchema>) {
|
|
176
206
|
passwordLoading.value = true
|
|
177
207
|
|
|
@@ -293,6 +323,22 @@ async function onPasswordSubmit(event: FormSubmitEvent<PasswordSchema>) {
|
|
|
293
323
|
</UForm>
|
|
294
324
|
</UPageCard>
|
|
295
325
|
|
|
326
|
+
<!-- Onboarding Tour Card -->
|
|
327
|
+
<UPageCard
|
|
328
|
+
:title="t('motor-core.profile.onboarding_title')"
|
|
329
|
+
:description="t('motor-core.profile.onboarding_description')"
|
|
330
|
+
>
|
|
331
|
+
<div class="flex justify-end">
|
|
332
|
+
<UButton
|
|
333
|
+
:loading="onboardingLoading"
|
|
334
|
+
icon="i-lucide-graduation-cap"
|
|
335
|
+
@click="onRestartTour"
|
|
336
|
+
>
|
|
337
|
+
{{ t('motor-core.profile.restart_tour') }}
|
|
338
|
+
</UButton>
|
|
339
|
+
</div>
|
|
340
|
+
</UPageCard>
|
|
341
|
+
|
|
296
342
|
<!-- Change Password Card -->
|
|
297
343
|
<UPageCard
|
|
298
344
|
:title="t('motor-core.profile.change_password_title')"
|
package/app/pages/search.vue
CHANGED
|
@@ -4,6 +4,11 @@ import type { SearchGridRow } from '@motor-cms/ui-core/app/types/search'
|
|
|
4
4
|
import type { PaginatedResponse, PaginationMeta } from '@motor-cms/ui-core/app/types/grid'
|
|
5
5
|
import { watchDebounced } from '@vueuse/core'
|
|
6
6
|
|
|
7
|
+
definePageMeta({
|
|
8
|
+
layout: 'default',
|
|
9
|
+
permission: 'search.read'
|
|
10
|
+
})
|
|
11
|
+
|
|
7
12
|
const { t } = useI18n()
|
|
8
13
|
const route = useRoute()
|
|
9
14
|
const router = useRouter()
|
|
@@ -123,16 +128,20 @@ async function handleCardAction(key: string, id: number | string | null, meta: R
|
|
|
123
128
|
quicklinkerPageName.value = (meta.name as string) ?? ''
|
|
124
129
|
quicklinkerOpen.value = true
|
|
125
130
|
} else if (key === 'publish' && id) {
|
|
131
|
+
const isPublished = !!meta?.is_published
|
|
126
132
|
try {
|
|
127
133
|
await client(`/api/v2/builder-pages/${id}/publication`, {
|
|
128
134
|
method: 'PUT',
|
|
129
|
-
body: { is_published:
|
|
135
|
+
body: { is_published: !isPublished }
|
|
130
136
|
})
|
|
131
137
|
toast.add({
|
|
132
|
-
title:
|
|
138
|
+
title: !isPublished
|
|
139
|
+
? t('motor-builder.builder_pages.toast_published')
|
|
140
|
+
: t('motor-builder.builder_pages.toast_unpublished'),
|
|
133
141
|
color: 'success',
|
|
134
|
-
icon: 'i-lucide-globe'
|
|
142
|
+
icon: !isPublished ? 'i-lucide-globe' : 'i-lucide-globe-lock'
|
|
135
143
|
})
|
|
144
|
+
doSearch()
|
|
136
145
|
} catch {
|
|
137
146
|
toast.add({
|
|
138
147
|
title: t('motor-builder.builder_pages.toast_publish_error'),
|
|
@@ -262,6 +271,7 @@ onMounted(() => {
|
|
|
262
271
|
:thumbnail-url="row.thumbnail_url"
|
|
263
272
|
:module="row.module"
|
|
264
273
|
:index-label="row.index_label"
|
|
274
|
+
:suffix="row.suffix"
|
|
265
275
|
:to="row.to"
|
|
266
276
|
:actions="row.actions"
|
|
267
277
|
:file-id="row.raw_index === 'files' ? row.id : undefined"
|
|
@@ -28,16 +28,16 @@ export const clientFormMeta = {
|
|
|
28
28
|
fields: {
|
|
29
29
|
name: { input: 'text', required: true },
|
|
30
30
|
slug: { input: 'text', required: true },
|
|
31
|
-
address: { input: 'text' },
|
|
32
|
-
zip: { input: 'text' },
|
|
33
|
-
city: { input: 'text' },
|
|
34
|
-
country_iso_3166_1: { input: 'text' },
|
|
31
|
+
address: { input: 'text', required: true },
|
|
32
|
+
zip: { input: 'text', required: true },
|
|
33
|
+
city: { input: 'text', required: true },
|
|
34
|
+
country_iso_3166_1: { input: 'text', required: true },
|
|
35
|
+
is_active: { input: 'toggle', required: true },
|
|
36
|
+
contact_name: { input: 'text', required: true },
|
|
37
|
+
contact_email: { input: 'email', required: true },
|
|
38
|
+
contact_phone: { input: 'text', required: true },
|
|
35
39
|
website: { input: 'text' },
|
|
36
|
-
description: { input: 'textarea' }
|
|
37
|
-
is_active: { input: 'toggle' },
|
|
38
|
-
contact_name: { input: 'text' },
|
|
39
|
-
contact_email: { input: 'email' },
|
|
40
|
-
contact_phone: { input: 'text' }
|
|
40
|
+
description: { input: 'textarea' }
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
patch: {
|
|
@@ -45,16 +45,16 @@ export const clientFormMeta = {
|
|
|
45
45
|
fields: {
|
|
46
46
|
name: { input: 'text', required: true },
|
|
47
47
|
slug: { input: 'text', required: true },
|
|
48
|
-
address: { input: 'text' },
|
|
49
|
-
zip: { input: 'text' },
|
|
50
|
-
city: { input: 'text' },
|
|
51
|
-
country_iso_3166_1: { input: 'text' },
|
|
48
|
+
address: { input: 'text', required: true },
|
|
49
|
+
zip: { input: 'text', required: true },
|
|
50
|
+
city: { input: 'text', required: true },
|
|
51
|
+
country_iso_3166_1: { input: 'text', required: true },
|
|
52
|
+
is_active: { input: 'toggle', required: true },
|
|
53
|
+
contact_name: { input: 'text', required: true },
|
|
54
|
+
contact_email: { input: 'email', required: true },
|
|
55
|
+
contact_phone: { input: 'text', required: true },
|
|
52
56
|
website: { input: 'text' },
|
|
53
|
-
description: { input: 'textarea' }
|
|
54
|
-
is_active: { input: 'toggle' },
|
|
55
|
-
contact_name: { input: 'text' },
|
|
56
|
-
contact_email: { input: 'email' },
|
|
57
|
-
contact_phone: { input: 'text' }
|
|
57
|
+
description: { input: 'textarea' }
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
} as const
|
|
@@ -92,7 +92,9 @@ export const domainFormMeta = {
|
|
|
92
92
|
protocol: { input: 'text', required: true },
|
|
93
93
|
host: { input: 'text', required: true },
|
|
94
94
|
port: { input: 'number', required: true },
|
|
95
|
-
path: { input: 'text', required: true }
|
|
95
|
+
path: { input: 'text', required: true },
|
|
96
|
+
is_preview_domain: { input: 'toggle' },
|
|
97
|
+
is_canonical: { input: 'toggle' }
|
|
96
98
|
}
|
|
97
99
|
},
|
|
98
100
|
patch: {
|
|
@@ -104,7 +106,9 @@ export const domainFormMeta = {
|
|
|
104
106
|
protocol: { input: 'text', required: true },
|
|
105
107
|
host: { input: 'text', required: true },
|
|
106
108
|
port: { input: 'number', required: true },
|
|
107
|
-
path: { input: 'text', required: true }
|
|
109
|
+
path: { input: 'text', required: true },
|
|
110
|
+
is_preview_domain: { input: 'toggle' },
|
|
111
|
+
is_canonical: { input: 'toggle' }
|
|
108
112
|
}
|
|
109
113
|
}
|
|
110
114
|
} as const
|
|
@@ -32,6 +32,7 @@ export const clientMeta = {
|
|
|
32
32
|
contact_name: { type: 'string' },
|
|
33
33
|
contact_phone: { type: 'string' },
|
|
34
34
|
contact_email: { type: 'string', renderer: 'link' },
|
|
35
|
+
frontend_config: { type: 'unknown' },
|
|
35
36
|
created_at: { type: 'string' },
|
|
36
37
|
updated_at: { type: 'string' }
|
|
37
38
|
}
|
|
@@ -57,8 +58,9 @@ export const domainMeta = {
|
|
|
57
58
|
id: { type: 'integer', renderer: 'number', hideable: false },
|
|
58
59
|
name: { type: 'string', sortable: true, hideable: false },
|
|
59
60
|
client: { type: 'ref', renderer: 'text', ref: 'ClientResource', labelKey: 'name' },
|
|
60
|
-
client_id: { type: '
|
|
61
|
+
client_id: { type: 'integer', renderer: 'number' },
|
|
61
62
|
is_active: { type: 'boolean', renderer: 'boolean' },
|
|
63
|
+
is_preview_domain: { type: 'boolean', renderer: 'boolean' },
|
|
62
64
|
protocol: { type: 'string' },
|
|
63
65
|
host: { type: 'string' },
|
|
64
66
|
port: { type: 'integer', renderer: 'number' },
|
|
@@ -124,8 +126,8 @@ export const permissionGroupMeta = {
|
|
|
124
126
|
fields: {
|
|
125
127
|
id: { type: 'integer', renderer: 'number', hideable: false },
|
|
126
128
|
name: { type: 'string', sortable: true, hideable: false },
|
|
127
|
-
sort_position: { type: '
|
|
128
|
-
permission_names: { type: '
|
|
129
|
+
sort_position: { type: 'integer', renderer: 'number' },
|
|
130
|
+
permission_names: { type: 'array' },
|
|
129
131
|
permissions: { type: 'ref[]', renderer: 'list', ref: 'PermissionResource', labelKey: 'name' },
|
|
130
132
|
created_at: { type: 'string' },
|
|
131
133
|
updated_at: { type: 'string' }
|
package/nuxt.config.ts
CHANGED
|
@@ -1 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import { fileURLToPath } from 'node:url'
|
|
2
|
+
import { dirname, resolve } from 'node:path'
|
|
3
|
+
|
|
4
|
+
const __layerDir = dirname(fileURLToPath(import.meta.url))
|
|
5
|
+
|
|
6
|
+
export default defineNuxtConfig({
|
|
7
|
+
modules: ['v-onboarding/nuxt'],
|
|
8
|
+
css: [resolve(__layerDir, 'app/assets/css/v-onboarding.css')],
|
|
9
|
+
runtimeConfig: {
|
|
10
|
+
public: {
|
|
11
|
+
featureClientFrontendConfig:
|
|
12
|
+
process.env.NUXT_PUBLIC_FEATURE_CLIENT_FRONTEND_CONFIG === 'true'
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@motor-cms/ui-admin",
|
|
3
|
-
"version": "1.1.0-alpha.
|
|
3
|
+
"version": "1.1.0-alpha.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./nuxt.config.ts",
|
|
6
6
|
"files": [
|
|
@@ -16,8 +16,12 @@
|
|
|
16
16
|
"@tiptap/vue-3": "^3.0.0",
|
|
17
17
|
"@vueuse/core": "^14.0.0",
|
|
18
18
|
"sortablejs": "^1.15.0",
|
|
19
|
+
"v-onboarding": "^2.12.2",
|
|
19
20
|
"zod": "^4.0.0",
|
|
20
|
-
"@motor-cms/ui-core": "1.1.0-alpha.
|
|
21
|
+
"@motor-cms/ui-core": "1.1.0-alpha.5"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@motor-cms/ui-core": "1.1.0-alpha.5"
|
|
21
25
|
},
|
|
22
26
|
"peerDependencies": {
|
|
23
27
|
"nuxt": "^4.0.0",
|