@motor-cms/ui-admin 1.5.2 → 1.6.0

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.
@@ -9,8 +9,9 @@ const emit = defineEmits<{
9
9
  }>()
10
10
 
11
11
  const { t } = useI18n()
12
- const client = useSanctumClient()
13
- const { can } = usePermissions()
12
+ const apiClient = useSanctumClient()
13
+ const { can, hasRole } = usePermissions()
14
+ const { user } = useSanctumAuth<import('@motor-cms/ui-core/app/types/auth').User>()
14
15
  const saving = ref(false)
15
16
 
16
17
  const canWriteAnnouncements = computed(() => can('dashboard-announcements.write'))
@@ -21,6 +22,7 @@ const form = reactive({
21
22
  type: 'info',
22
23
  audience: 'self',
23
24
  target_user_ids: [] as number[],
25
+ client_id: undefined as number | undefined,
24
26
  linkable_type: '',
25
27
  linkable_id: undefined as number | undefined,
26
28
  starts_at: undefined as string | undefined,
@@ -56,11 +58,29 @@ const userOptions = ref<Array<{ label: string; value: number }>>([])
56
58
  const usersLoading = ref(false)
57
59
  const usersFetched = ref(false)
58
60
 
61
+ const clientOptions = computed(() => {
62
+ return (user.value?.data?.clients ?? []).map(c => ({
63
+ label: c.name,
64
+ value: c.id,
65
+ }))
66
+ })
67
+
68
+ const allClientOptions = ref<Array<{ label: string; value: number }>>([])
69
+ const allClientsFetched = ref(false)
70
+ const allClientsLoading = ref(false)
71
+
72
+ const visibleClientOptions = computed(() => {
73
+ if (hasRole('SuperAdmin') && allClientsFetched.value) {
74
+ return allClientOptions.value
75
+ }
76
+ return clientOptions.value
77
+ })
78
+
59
79
  watch(() => form.audience, async (audience) => {
60
80
  if (audience === 'users' && !usersFetched.value) {
61
81
  usersLoading.value = true
62
82
  try {
63
- const response = await client<{ data: Array<{ id: number; name: string }> }>('/api/v2/users?per_page=200')
83
+ const response = await apiClient<{ data: Array<{ id: number; name: string }> }>('/api/v2/users?per_page=200')
64
84
  userOptions.value = response.data.map(u => ({
65
85
  label: u.name,
66
86
  value: u.id,
@@ -70,6 +90,19 @@ watch(() => form.audience, async (audience) => {
70
90
  usersLoading.value = false
71
91
  }
72
92
  }
93
+ if (audience === 'client' && hasRole('SuperAdmin') && !allClientsFetched.value) {
94
+ allClientsLoading.value = true
95
+ try {
96
+ const response = await apiClient<{ data: Array<{ id: number; name: string }> }>('/api/v2/clients?per_page=200')
97
+ allClientOptions.value = response.data.map(c => ({
98
+ label: c.name,
99
+ value: c.id,
100
+ }))
101
+ allClientsFetched.value = true
102
+ } finally {
103
+ allClientsLoading.value = false
104
+ }
105
+ }
73
106
  })
74
107
 
75
108
  const linkableOptions = ref<Array<{ label: string; value: number }>>([])
@@ -106,7 +139,7 @@ async function fetchLinkableOptions(query: string) {
106
139
  if (query) {
107
140
  params.set('search', query)
108
141
  }
109
- const response = await client<{ data: Array<Record<string, any>> }>(`${config.endpoint}?${params}`)
142
+ const response = await apiClient<{ data: Array<Record<string, any>> }>(`${config.endpoint}?${params}`)
110
143
  linkableOptions.value = response.data.map(item => ({
111
144
  label: config.labelFn(item),
112
145
  value: item.id,
@@ -144,6 +177,9 @@ async function handleSubmit() {
144
177
  if (form.audience === 'users') {
145
178
  data.target_user_ids = form.target_user_ids
146
179
  }
180
+ if (form.audience === 'client' && form.client_id) {
181
+ data.client_id = form.client_id
182
+ }
147
183
  if (form.linkable_type && form.linkable_id) {
148
184
  data.linkable_type = form.linkable_type
149
185
  data.linkable_id = form.linkable_id
@@ -155,7 +191,7 @@ async function handleSubmit() {
155
191
  data.expires_at = form.expires_at
156
192
  }
157
193
 
158
- await client('/api/v2/dashboard/announcements', {
194
+ await apiClient('/api/v2/dashboard/announcements', {
159
195
  method: 'POST',
160
196
  body: data,
161
197
  })
@@ -166,6 +202,7 @@ async function handleSubmit() {
166
202
  type: 'info',
167
203
  audience: 'self',
168
204
  target_user_ids: [],
205
+ client_id: undefined,
169
206
  linkable_type: '',
170
207
  linkable_id: null,
171
208
  starts_at: null,
@@ -222,6 +259,17 @@ async function handleSubmit() {
222
259
  />
223
260
  </UFormField>
224
261
 
262
+ <UFormField v-if="form.audience === 'client'" :label="t('motor-admin.dashboard.announcements.field_client')">
263
+ <USelectMenu
264
+ v-model="form.client_id"
265
+ :items="visibleClientOptions"
266
+ value-key="value"
267
+ :loading="allClientsLoading"
268
+ :placeholder="t('motor-admin.dashboard.announcements.field_client_placeholder')"
269
+ class="w-full"
270
+ />
271
+ </UFormField>
272
+
225
273
  <UFormField :label="t('motor-admin.dashboard.announcements.field_link')">
226
274
  <USelectMenu
227
275
  v-model="form.linkable_type"
@@ -80,7 +80,7 @@ const borderColors: Record<string, string> = {
80
80
  {{ item.linkable_name }}
81
81
  </NuxtLink>
82
82
  <div class="text-xs text-dimmed mt-2">
83
- {{ item.created_by_name }} &middot; {{ formatTimeAgo(new Date(item.created_at)) }}
83
+ {{ item.created_by_name }} &middot; {{ formatTimeAgo(new Date(item.starts_at ?? item.created_at)) }}
84
84
  </div>
85
85
  </div>
86
86
  </div>
@@ -37,6 +37,7 @@ export interface AnnouncementItem {
37
37
  linkable_name: string | null
38
38
  linkable_url: string | null
39
39
  created_by_name: string | null
40
+ starts_at: string | null
40
41
  created_at: string
41
42
  }
42
43
 
@@ -49,6 +49,8 @@
49
49
  "field_audience": "Zielgruppe",
50
50
  "field_users": "Nutzer auswählen",
51
51
  "field_users_placeholder": "Nutzer suchen...",
52
+ "field_client": "Mandant auswählen",
53
+ "field_client_placeholder": "Mandant wählen...",
52
54
  "field_link": "Verknüpfung (optional)",
53
55
  "field_link_type_placeholder": "Typ wählen...",
54
56
  "field_link_item": "Element",
@@ -49,6 +49,8 @@
49
49
  "field_audience": "Audience",
50
50
  "field_users": "Select users",
51
51
  "field_users_placeholder": "Search users...",
52
+ "field_client": "Select client",
53
+ "field_client_placeholder": "Choose a client...",
52
54
  "field_link": "Link (optional)",
53
55
  "field_link_type_placeholder": "Select type...",
54
56
  "field_link_item": "Item",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@motor-cms/ui-admin",
3
- "version": "1.5.2",
3
+ "version": "1.6.0",
4
4
  "type": "module",
5
5
  "main": "./nuxt.config.ts",
6
6
  "files": [
@@ -17,7 +17,7 @@
17
17
  "@vueuse/core": "^14.0.0",
18
18
  "sortablejs": "^1.15.0",
19
19
  "zod": "^4.0.0",
20
- "@motor-cms/ui-core": "1.5.2"
20
+ "@motor-cms/ui-core": "1.6.0"
21
21
  },
22
22
  "peerDependencies": {
23
23
  "nuxt": "^4.0.0",