@motor-cms/ui-admin 1.0.1-alpha.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.
- package/README.md +77 -0
- package/app/components/form/inputs/CategoryTreeInput.vue +154 -0
- package/app/components/form/inputs/CategoryTreePicker.vue +355 -0
- package/app/components/form/inputs/NestedDraggable.vue +217 -0
- package/app/components/form/inputs/QuicklinksInput.vue +186 -0
- package/app/lang/de/motor-admin/CLAUDE.md +21 -0
- package/app/lang/de/motor-admin/ai_system_prompts.json +12 -0
- package/app/lang/de/motor-admin/categories.json +12 -0
- package/app/lang/de/motor-admin/category_trees.json +14 -0
- package/app/lang/de/motor-admin/clients.json +26 -0
- package/app/lang/de/motor-admin/config_variables.json +14 -0
- package/app/lang/de/motor-admin/domains.json +19 -0
- package/app/lang/de/motor-admin/email_templates.json +38 -0
- package/app/lang/de/motor-admin/global.json +5 -0
- package/app/lang/de/motor-admin/languages.json +16 -0
- package/app/lang/de/motor-admin/permissions.json +14 -0
- package/app/lang/de/motor-admin/roles.json +15 -0
- package/app/lang/de/motor-admin/users.json +22 -0
- package/app/lang/en/motor-admin/CLAUDE.md +7 -0
- package/app/lang/en/motor-admin/ai_system_prompts.json +12 -0
- package/app/lang/en/motor-admin/categories.json +12 -0
- package/app/lang/en/motor-admin/category_trees.json +14 -0
- package/app/lang/en/motor-admin/clients.json +26 -0
- package/app/lang/en/motor-admin/config_variables.json +14 -0
- package/app/lang/en/motor-admin/domains.json +18 -0
- package/app/lang/en/motor-admin/email_templates.json +33 -0
- package/app/lang/en/motor-admin/global.json +5 -0
- package/app/lang/en/motor-admin/languages.json +16 -0
- package/app/lang/en/motor-admin/permissions.json +14 -0
- package/app/lang/en/motor-admin/roles.json +15 -0
- package/app/lang/en/motor-admin/users.json +22 -0
- package/app/pages/dashboard.vue +5 -0
- package/app/pages/index.vue +39 -0
- package/app/pages/login.vue +85 -0
- package/app/pages/motor-admin/ai-system-prompts/CLAUDE.md +7 -0
- package/app/pages/motor-admin/ai-system-prompts/[id]/edit.vue +48 -0
- package/app/pages/motor-admin/ai-system-prompts/create.vue +40 -0
- package/app/pages/motor-admin/ai-system-prompts/index.vue +68 -0
- package/app/pages/motor-admin/category-trees/CLAUDE.md +7 -0
- package/app/pages/motor-admin/category-trees/[id]/CLAUDE.md +7 -0
- package/app/pages/motor-admin/category-trees/[id]/categories/[categoryId]/edit.vue +73 -0
- package/app/pages/motor-admin/category-trees/[id]/categories/create.vue +64 -0
- package/app/pages/motor-admin/category-trees/[id]/edit.vue +45 -0
- package/app/pages/motor-admin/category-trees/[id]/index.vue +81 -0
- package/app/pages/motor-admin/category-trees/create.vue +37 -0
- package/app/pages/motor-admin/category-trees/index.vue +54 -0
- package/app/pages/motor-admin/clients/CLAUDE.md +11 -0
- package/app/pages/motor-admin/clients/[id]/CLAUDE.md +11 -0
- package/app/pages/motor-admin/clients/[id]/edit.vue +45 -0
- package/app/pages/motor-admin/clients/create.vue +37 -0
- package/app/pages/motor-admin/clients/index.vue +46 -0
- package/app/pages/motor-admin/config-variables/CLAUDE.md +11 -0
- package/app/pages/motor-admin/config-variables/[id]/edit.vue +44 -0
- package/app/pages/motor-admin/config-variables/create.vue +36 -0
- package/app/pages/motor-admin/config-variables/index.vue +66 -0
- package/app/pages/motor-admin/domains/CLAUDE.md +11 -0
- package/app/pages/motor-admin/domains/[id]/edit.vue +54 -0
- package/app/pages/motor-admin/domains/create.vue +46 -0
- package/app/pages/motor-admin/domains/index.vue +98 -0
- package/app/pages/motor-admin/email-templates/CLAUDE.md +12 -0
- package/app/pages/motor-admin/email-templates/[id]/CLAUDE.md +7 -0
- package/app/pages/motor-admin/email-templates/[id]/edit.vue +56 -0
- package/app/pages/motor-admin/email-templates/create.vue +48 -0
- package/app/pages/motor-admin/email-templates/index.vue +67 -0
- package/app/pages/motor-admin/index.vue +12 -0
- package/app/pages/motor-admin/languages/CLAUDE.md +7 -0
- package/app/pages/motor-admin/languages/[id]/edit.vue +44 -0
- package/app/pages/motor-admin/languages/create.vue +36 -0
- package/app/pages/motor-admin/languages/index.vue +44 -0
- package/app/pages/motor-admin/permission-groups/CLAUDE.md +14 -0
- package/app/pages/motor-admin/permission-groups/[id]/CLAUDE.md +11 -0
- package/app/pages/motor-admin/permission-groups/[id]/edit.vue +49 -0
- package/app/pages/motor-admin/permission-groups/create.vue +41 -0
- package/app/pages/motor-admin/permission-groups/index.vue +43 -0
- package/app/pages/motor-admin/roles/CLAUDE.md +7 -0
- package/app/pages/motor-admin/roles/[id]/edit.vue +47 -0
- package/app/pages/motor-admin/roles/create.vue +40 -0
- package/app/pages/motor-admin/roles/index.vue +45 -0
- package/app/pages/motor-admin/theme-preview/CLAUDE.md +7 -0
- package/app/pages/motor-admin/theme-preview/index.vue +4801 -0
- package/app/pages/motor-admin/theme-preview/themes/CLAUDE.md +11 -0
- package/app/pages/motor-admin/theme-preview/themes/asymmetric-brutalist.md +381 -0
- package/app/pages/motor-admin/theme-preview/themes/bold-modern.md +231 -0
- package/app/pages/motor-admin/theme-preview/themes/geometric-minimal.md +778 -0
- package/app/pages/motor-admin/theme-preview/themes/gradient-flow.md +1057 -0
- package/app/pages/motor-admin/theme-preview/themes/liquid-glass.md +823 -0
- package/app/pages/motor-admin/theme-preview/themes/neon-amber.md +1223 -0
- package/app/pages/motor-admin/theme-preview/themes/neon-terminal.md +779 -0
- package/app/pages/motor-admin/theme-preview/themes/neon-violet.md +1134 -0
- package/app/pages/motor-admin/theme-preview/themes/professional-clean.md +232 -0
- package/app/pages/motor-admin/theme-preview/themes/refined-brutalist.md +462 -0
- package/app/pages/motor-admin/theme-preview/themes/wild-card.md +263 -0
- package/app/pages/motor-admin/users/CLAUDE.md +17 -0
- package/app/pages/motor-admin/users/[id]/CLAUDE.md +11 -0
- package/app/pages/motor-admin/users/[id]/edit.vue +83 -0
- package/app/pages/motor-admin/users/create.vue +40 -0
- package/app/pages/motor-admin/users/index.vue +66 -0
- package/app/pages/profile.vue +363 -0
- package/app/pages/search.vue +91 -0
- package/app/types/generated/form-meta.ts +258 -0
- package/app/types/generated/grid-meta.ts +172 -0
- package/nuxt.config.ts +1 -0
- package/package.json +26 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<!-- app/pages/motor-admin/domains/index.vue -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import type { ColumnDef } from '@motor-cms/ui-core/app/types/grid'
|
|
4
|
+
import { domainMeta } from '../../../types/generated/grid-meta'
|
|
5
|
+
|
|
6
|
+
definePageMeta({ permission: 'domains.read' })
|
|
7
|
+
|
|
8
|
+
interface DomainApi {
|
|
9
|
+
id: number
|
|
10
|
+
name: string
|
|
11
|
+
client?: { id: number, name: string }
|
|
12
|
+
client_id: string
|
|
13
|
+
is_active: boolean
|
|
14
|
+
protocol: string
|
|
15
|
+
host: string
|
|
16
|
+
port: number
|
|
17
|
+
path: string
|
|
18
|
+
created_at: string
|
|
19
|
+
updated_at: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface Domain {
|
|
23
|
+
id: number
|
|
24
|
+
name: string
|
|
25
|
+
client_name: string
|
|
26
|
+
is_active: boolean
|
|
27
|
+
protocol: string
|
|
28
|
+
host: string
|
|
29
|
+
port: string
|
|
30
|
+
path: string
|
|
31
|
+
created_at: string
|
|
32
|
+
updated_at: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const { t } = useI18n()
|
|
36
|
+
|
|
37
|
+
const columns: ColumnDef<Domain>[] = [
|
|
38
|
+
...columnsFromMeta<Domain>(domainMeta, t, {
|
|
39
|
+
pick: ['name', 'host', 'is_active'],
|
|
40
|
+
overrides: {
|
|
41
|
+
is_active: { renderer: 'boolean' }
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
// Insert client_name after name
|
|
47
|
+
columns.splice(1, 0, { key: 'client_name', label: t('motor-admin.clients.client') })
|
|
48
|
+
|
|
49
|
+
// Insert protocol before is_active (index 3 after splice)
|
|
50
|
+
columns.splice(3, 0, {
|
|
51
|
+
key: 'protocol',
|
|
52
|
+
label: t('motor-admin.domains.protocol'),
|
|
53
|
+
renderer: 'badge',
|
|
54
|
+
rendererProps: {
|
|
55
|
+
color: (value: string | null) => value === 'https' ? 'success' : 'warning'
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
columns.push(createdAtColumn(t))
|
|
60
|
+
|
|
61
|
+
const filters = [useClientFilter(), useIsActiveFilter()]
|
|
62
|
+
|
|
63
|
+
const fetchDomains = useGridFetch<DomainApi, Domain>('/api/v2/domains', {
|
|
64
|
+
transform: record => ({
|
|
65
|
+
id: record.id,
|
|
66
|
+
name: record.name,
|
|
67
|
+
client_name: record.client?.name ?? '-',
|
|
68
|
+
is_active: record.is_active,
|
|
69
|
+
protocol: record.protocol,
|
|
70
|
+
host: record.host,
|
|
71
|
+
port: String(record.port),
|
|
72
|
+
path: record.path,
|
|
73
|
+
created_at: record.created_at,
|
|
74
|
+
updated_at: record.updated_at
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
</script>
|
|
78
|
+
|
|
79
|
+
<template>
|
|
80
|
+
<GridPage
|
|
81
|
+
:title="t('motor-admin.domains.title')"
|
|
82
|
+
:subtitle="t('motor-admin.domains.subtitle')"
|
|
83
|
+
add-route="/motor-admin/domains/create"
|
|
84
|
+
:add-label="t('motor-admin.domains.add')"
|
|
85
|
+
write-permission="domains.write"
|
|
86
|
+
>
|
|
87
|
+
<GridBase
|
|
88
|
+
id="domains-grid"
|
|
89
|
+
:fetch="fetchDomains"
|
|
90
|
+
:columns="columns"
|
|
91
|
+
:filters="filters"
|
|
92
|
+
base-path="/motor-admin/domains"
|
|
93
|
+
:row-click-to="(row: any) => `/motor-admin/domains/${row.id}/edit`"
|
|
94
|
+
write-permission="domains.write"
|
|
95
|
+
delete-permission="domains.delete"
|
|
96
|
+
/>
|
|
97
|
+
</GridPage>
|
|
98
|
+
</template>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<claude-mem-context>
|
|
2
|
+
# Recent Activity
|
|
3
|
+
|
|
4
|
+
<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->
|
|
5
|
+
|
|
6
|
+
### Feb 12, 2026
|
|
7
|
+
|
|
8
|
+
| ID | Time | T | Title | Read |
|
|
9
|
+
|----|------|---|-------|------|
|
|
10
|
+
| #24261 | 3:09 PM | 🔵 | Email Templates Form Pattern with Slug Auto-Generation | ~414 |
|
|
11
|
+
| #24248 | 1:06 PM | 🔄 | Grid Filters Now Use Cached Entity Options via fetchResourceOptions | ~402 |
|
|
12
|
+
</claude-mem-context>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<!-- app/pages/motor-admin/email-templates/[id]/edit.vue -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import { emailTemplateFormMeta } from '../../../../types/generated/form-meta'
|
|
4
|
+
import { emailTemplateFormConfig, emailTemplateSelectOptionConfigs } from '@motor-cms/ui-core/app/types/config/email-template'
|
|
5
|
+
|
|
6
|
+
definePageMeta({ layout: 'default', permission: 'email-templates.write' })
|
|
7
|
+
|
|
8
|
+
const route = useRoute()
|
|
9
|
+
const { t } = useI18n()
|
|
10
|
+
const { fields: rawFields, schema, groups, state, loading, fetching, fetchError, formRef, selectOptions, selectOptionsLoading, onSubmit, onSaveAndContinue, onSaveAndNew, deleteRecord, deleting } = await useEntityForm({
|
|
11
|
+
apiEndpoint: '/api/v2/email-templates',
|
|
12
|
+
routePrefix: '/motor-admin/email-templates',
|
|
13
|
+
translationPrefix: 'motor-admin.email_templates',
|
|
14
|
+
formMeta: emailTemplateFormMeta,
|
|
15
|
+
formConfig: emailTemplateFormConfig,
|
|
16
|
+
mode: 'edit',
|
|
17
|
+
id: route.params.id as string,
|
|
18
|
+
selectOptionConfigs: emailTemplateSelectOptionConfigs
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const fields = reactive(rawFields)
|
|
22
|
+
const bodyHtmlField = fields.find(f => f.key === 'body_html')
|
|
23
|
+
if (bodyHtmlField) {
|
|
24
|
+
watchEffect(() => {
|
|
25
|
+
bodyHtmlField.hidden = !state.has_body_html
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<template>
|
|
31
|
+
<FormPage
|
|
32
|
+
:title="t('motor-admin.email_templates.edit_title')"
|
|
33
|
+
back-route="/motor-admin/email-templates"
|
|
34
|
+
:loading="fetching"
|
|
35
|
+
:error="fetchError"
|
|
36
|
+
>
|
|
37
|
+
<FormBase
|
|
38
|
+
ref="formRef"
|
|
39
|
+
v-model:state="state"
|
|
40
|
+
:fields="fields"
|
|
41
|
+
:schema="schema"
|
|
42
|
+
:groups="groups"
|
|
43
|
+
:select-options="selectOptions"
|
|
44
|
+
:select-options-loading="selectOptionsLoading"
|
|
45
|
+
:loading="loading"
|
|
46
|
+
:delete-record="deleteRecord"
|
|
47
|
+
:deleting="deleting"
|
|
48
|
+
cancel-route="/motor-admin/email-templates"
|
|
49
|
+
show-save-and-continue
|
|
50
|
+
show-save-and-new
|
|
51
|
+
@submit="onSubmit"
|
|
52
|
+
@save-and-continue="onSaveAndContinue"
|
|
53
|
+
@save-and-new="onSaveAndNew"
|
|
54
|
+
/>
|
|
55
|
+
</FormPage>
|
|
56
|
+
</template>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<!-- app/pages/motor-admin/email-templates/create.vue -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import { emailTemplateFormMeta } from '../../../types/generated/form-meta'
|
|
4
|
+
import { emailTemplateFormConfig, emailTemplateSelectOptionConfigs } from '@motor-cms/ui-core/app/types/config/email-template'
|
|
5
|
+
|
|
6
|
+
definePageMeta({ layout: 'default', permission: 'email-templates.write' })
|
|
7
|
+
|
|
8
|
+
const { t } = useI18n()
|
|
9
|
+
const { fields: rawFields, schema, groups, state, loading, selectOptions, selectOptionsLoading, formRef, onSubmit, onSaveAndNew } = await useEntityForm({
|
|
10
|
+
apiEndpoint: '/api/v2/email-templates',
|
|
11
|
+
routePrefix: '/motor-admin/email-templates',
|
|
12
|
+
translationPrefix: 'motor-admin.email_templates',
|
|
13
|
+
formMeta: emailTemplateFormMeta,
|
|
14
|
+
formConfig: emailTemplateFormConfig,
|
|
15
|
+
mode: 'create',
|
|
16
|
+
selectOptionConfigs: emailTemplateSelectOptionConfigs
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const fields = reactive(rawFields)
|
|
20
|
+
const bodyHtmlField = fields.find(f => f.key === 'body_html')
|
|
21
|
+
if (bodyHtmlField) {
|
|
22
|
+
watchEffect(() => {
|
|
23
|
+
bodyHtmlField.hidden = !state.has_body_html
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<template>
|
|
29
|
+
<FormPage
|
|
30
|
+
:title="t('motor-admin.email_templates.create_title')"
|
|
31
|
+
back-route="/motor-admin/email-templates"
|
|
32
|
+
>
|
|
33
|
+
<FormBase
|
|
34
|
+
ref="formRef"
|
|
35
|
+
v-model:state="state"
|
|
36
|
+
:fields="fields"
|
|
37
|
+
:schema="schema"
|
|
38
|
+
:groups="groups"
|
|
39
|
+
:select-options="selectOptions"
|
|
40
|
+
:select-options-loading="selectOptionsLoading"
|
|
41
|
+
:loading="loading"
|
|
42
|
+
cancel-route="/motor-admin/email-templates"
|
|
43
|
+
show-save-and-new
|
|
44
|
+
@submit="onSubmit"
|
|
45
|
+
@save-and-new="onSaveAndNew"
|
|
46
|
+
/>
|
|
47
|
+
</FormPage>
|
|
48
|
+
</template>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<!-- app/pages/motor-admin/email-templates/index.vue -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import type { components } from '@motor-cms/ui-core/app/types/generated/api'
|
|
4
|
+
import type { RowActionDef } from '@motor-cms/ui-core/app/types/grid'
|
|
5
|
+
import { emailTemplateMeta } from '../../../types/generated/grid-meta'
|
|
6
|
+
import { emailTemplateGridConfig } from '@motor-cms/ui-core/app/types/config/email-template'
|
|
7
|
+
|
|
8
|
+
definePageMeta({ permission: 'email-templates.read' })
|
|
9
|
+
|
|
10
|
+
type EmailTemplate = components['schemas']['EmailTemplateResource']
|
|
11
|
+
|
|
12
|
+
const { t } = useI18n()
|
|
13
|
+
|
|
14
|
+
const usageModalOpen = ref(false)
|
|
15
|
+
const usageEndpoint = ref('')
|
|
16
|
+
|
|
17
|
+
const columns = columnsFromMeta<EmailTemplate>(emailTemplateMeta, t, emailTemplateGridConfig)
|
|
18
|
+
|
|
19
|
+
columns.push(createdAtColumn(t))
|
|
20
|
+
|
|
21
|
+
const rowActions: RowActionDef<EmailTemplate>[] = [
|
|
22
|
+
{
|
|
23
|
+
key: 'usage',
|
|
24
|
+
label: t('motor-admin.email_templates.usage_title'),
|
|
25
|
+
icon: 'i-lucide-link',
|
|
26
|
+
silent: true,
|
|
27
|
+
handler: (row: EmailTemplate) => {
|
|
28
|
+
usageEndpoint.value = `/api/v2/email-templates/${row.id}/usage`
|
|
29
|
+
usageModalOpen.value = true
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
const filters = [useClientFilter(), useLanguageFilter()]
|
|
35
|
+
|
|
36
|
+
const fetchEmailTemplates = useGridFetch<EmailTemplate>('/api/v2/email-templates')
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<template>
|
|
40
|
+
<div>
|
|
41
|
+
<GridPage
|
|
42
|
+
:title="t('motor-admin.email_templates.title')"
|
|
43
|
+
:subtitle="t('motor-admin.email_templates.subtitle')"
|
|
44
|
+
add-route="/motor-admin/email-templates/create"
|
|
45
|
+
:add-label="t('motor-admin.email_templates.add')"
|
|
46
|
+
write-permission="email-templates.write"
|
|
47
|
+
>
|
|
48
|
+
<GridBase
|
|
49
|
+
id="email-templates-grid"
|
|
50
|
+
:fetch="fetchEmailTemplates"
|
|
51
|
+
:columns="columns"
|
|
52
|
+
:filters="filters"
|
|
53
|
+
:row-actions="rowActions"
|
|
54
|
+
base-path="/motor-admin/email-templates"
|
|
55
|
+
:row-click-to="(row: any) => `/motor-admin/email-templates/${row.id}/edit`"
|
|
56
|
+
write-permission="email-templates.write"
|
|
57
|
+
delete-permission="email-templates.delete"
|
|
58
|
+
/>
|
|
59
|
+
</GridPage>
|
|
60
|
+
|
|
61
|
+
<EntityUsageModal
|
|
62
|
+
v-model:open="usageModalOpen"
|
|
63
|
+
:endpoint="usageEndpoint"
|
|
64
|
+
:title="t('motor-admin.email_templates.usage_title')"
|
|
65
|
+
/>
|
|
66
|
+
</div>
|
|
67
|
+
</template>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!-- app/pages/motor-admin/index.vue -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
definePageMeta({ permission: 'administration.read' })
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<template>
|
|
7
|
+
<SectionLanding
|
|
8
|
+
section-prefix="motor-admin"
|
|
9
|
+
title-key="motor-core.global.administration"
|
|
10
|
+
subtitle-key="motor-core.global.section_subtitle"
|
|
11
|
+
/>
|
|
12
|
+
</template>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { languageFormMeta } from '../../../../types/generated/form-meta'
|
|
3
|
+
import { languageFormConfig } from '@motor-cms/ui-core/app/types/config/language'
|
|
4
|
+
|
|
5
|
+
definePageMeta({ layout: 'default', permission: 'languages.write' })
|
|
6
|
+
|
|
7
|
+
const route = useRoute()
|
|
8
|
+
const { t } = useI18n()
|
|
9
|
+
const { fields, schema, groups, state, loading, fetching, fetchError, formRef, onSubmit, onSaveAndContinue, onSaveAndNew, deleteRecord, deleting } = await useEntityForm({
|
|
10
|
+
apiEndpoint: '/api/v2/languages',
|
|
11
|
+
routePrefix: '/motor-admin/languages',
|
|
12
|
+
translationPrefix: 'motor-admin.languages',
|
|
13
|
+
formMeta: languageFormMeta,
|
|
14
|
+
formConfig: languageFormConfig,
|
|
15
|
+
mode: 'edit',
|
|
16
|
+
id: route.params.id as string
|
|
17
|
+
})
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<template>
|
|
21
|
+
<FormPage
|
|
22
|
+
:title="t('motor-admin.languages.edit_title')"
|
|
23
|
+
back-route="/motor-admin/languages"
|
|
24
|
+
:loading="fetching"
|
|
25
|
+
:error="fetchError"
|
|
26
|
+
>
|
|
27
|
+
<FormBase
|
|
28
|
+
ref="formRef"
|
|
29
|
+
v-model:state="state"
|
|
30
|
+
:fields="fields"
|
|
31
|
+
:schema="schema"
|
|
32
|
+
:groups="groups"
|
|
33
|
+
:loading="loading"
|
|
34
|
+
:delete-record="deleteRecord"
|
|
35
|
+
:deleting="deleting"
|
|
36
|
+
cancel-route="/motor-admin/languages"
|
|
37
|
+
show-save-and-continue
|
|
38
|
+
show-save-and-new
|
|
39
|
+
@submit="onSubmit"
|
|
40
|
+
@save-and-continue="onSaveAndContinue"
|
|
41
|
+
@save-and-new="onSaveAndNew"
|
|
42
|
+
/>
|
|
43
|
+
</FormPage>
|
|
44
|
+
</template>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { languageFormMeta } from '../../../types/generated/form-meta'
|
|
3
|
+
import { languageFormConfig } from '@motor-cms/ui-core/app/types/config/language'
|
|
4
|
+
|
|
5
|
+
definePageMeta({ layout: 'default', permission: 'languages.write' })
|
|
6
|
+
|
|
7
|
+
const { t } = useI18n()
|
|
8
|
+
const { fields, schema, groups, state, loading, formRef, onSubmit, onSaveAndNew } = await useEntityForm({
|
|
9
|
+
apiEndpoint: '/api/v2/languages',
|
|
10
|
+
routePrefix: '/motor-admin/languages',
|
|
11
|
+
translationPrefix: 'motor-admin.languages',
|
|
12
|
+
formMeta: languageFormMeta,
|
|
13
|
+
formConfig: languageFormConfig,
|
|
14
|
+
mode: 'create'
|
|
15
|
+
})
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<FormPage
|
|
20
|
+
:title="t('motor-admin.languages.create_title')"
|
|
21
|
+
back-route="/motor-admin/languages"
|
|
22
|
+
>
|
|
23
|
+
<FormBase
|
|
24
|
+
ref="formRef"
|
|
25
|
+
v-model:state="state"
|
|
26
|
+
:fields="fields"
|
|
27
|
+
:schema="schema"
|
|
28
|
+
:groups="groups"
|
|
29
|
+
:loading="loading"
|
|
30
|
+
cancel-route="/motor-admin/languages"
|
|
31
|
+
show-save-and-new
|
|
32
|
+
@submit="onSubmit"
|
|
33
|
+
@save-and-new="onSaveAndNew"
|
|
34
|
+
/>
|
|
35
|
+
</FormPage>
|
|
36
|
+
</template>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<!-- app/pages/motor-admin/languages/index.vue -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import type { components } from '@motor-cms/ui-core/app/types/generated/api'
|
|
4
|
+
import { languageMeta } from '../../../types/generated/grid-meta'
|
|
5
|
+
|
|
6
|
+
definePageMeta({ permission: 'languages.read' })
|
|
7
|
+
|
|
8
|
+
type Language = components['schemas']['LanguageResource']
|
|
9
|
+
|
|
10
|
+
const { t } = useI18n()
|
|
11
|
+
|
|
12
|
+
const columns = columnsFromMeta<Language>(languageMeta, t, {
|
|
13
|
+
pick: ['iso_639_1', 'english_name', 'native_name'],
|
|
14
|
+
overrides: {
|
|
15
|
+
iso_639_1: { renderer: 'badge', sortable: true, hideable: false },
|
|
16
|
+
english_name: { sortable: true, hideable: false },
|
|
17
|
+
native_name: { sortable: true }
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
columns.push(createdAtColumn(t))
|
|
22
|
+
|
|
23
|
+
const { fetch: fetchLanguages } = useGridData<Language>('/api/v2/languages')
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<template>
|
|
27
|
+
<GridPage
|
|
28
|
+
:title="t('motor-admin.languages.title')"
|
|
29
|
+
:subtitle="t('motor-admin.languages.subtitle')"
|
|
30
|
+
add-route="/motor-admin/languages/create"
|
|
31
|
+
:add-label="t('motor-admin.languages.add')"
|
|
32
|
+
write-permission="languages.write"
|
|
33
|
+
>
|
|
34
|
+
<GridBase
|
|
35
|
+
id="languages-grid"
|
|
36
|
+
:fetch="fetchLanguages"
|
|
37
|
+
:columns="columns"
|
|
38
|
+
base-path="/motor-admin/languages"
|
|
39
|
+
:row-click-to="(row: any) => `/motor-admin/languages/${row.id}/edit`"
|
|
40
|
+
write-permission="languages.write"
|
|
41
|
+
delete-permission="languages.delete"
|
|
42
|
+
/>
|
|
43
|
+
</GridPage>
|
|
44
|
+
</template>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<claude-mem-context>
|
|
2
|
+
# Recent Activity
|
|
3
|
+
|
|
4
|
+
<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->
|
|
5
|
+
|
|
6
|
+
### Feb 12, 2026
|
|
7
|
+
|
|
8
|
+
| ID | Time | T | Title | Read |
|
|
9
|
+
|----|------|---|-------|------|
|
|
10
|
+
| #24287 | 3:18 PM | ✅ | Permissions Endpoint Query Updated to Fetch All Permissions | ~260 |
|
|
11
|
+
| #24277 | 3:14 PM | ✅ | Permission Groups Form Uses Checkbox Group Instead of Multi-Select | ~254 |
|
|
12
|
+
| #24268 | 3:10 PM | 🟣 | Permission Groups Form Now Supports Multi-Checkbox Permission Assignment | ~299 |
|
|
13
|
+
| #24263 | " | 🟣 | Users Create Form with Cached Select Options | ~329 |
|
|
14
|
+
</claude-mem-context>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<claude-mem-context>
|
|
2
|
+
# Recent Activity
|
|
3
|
+
|
|
4
|
+
<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->
|
|
5
|
+
|
|
6
|
+
### Feb 12, 2026
|
|
7
|
+
|
|
8
|
+
| ID | Time | T | Title | Read |
|
|
9
|
+
|----|------|---|-------|------|
|
|
10
|
+
| #24269 | 3:11 PM | 🟣 | Permissions Multi-Select Field Added to Permission-Groups Form | ~435 |
|
|
11
|
+
</claude-mem-context>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { permissionGroupFormMeta } from '../../../../types/generated/form-meta'
|
|
3
|
+
import { permissionGroupFormConfig, permissionGroupSelectOptionConfigs, permissionGroupExtraFields } from '@motor-cms/ui-core/app/types/config/permission-group'
|
|
4
|
+
|
|
5
|
+
definePageMeta({ layout: 'default', permission: 'permission-groups.write' })
|
|
6
|
+
|
|
7
|
+
const route = useRoute()
|
|
8
|
+
const { t } = useI18n()
|
|
9
|
+
const { fields, schema, groups, state, loading, fetching, fetchError, formRef, selectOptions, selectOptionsLoading, onSubmit, onSaveAndContinue, onSaveAndNew, deleteRecord, deleting } = await useEntityForm({
|
|
10
|
+
apiEndpoint: '/api/v2/permission-groups',
|
|
11
|
+
routePrefix: '/motor-admin/permission-groups',
|
|
12
|
+
translationPrefix: 'motor-admin.permissions',
|
|
13
|
+
formMeta: permissionGroupFormMeta,
|
|
14
|
+
formConfig: permissionGroupFormConfig,
|
|
15
|
+
mode: 'edit',
|
|
16
|
+
id: route.params.id as string,
|
|
17
|
+
selectOptionConfigs: permissionGroupSelectOptionConfigs,
|
|
18
|
+
extraFields: permissionGroupExtraFields,
|
|
19
|
+
extraState: { permissions: [] }
|
|
20
|
+
})
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<template>
|
|
24
|
+
<FormPage
|
|
25
|
+
:title="t('motor-admin.permissions.edit_title')"
|
|
26
|
+
back-route="/motor-admin/permission-groups"
|
|
27
|
+
:loading="fetching"
|
|
28
|
+
:error="fetchError"
|
|
29
|
+
>
|
|
30
|
+
<FormBase
|
|
31
|
+
ref="formRef"
|
|
32
|
+
v-model:state="state"
|
|
33
|
+
:fields="fields"
|
|
34
|
+
:schema="schema"
|
|
35
|
+
:groups="groups"
|
|
36
|
+
:select-options="selectOptions"
|
|
37
|
+
:select-options-loading="selectOptionsLoading"
|
|
38
|
+
:loading="loading"
|
|
39
|
+
:delete-record="deleteRecord"
|
|
40
|
+
:deleting="deleting"
|
|
41
|
+
cancel-route="/motor-admin/permission-groups"
|
|
42
|
+
show-save-and-continue
|
|
43
|
+
show-save-and-new
|
|
44
|
+
@submit="onSubmit"
|
|
45
|
+
@save-and-continue="onSaveAndContinue"
|
|
46
|
+
@save-and-new="onSaveAndNew"
|
|
47
|
+
/>
|
|
48
|
+
</FormPage>
|
|
49
|
+
</template>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { permissionGroupFormMeta } from '../../../types/generated/form-meta'
|
|
3
|
+
import { permissionGroupFormConfig, permissionGroupSelectOptionConfigs, permissionGroupExtraFields } from '@motor-cms/ui-core/app/types/config/permission-group'
|
|
4
|
+
|
|
5
|
+
definePageMeta({ layout: 'default', permission: 'permission-groups.write' })
|
|
6
|
+
|
|
7
|
+
const { t } = useI18n()
|
|
8
|
+
const { fields, schema, groups, state, loading, selectOptions, selectOptionsLoading, formRef, onSubmit, onSaveAndNew } = await useEntityForm({
|
|
9
|
+
apiEndpoint: '/api/v2/permission-groups',
|
|
10
|
+
routePrefix: '/motor-admin/permission-groups',
|
|
11
|
+
translationPrefix: 'motor-admin.permissions',
|
|
12
|
+
formMeta: permissionGroupFormMeta,
|
|
13
|
+
formConfig: permissionGroupFormConfig,
|
|
14
|
+
mode: 'create',
|
|
15
|
+
selectOptionConfigs: permissionGroupSelectOptionConfigs,
|
|
16
|
+
extraFields: permissionGroupExtraFields,
|
|
17
|
+
extraState: { permissions: [] }
|
|
18
|
+
})
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<template>
|
|
22
|
+
<FormPage
|
|
23
|
+
:title="t('motor-admin.permissions.create_title')"
|
|
24
|
+
back-route="/motor-admin/permission-groups"
|
|
25
|
+
>
|
|
26
|
+
<FormBase
|
|
27
|
+
ref="formRef"
|
|
28
|
+
v-model:state="state"
|
|
29
|
+
:fields="fields"
|
|
30
|
+
:schema="schema"
|
|
31
|
+
:groups="groups"
|
|
32
|
+
:select-options="selectOptions"
|
|
33
|
+
:select-options-loading="selectOptionsLoading"
|
|
34
|
+
:loading="loading"
|
|
35
|
+
cancel-route="/motor-admin/permission-groups"
|
|
36
|
+
show-save-and-new
|
|
37
|
+
@submit="onSubmit"
|
|
38
|
+
@save-and-new="onSaveAndNew"
|
|
39
|
+
/>
|
|
40
|
+
</FormPage>
|
|
41
|
+
</template>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<!-- app/pages/motor-admin/permission-groups/index.vue -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import type { components } from '@motor-cms/ui-core/app/types/generated/api'
|
|
4
|
+
import { permissionGroupMeta } from '../../../types/generated/grid-meta'
|
|
5
|
+
|
|
6
|
+
definePageMeta({ permission: 'permission-groups.read' })
|
|
7
|
+
|
|
8
|
+
type PermissionGroup = components['schemas']['PermissionGroupResource']
|
|
9
|
+
|
|
10
|
+
const { t } = useI18n()
|
|
11
|
+
|
|
12
|
+
const columns = columnsFromMeta<PermissionGroup>(permissionGroupMeta, t, {
|
|
13
|
+
pick: ['name', 'sort_position', 'permissions'],
|
|
14
|
+
overrides: {
|
|
15
|
+
sort_position: { label: t('motor-admin.permissions.position'), sortable: true }
|
|
16
|
+
},
|
|
17
|
+
translationPrefix: 'motor-admin.permissions'
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
columns.push(createdAtColumn(t))
|
|
21
|
+
|
|
22
|
+
const fetchPermissionGroups = useGridFetch<PermissionGroup>('/api/v2/permission-groups')
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template>
|
|
26
|
+
<GridPage
|
|
27
|
+
:title="t('motor-admin.permissions.title')"
|
|
28
|
+
:subtitle="t('motor-admin.permissions.subtitle')"
|
|
29
|
+
add-route="/motor-admin/permission-groups/create"
|
|
30
|
+
:add-label="t('motor-admin.permissions.add')"
|
|
31
|
+
write-permission="permission-groups.write"
|
|
32
|
+
>
|
|
33
|
+
<GridBase
|
|
34
|
+
id="permission-groups-grid"
|
|
35
|
+
:fetch="fetchPermissionGroups"
|
|
36
|
+
:columns="columns"
|
|
37
|
+
base-path="/motor-admin/permission-groups"
|
|
38
|
+
:row-click-to="(row: any) => `/motor-admin/permission-groups/${row.id}/edit`"
|
|
39
|
+
write-permission="permission-groups.write"
|
|
40
|
+
delete-permission="permission-groups.delete"
|
|
41
|
+
/>
|
|
42
|
+
</GridPage>
|
|
43
|
+
</template>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { roleFormMeta } from '../../../../types/generated/form-meta'
|
|
3
|
+
import { roleFormConfig, roleSelectOptionConfigs } from '@motor-cms/ui-core/app/types/config/role'
|
|
4
|
+
|
|
5
|
+
definePageMeta({ layout: 'default', permission: 'roles.write' })
|
|
6
|
+
|
|
7
|
+
const route = useRoute()
|
|
8
|
+
const { t } = useI18n()
|
|
9
|
+
const { fields, schema, groups, state, loading, fetching, fetchError, formRef, selectOptions, selectOptionsLoading, onSubmit, onSaveAndContinue, onSaveAndNew, deleteRecord, deleting } = await useEntityForm({
|
|
10
|
+
apiEndpoint: '/api/v2/roles',
|
|
11
|
+
routePrefix: '/motor-admin/roles',
|
|
12
|
+
translationPrefix: 'motor-admin.roles',
|
|
13
|
+
formMeta: roleFormMeta,
|
|
14
|
+
formConfig: roleFormConfig,
|
|
15
|
+
mode: 'edit',
|
|
16
|
+
id: route.params.id as string,
|
|
17
|
+
selectOptionConfigs: roleSelectOptionConfigs
|
|
18
|
+
})
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<template>
|
|
22
|
+
<FormPage
|
|
23
|
+
:title="t('motor-admin.roles.edit_title')"
|
|
24
|
+
back-route="/motor-admin/roles"
|
|
25
|
+
:loading="fetching"
|
|
26
|
+
:error="fetchError"
|
|
27
|
+
>
|
|
28
|
+
<FormBase
|
|
29
|
+
ref="formRef"
|
|
30
|
+
v-model:state="state"
|
|
31
|
+
:fields="fields"
|
|
32
|
+
:schema="schema"
|
|
33
|
+
:groups="groups"
|
|
34
|
+
:select-options="selectOptions"
|
|
35
|
+
:select-options-loading="selectOptionsLoading"
|
|
36
|
+
:loading="loading"
|
|
37
|
+
:delete-record="deleteRecord"
|
|
38
|
+
:deleting="deleting"
|
|
39
|
+
cancel-route="/motor-admin/roles"
|
|
40
|
+
show-save-and-continue
|
|
41
|
+
show-save-and-new
|
|
42
|
+
@submit="onSubmit"
|
|
43
|
+
@save-and-continue="onSaveAndContinue"
|
|
44
|
+
@save-and-new="onSaveAndNew"
|
|
45
|
+
/>
|
|
46
|
+
</FormPage>
|
|
47
|
+
</template>
|