@motor-cms/ui-admin 1.1.0-alpha.3 → 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.
Files changed (73) hide show
  1. package/app/assets/css/v-onboarding.css +64 -0
  2. package/app/components/OnboardingStep.vue +42 -0
  3. package/app/components/UsersOnboarding.vue +84 -0
  4. package/app/components/client/FooterSlotCard.vue +313 -0
  5. package/app/components/client/GlobalComponentsSection.vue +65 -0
  6. package/app/components/dashboard/DashboardActivity.vue +71 -0
  7. package/app/components/dashboard/DashboardActivityItem.vue +96 -0
  8. package/app/components/dashboard/DashboardAnnouncementModal.vue +327 -0
  9. package/app/components/dashboard/DashboardAnnouncements.vue +93 -0
  10. package/app/components/dashboard/DashboardOnboarding.vue +285 -0
  11. package/app/components/dashboard/DashboardPublishingQueue.vue +47 -0
  12. package/app/components/dashboard/DashboardQuickActions.vue +44 -0
  13. package/app/components/dashboard/DashboardStats.vue +63 -0
  14. package/app/components/form/inputs/CategoryTreePicker.vue +265 -109
  15. package/app/components/form/inputs/EntityConfigurationsPanel.vue +235 -0
  16. package/app/composables/useClientFormExtensions.ts +89 -0
  17. package/app/composables/useClientLanguages.ts +81 -0
  18. package/app/composables/useDashboardData.ts +169 -0
  19. package/app/composables/useOnboardingState.ts +151 -0
  20. package/app/data/footerTemplate.ts +283 -0
  21. package/app/lang/de/motor-admin/ai_system_prompts.json +1 -0
  22. package/app/lang/de/motor-admin/categories.json +1 -0
  23. package/app/lang/de/motor-admin/category_trees.json +2 -1
  24. package/app/lang/de/motor-admin/clients.json +17 -1
  25. package/app/lang/de/motor-admin/config_variables.json +1 -0
  26. package/app/lang/de/motor-admin/dashboard.json +83 -0
  27. package/app/lang/de/motor-admin/domains.json +6 -1
  28. package/app/lang/de/motor-admin/email_templates.json +1 -0
  29. package/app/lang/de/motor-admin/entity_configurations.json +12 -0
  30. package/app/lang/de/motor-admin/languages.json +1 -0
  31. package/app/lang/de/motor-admin/onboarding.json +60 -0
  32. package/app/lang/de/motor-admin/permissions.json +1 -0
  33. package/app/lang/de/motor-admin/roles.json +1 -0
  34. package/app/lang/de/motor-admin/users.json +1 -0
  35. package/app/lang/en/motor-admin/ai_system_prompts.json +1 -0
  36. package/app/lang/en/motor-admin/categories.json +1 -0
  37. package/app/lang/en/motor-admin/category_trees.json +2 -1
  38. package/app/lang/en/motor-admin/clients.json +17 -1
  39. package/app/lang/en/motor-admin/config_variables.json +1 -0
  40. package/app/lang/en/motor-admin/dashboard.json +83 -0
  41. package/app/lang/en/motor-admin/domains.json +6 -1
  42. package/app/lang/en/motor-admin/email_templates.json +1 -0
  43. package/app/lang/en/motor-admin/entity_configurations.json +12 -0
  44. package/app/lang/en/motor-admin/languages.json +1 -0
  45. package/app/lang/en/motor-admin/onboarding.json +60 -0
  46. package/app/lang/en/motor-admin/permissions.json +1 -0
  47. package/app/lang/en/motor-admin/roles.json +1 -0
  48. package/app/lang/en/motor-admin/users.json +1 -0
  49. package/app/pages/index.vue +119 -22
  50. package/app/pages/login.vue +6 -0
  51. package/app/pages/motor-admin/ai-system-prompts/[id]/edit.vue +4 -4
  52. package/app/pages/motor-admin/category-trees/[id]/categories/[categoryId]/edit.vue +4 -3
  53. package/app/pages/motor-admin/category-trees/[id]/edit.vue +4 -4
  54. package/app/pages/motor-admin/clients/[id]/edit.vue +146 -6
  55. package/app/pages/motor-admin/clients/create.vue +34 -2
  56. package/app/pages/motor-admin/config-variables/[id]/edit.vue +4 -4
  57. package/app/pages/motor-admin/domains/[id]/edit.vue +18 -5
  58. package/app/pages/motor-admin/email-templates/[id]/edit.vue +4 -4
  59. package/app/pages/motor-admin/email-templates/index.vue +36 -25
  60. package/app/pages/motor-admin/languages/[id]/edit.vue +17 -4
  61. package/app/pages/motor-admin/languages/create.vue +13 -0
  62. package/app/pages/motor-admin/permission-groups/[id]/edit.vue +4 -4
  63. package/app/pages/motor-admin/roles/[id]/edit.vue +4 -4
  64. package/app/pages/motor-admin/roles/create.vue +4 -1
  65. package/app/pages/motor-admin/users/[id]/edit.vue +4 -3
  66. package/app/pages/motor-admin/users/index.vue +1 -0
  67. package/app/pages/profile.vue +47 -1
  68. package/app/pages/search.vue +13 -3
  69. package/app/types/generated/form-meta.ts +24 -20
  70. package/app/types/generated/grid-meta.ts +5 -3
  71. package/nuxt.config.ts +15 -1
  72. package/package.json +6 -2
  73. package/app/pages/dashboard.vue +0 -5
@@ -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')"
@@ -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: true }
135
+ body: { is_published: !isPublished }
130
136
  })
131
137
  toast.add({
132
- title: t('motor-builder.builder_pages.toast_published'),
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: 'string' },
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: 'string' },
128
- permission_names: { type: 'string' },
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
- export default defineNuxtConfig({})
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",
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.3"
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",
@@ -1,5 +0,0 @@
1
- <script setup lang="ts">
2
- definePageMeta({
3
- redirect: '/'
4
- })
5
- </script>