i18n-dashboard 0.13.0 → 0.13.2
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 +3 -0
- package/package.json +1 -1
- package/src/components/GitRepoManager.vue +4 -4
- package/src/components/ScanModal.vue +3 -3
- package/src/components/TranslationRow.vue +1 -1
- package/src/components/dashboard/WidgetConfigModal.vue +6 -5
- package/src/components/dashboard/WidgetGrid.vue +2 -2
- package/src/components/dashboard/WidgetPicker.vue +6 -5
- package/src/components/dashboard/widgets/ActivityWidget.vue +4 -3
- package/src/components/dashboard/widgets/LanguagesCoverageWidget.vue +4 -3
- package/src/components/dashboard/widgets/ProjectsWidget.vue +2 -2
- package/src/components/dashboard/widgets/ReviewWidget.vue +5 -4
- package/src/components/dashboard/widgets/StatWidget.vue +5 -4
- package/src/composables/useAuth.ts +2 -10
- package/src/composables/useDashboard.ts +7 -7
- package/src/composables/useKeys.ts +3 -3
- package/src/composables/useLanguages.ts +6 -6
- package/src/composables/useProfile.ts +1 -1
- package/src/composables/useProject.ts +8 -23
- package/src/composables/useReview.ts +5 -12
- package/src/composables/useSettings.ts +2 -2
- package/src/composables/useStats.ts +2 -2
- package/src/composables/useUsers.ts +3 -3
- package/src/composables/useWidgetData.ts +2 -2
- package/src/consts/commons.const.ts +20 -5
- package/src/consts/dashboard.const.ts +6 -5
- package/src/consts/languages.const.ts +2 -2
- package/src/consts/translation-job.const.ts +2 -0
- package/src/enums/translation-job.enum.ts +5 -0
- package/src/interfaces/auth.interface.ts +8 -0
- package/src/interfaces/commons.interface.ts +9 -9
- package/src/interfaces/dashboard.interface.ts +12 -0
- package/src/interfaces/job.interface.ts +1 -1
- package/src/interfaces/key.interface.ts +8 -8
- package/src/interfaces/languages.interface.ts +3 -3
- package/src/{server/interfaces → interfaces}/profile.interface.ts +9 -9
- package/src/{server/interfaces → interfaces}/project-config.interface.ts +1 -1
- package/src/interfaces/project-snapshot.interface.ts +26 -0
- package/src/interfaces/project.interface.ts +18 -3
- package/src/interfaces/review.interface.ts +7 -0
- package/src/interfaces/scan.interface.ts +2 -2
- package/src/{server/interfaces → interfaces}/scanner.interface.ts +4 -4
- package/src/interfaces/settings.interface.ts +1 -1
- package/src/interfaces/stat.interface.ts +5 -5
- package/src/{server/interfaces → interfaces}/translation-job.interface.ts +3 -3
- package/src/interfaces/translation.interface.ts +2 -2
- package/src/interfaces/user.interface.ts +3 -3
- package/src/pages/projects/[id]/review.vue +1 -1
- package/src/pages/projects/[id]/translations/index.vue +1 -1
- package/src/pages/projects/[id]/users.vue +4 -4
- package/src/server/api/auth/login.post.ts +1 -1
- package/src/server/api/auth/logout.post.ts +1 -1
- package/src/server/api/auth/me.get.ts +1 -1
- package/src/server/api/auth/me.put.ts +1 -1
- package/src/server/api/auth/password.put.ts +1 -1
- package/src/server/api/auth/refresh.post.ts +1 -1
- package/src/server/api/auth/status.get.ts +1 -1
- package/src/server/api/config.get.ts +1 -1
- package/src/server/api/dashboard/layout.get.ts +1 -1
- package/src/server/api/dashboard/layout.post.ts +1 -1
- package/src/server/api/export.get.ts +1 -1
- package/src/server/api/languages/index.post.ts +1 -1
- package/src/server/api/onboarding.post.ts +1 -1
- package/src/server/api/profile.get.ts +2 -2
- package/src/server/api/project-snapshot.post.ts +2 -28
- package/src/server/api/projects/detect.post.ts +1 -1
- package/src/server/api/scan.post.ts +1 -1
- package/src/server/api/setup.post.ts +1 -1
- package/src/server/api/stats/global.get.ts +1 -1
- package/src/server/api/translations/bulk-status.post.ts +1 -1
- package/src/server/api/translations/index.post.ts +1 -1
- package/src/server/api/translations/job/[id].get.ts +1 -1
- package/src/server/api/translations/status.post.ts +1 -1
- package/src/server/api/translations/translate-all.post.ts +1 -1
- package/src/server/api/users/[id]/profile.get.ts +3 -3
- package/src/server/api/users/[id]/roles.put.ts +1 -1
- package/src/server/api/users/[id].delete.ts +1 -1
- package/src/server/api/users/[id].put.ts +1 -1
- package/src/server/api/users/index.get.ts +1 -1
- package/src/server/api/users/index.post.ts +2 -2
- package/src/server/consts/commons.const.ts +5 -20
- package/src/server/db/index.ts +4 -4
- package/src/server/middleware/auth.ts +2 -2
- package/src/server/routes/locale/[lang].get.ts +1 -1
- package/src/server/utils/auth.util.ts +10 -10
- package/src/server/utils/auto-translate.util.ts +1 -1
- package/src/server/utils/project-config.util.ts +3 -3
- package/src/server/utils/{scanner.uti.ts → scanner.util.ts} +13 -13
- package/src/server/utils/translation-job.util.ts +14 -13
- package/src/services/auth.service.ts +10 -10
- package/src/services/base.service.ts +13 -13
- package/src/services/job.service.ts +6 -6
- package/src/services/key.service.ts +10 -10
- package/src/services/language.service.ts +8 -8
- package/src/services/profile.service.ts +8 -8
- package/src/services/project.service.ts +11 -11
- package/src/services/scan.service.ts +8 -8
- package/src/services/settings.service.ts +5 -5
- package/src/services/stats.service.ts +6 -6
- package/src/services/translation.service.ts +6 -6
- package/src/services/user.service.ts +10 -10
- package/src/types/auth.type.ts +3 -0
- package/src/types/commons.type.ts +1 -1
- package/src/types/dashboard.type.ts +5 -15
- package/src/consts/commons.const.js +0 -6
- package/src/server/consts/translation-job.const.ts +0 -8
- package/src/server/types/auth.type.ts +0 -3
- /package/src/{server/consts → consts}/auto-translate.const.ts +0 -0
- /package/src/{server/consts → consts}/scanner.const.ts +0 -0
- /package/src/{server/enums → enums}/auth.enum.ts +0 -0
- /package/src/{server/enums → enums}/translation.enum.ts +0 -0
- /package/src/{server/utils → utils}/lang-api.util.ts +0 -0
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -15,19 +15,19 @@
|
|
|
15
15
|
</template>
|
|
16
16
|
|
|
17
17
|
<script setup lang="ts">
|
|
18
|
-
import type {
|
|
18
|
+
import type { IGitRepo } from '~/interfaces/project.interface'
|
|
19
19
|
|
|
20
20
|
const { t } = useT()
|
|
21
21
|
|
|
22
22
|
const props = defineProps<{
|
|
23
|
-
modelValue:
|
|
23
|
+
modelValue: IGitRepo | null | undefined
|
|
24
24
|
}>()
|
|
25
25
|
|
|
26
26
|
const emit = defineEmits<{
|
|
27
|
-
'update:modelValue': [value:
|
|
27
|
+
'update:modelValue': [value: IGitRepo | null]
|
|
28
28
|
}>()
|
|
29
29
|
|
|
30
|
-
const local = reactive<
|
|
30
|
+
const local = reactive<IGitRepo>({ url: '', branch: '', token: '' })
|
|
31
31
|
|
|
32
32
|
watch(() => props.modelValue, (val) => {
|
|
33
33
|
local.url = val?.url ?? ''
|
|
@@ -96,13 +96,13 @@
|
|
|
96
96
|
</template>
|
|
97
97
|
|
|
98
98
|
<script setup lang="ts">
|
|
99
|
-
import type {
|
|
99
|
+
import type { IGitRepo } from '~/interfaces/project.interface'
|
|
100
100
|
|
|
101
101
|
const { t } = useT()
|
|
102
102
|
|
|
103
103
|
const props = defineProps<{
|
|
104
104
|
projectId: number
|
|
105
|
-
project?: { languages?: { code: string; name: string }[]; root_path?: string; git_repo?:
|
|
105
|
+
project?: { languages?: { code: string; name: string }[]; root_path?: string; git_repo?: IGitRepo | null }
|
|
106
106
|
}>()
|
|
107
107
|
|
|
108
108
|
const emit = defineEmits<{ done: [] }>()
|
|
@@ -111,7 +111,7 @@ const open = defineModel<boolean>('open', { default: false })
|
|
|
111
111
|
|
|
112
112
|
const mode = ref<'local' | 'git'>('local')
|
|
113
113
|
const localPath = ref(props.project?.root_path ?? '')
|
|
114
|
-
const gitRepo = ref<
|
|
114
|
+
const gitRepo = ref<IGitRepo | null>(null)
|
|
115
115
|
const saveRepo = ref(false)
|
|
116
116
|
const loading = ref(false)
|
|
117
117
|
const result = ref<any>(null)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import type { PropType } from 'vue'
|
|
3
|
-
import type {
|
|
3
|
+
import type { TDataSourceType } from '~/types/dashboard.type'
|
|
4
|
+
import type { IWidgetConfig, IWidgetDataSource } from '~/interfaces/dashboard.interface'
|
|
4
5
|
import { WIDGET_REGISTRY } from '~/consts/dashboard.const'
|
|
5
6
|
|
|
6
7
|
const props = defineProps({
|
|
@@ -9,7 +10,7 @@ const props = defineProps({
|
|
|
9
10
|
required: true,
|
|
10
11
|
},
|
|
11
12
|
widget: {
|
|
12
|
-
type: Object as PropType<
|
|
13
|
+
type: Object as PropType<IWidgetConfig | null>,
|
|
13
14
|
default: null,
|
|
14
15
|
},
|
|
15
16
|
index: {
|
|
@@ -20,13 +21,13 @@ const props = defineProps({
|
|
|
20
21
|
|
|
21
22
|
const emit = defineEmits<{
|
|
22
23
|
(e: 'update:open', value: boolean): void
|
|
23
|
-
(e: 'save', value: { dataSource:
|
|
24
|
+
(e: 'save', value: { dataSource: IWidgetDataSource | undefined; title: string | undefined }): void
|
|
24
25
|
}>()
|
|
25
26
|
|
|
26
27
|
const { t } = useT()
|
|
27
28
|
const { visibleProjects } = useProject()
|
|
28
29
|
|
|
29
|
-
const draftSource = ref<
|
|
30
|
+
const draftSource = ref<TDataSourceType>('global')
|
|
30
31
|
const draftProjectId = ref<number | undefined>()
|
|
31
32
|
const draftTitle = ref('')
|
|
32
33
|
|
|
@@ -53,7 +54,7 @@ const hasDataSource = computed(() => {
|
|
|
53
54
|
})
|
|
54
55
|
|
|
55
56
|
function save() {
|
|
56
|
-
const dataSource:
|
|
57
|
+
const dataSource: IWidgetDataSource = draftSource.value === 'project'
|
|
57
58
|
? { type: 'project', projectId: draftProjectId.value }
|
|
58
59
|
: { type: 'global' }
|
|
59
60
|
emit('save', { dataSource, title: draftTitle.value || undefined })
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import type {
|
|
2
|
+
import type { TWidgetType } from '~/types/dashboard.type'
|
|
3
3
|
import { WIDGET_REGISTRY, WIDGET_SIZE_CLASSES } from '~/consts/dashboard.const'
|
|
4
4
|
|
|
5
5
|
const { t } = useT()
|
|
@@ -30,7 +30,7 @@ function sizeClass(size: string) {
|
|
|
30
30
|
return WIDGET_SIZE_CLASSES[size as keyof typeof WIDGET_SIZE_CLASSES] ?? 'col-span-1 row-span-1'
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
function widgetComponent(type:
|
|
33
|
+
function widgetComponent(type: TWidgetType) {
|
|
34
34
|
switch (type) {
|
|
35
35
|
case 'stat-keys':
|
|
36
36
|
case 'stat-coverage':
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import type {
|
|
2
|
+
import type { TWidgetSize } from '~/types/dashboard.type'
|
|
3
|
+
import type { IWidgetConfig } from '~/interfaces/dashboard.interface'
|
|
3
4
|
import { WIDGET_REGISTRY } from '~/consts/dashboard.const'
|
|
4
5
|
|
|
5
6
|
const { t } = useT()
|
|
@@ -10,7 +11,7 @@ const props = defineProps<{
|
|
|
10
11
|
|
|
11
12
|
const emit = defineEmits<{
|
|
12
13
|
'update:modelValue': [value: boolean]
|
|
13
|
-
'add': [widget:
|
|
14
|
+
'add': [widget: IWidgetConfig]
|
|
14
15
|
}>()
|
|
15
16
|
|
|
16
17
|
const open = computed({
|
|
@@ -18,16 +19,16 @@ const open = computed({
|
|
|
18
19
|
set: (v) => emit('update:modelValue', v),
|
|
19
20
|
})
|
|
20
21
|
|
|
21
|
-
const selectedSizes = ref<Record<string,
|
|
22
|
+
const selectedSizes = ref<Record<string, TWidgetSize>>({})
|
|
22
23
|
|
|
23
|
-
function getSelectedSize(type: string):
|
|
24
|
+
function getSelectedSize(type: string): TWidgetSize {
|
|
24
25
|
return selectedSizes.value[type] ?? WIDGET_REGISTRY[type as keyof typeof WIDGET_REGISTRY].defaultSize
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
function addWidget(type: string) {
|
|
28
29
|
const size = getSelectedSize(type)
|
|
29
30
|
const id = Date.now().toString(36)
|
|
30
|
-
emit('add', { id, type: type as
|
|
31
|
+
emit('add', { id, type: type as IWidgetConfig['type'], size })
|
|
31
32
|
open.value = false
|
|
32
33
|
}
|
|
33
34
|
</script>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import type { PropType } from 'vue'
|
|
3
|
-
import type {
|
|
3
|
+
import type { TWidgetSize } from '~/types/dashboard.type'
|
|
4
|
+
import type { IWidgetDataSource } from '~/interfaces/dashboard.interface'
|
|
4
5
|
|
|
5
6
|
const props = defineProps({
|
|
6
7
|
id: {
|
|
@@ -8,7 +9,7 @@ const props = defineProps({
|
|
|
8
9
|
required: true,
|
|
9
10
|
},
|
|
10
11
|
size: {
|
|
11
|
-
type: String as PropType<
|
|
12
|
+
type: String as PropType<TWidgetSize>,
|
|
12
13
|
required: true,
|
|
13
14
|
},
|
|
14
15
|
editing: {
|
|
@@ -16,7 +17,7 @@ const props = defineProps({
|
|
|
16
17
|
required: true,
|
|
17
18
|
},
|
|
18
19
|
dataSource: {
|
|
19
|
-
type: Object as PropType<
|
|
20
|
+
type: Object as PropType<IWidgetDataSource | undefined>,
|
|
20
21
|
default: undefined,
|
|
21
22
|
},
|
|
22
23
|
title: {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import type { PropType } from 'vue'
|
|
3
|
-
import type {
|
|
3
|
+
import type { TWidgetSize } from '~/types/dashboard.type'
|
|
4
|
+
import type { IWidgetDataSource } from '~/interfaces/dashboard.interface'
|
|
4
5
|
|
|
5
6
|
const props = defineProps({
|
|
6
7
|
id: {
|
|
@@ -8,7 +9,7 @@ const props = defineProps({
|
|
|
8
9
|
required: true,
|
|
9
10
|
},
|
|
10
11
|
size: {
|
|
11
|
-
type: String as PropType<
|
|
12
|
+
type: String as PropType<TWidgetSize>,
|
|
12
13
|
required: true,
|
|
13
14
|
},
|
|
14
15
|
editing: {
|
|
@@ -16,7 +17,7 @@ const props = defineProps({
|
|
|
16
17
|
required: true,
|
|
17
18
|
},
|
|
18
19
|
dataSource: {
|
|
19
|
-
type: Object as PropType<
|
|
20
|
+
type: Object as PropType<IWidgetDataSource | undefined>,
|
|
20
21
|
default: undefined,
|
|
21
22
|
},
|
|
22
23
|
title: {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import type { PropType } from 'vue'
|
|
3
|
-
import type {
|
|
4
|
-
import {
|
|
3
|
+
import type { TWidgetSize } from '~/types/dashboard.type'
|
|
4
|
+
import type { IWidgetDataSource } from '~/interfaces/dashboard.interface'
|
|
5
|
+
import { TRANSLATION_STATUS } from '~/enums/translation.enum'
|
|
5
6
|
|
|
6
7
|
const props = defineProps({
|
|
7
8
|
id: {
|
|
@@ -9,7 +10,7 @@ const props = defineProps({
|
|
|
9
10
|
required: true,
|
|
10
11
|
},
|
|
11
12
|
size: {
|
|
12
|
-
type: String as PropType<
|
|
13
|
+
type: String as PropType<TWidgetSize>,
|
|
13
14
|
required: true,
|
|
14
15
|
},
|
|
15
16
|
editing: {
|
|
@@ -17,7 +18,7 @@ const props = defineProps({
|
|
|
17
18
|
required: true,
|
|
18
19
|
},
|
|
19
20
|
dataSource: {
|
|
20
|
-
type: Object as PropType<
|
|
21
|
+
type: Object as PropType<IWidgetDataSource | undefined>,
|
|
21
22
|
default: undefined,
|
|
22
23
|
},
|
|
23
24
|
title: {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import type { PropType } from 'vue'
|
|
3
|
-
import type {
|
|
3
|
+
import type { TWidgetType, TWidgetSize } from '~/types/dashboard.type'
|
|
4
|
+
import type { IWidgetDataSource } from '~/interfaces/dashboard.interface'
|
|
4
5
|
|
|
5
6
|
const props = defineProps({
|
|
6
7
|
id: {
|
|
@@ -8,11 +9,11 @@ const props = defineProps({
|
|
|
8
9
|
required: true,
|
|
9
10
|
},
|
|
10
11
|
type: {
|
|
11
|
-
type: String as PropType<
|
|
12
|
+
type: String as PropType<TWidgetType>,
|
|
12
13
|
required: true,
|
|
13
14
|
},
|
|
14
15
|
size: {
|
|
15
|
-
type: String as PropType<
|
|
16
|
+
type: String as PropType<TWidgetSize>,
|
|
16
17
|
required: true,
|
|
17
18
|
},
|
|
18
19
|
editing: {
|
|
@@ -20,7 +21,7 @@ const props = defineProps({
|
|
|
20
21
|
required: true,
|
|
21
22
|
},
|
|
22
23
|
dataSource: {
|
|
23
|
-
type: Object as PropType<
|
|
24
|
+
type: Object as PropType<IWidgetDataSource | undefined>,
|
|
24
25
|
default: undefined,
|
|
25
26
|
},
|
|
26
27
|
title: {
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import { authService } from '../services/auth.service'
|
|
2
|
+
import type { IAuthUser } from '../interfaces/auth.interface'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
id: number
|
|
5
|
-
email: string
|
|
6
|
-
name: string
|
|
7
|
-
is_super_admin: boolean
|
|
8
|
-
is_active: boolean
|
|
9
|
-
roles: Array<{ role: string; project_id: number | null; project_name?: string }>
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const _currentUser = ref<AuthUser | null>(null)
|
|
4
|
+
const _currentUser = ref<IAuthUser | null>(null)
|
|
13
5
|
|
|
14
6
|
export function useAuth() {
|
|
15
7
|
const currentUser = _currentUser
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { IWidgetConfig, IWidgetDataSource } from '../interfaces/dashboard.interface'
|
|
2
|
+
import type { TWidgetSize } from '../types/dashboard.type'
|
|
3
3
|
import { DEFAULT_LAYOUT } from '../consts/dashboard.const'
|
|
4
4
|
|
|
5
5
|
export function useDashboard() {
|
|
6
6
|
const { data, refresh } = useAsyncData('dashboard-layout', () => $fetch('/api/dashboard/layout'), { server: false })
|
|
7
|
-
const layout = computed<
|
|
7
|
+
const layout = computed<IWidgetConfig[]>(() => (data.value as IWidgetConfig[]) ?? DEFAULT_LAYOUT)
|
|
8
8
|
|
|
9
9
|
const editing = ref(false)
|
|
10
|
-
const localLayout = ref<
|
|
10
|
+
const localLayout = ref<IWidgetConfig[]>([])
|
|
11
11
|
|
|
12
12
|
function startEditing() {
|
|
13
13
|
localLayout.value = [...layout.value]
|
|
@@ -38,15 +38,15 @@ export function useDashboard() {
|
|
|
38
38
|
localLayout.value.splice(index, 1)
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
function addWidget(widget:
|
|
41
|
+
function addWidget(widget: IWidgetConfig) {
|
|
42
42
|
localLayout.value.push(widget)
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
function resizeWidget(index: number, size:
|
|
45
|
+
function resizeWidget(index: number, size: TWidgetSize) {
|
|
46
46
|
localLayout.value[index].size = size
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
function updateWidgetConfig(index: number, patch: { dataSource?:
|
|
49
|
+
function updateWidgetConfig(index: number, patch: { dataSource?: IWidgetDataSource | undefined; title?: string | undefined }) {
|
|
50
50
|
if (index < 0 || index >= localLayout.value.length) return
|
|
51
51
|
localLayout.value[index] = { ...localLayout.value[index], ...patch }
|
|
52
52
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { keyService } from '../services/key.service'
|
|
2
2
|
import { translationService } from '../services/translation.service'
|
|
3
3
|
import { scanService } from '../services/scan.service'
|
|
4
|
-
import type {
|
|
4
|
+
import type { IKeysQuery, IKeysResponse } from '../interfaces/key.interface'
|
|
5
5
|
|
|
6
6
|
export function useKeys(options: {
|
|
7
|
-
queryParams?: Ref<
|
|
7
|
+
queryParams?: Ref<IKeysQuery>
|
|
8
8
|
id?: Ref<string | string[]>
|
|
9
9
|
} = {}) {
|
|
10
10
|
const toast = useToast()
|
|
@@ -14,7 +14,7 @@ export function useKeys(options: {
|
|
|
14
14
|
|
|
15
15
|
// ── List mode ─────────────────────────────────────────────────────────────
|
|
16
16
|
|
|
17
|
-
const data = ref<
|
|
17
|
+
const data = ref<IKeysResponse | null>(null)
|
|
18
18
|
const listPending = ref(false)
|
|
19
19
|
|
|
20
20
|
async function refresh() {
|
|
@@ -2,7 +2,7 @@ import { LANGUAGES } from '../consts/languages.const'
|
|
|
2
2
|
import { languageService } from '../services/language.service'
|
|
3
3
|
import { translationService } from '../services/translation.service'
|
|
4
4
|
import { jobService } from '../services/job.service'
|
|
5
|
-
import type {
|
|
5
|
+
import type { ILanguage, ILanguageItem, ICreateLanguagePayload } from '../interfaces/languages.interface'
|
|
6
6
|
|
|
7
7
|
// ── Static language lookup ───────────────────────────────────────────────────
|
|
8
8
|
|
|
@@ -25,7 +25,7 @@ export function useLanguages() {
|
|
|
25
25
|
)
|
|
26
26
|
})
|
|
27
27
|
|
|
28
|
-
function findLanguage(code: string):
|
|
28
|
+
function findLanguage(code: string): ILanguage | undefined {
|
|
29
29
|
// Exact match first, then fall back to base language (fr-CA → fr)
|
|
30
30
|
return LANGUAGES.find(l => l.code === code)
|
|
31
31
|
?? LANGUAGES.find(l => l.code === code.split('-')[0])
|
|
@@ -38,7 +38,7 @@ export function useLanguages() {
|
|
|
38
38
|
|
|
39
39
|
// ── Project languages (API) ──────────────────────────────────────────────
|
|
40
40
|
|
|
41
|
-
const data = ref<
|
|
41
|
+
const data = ref<ILanguageItem[]>([])
|
|
42
42
|
const pending = ref(false)
|
|
43
43
|
|
|
44
44
|
async function refresh() {
|
|
@@ -60,7 +60,7 @@ export function useLanguages() {
|
|
|
60
60
|
const projectLanguages = computed(() => data.value ?? [])
|
|
61
61
|
|
|
62
62
|
const adding = ref(false)
|
|
63
|
-
async function addLanguage(payload: Omit<
|
|
63
|
+
async function addLanguage(payload: Omit<ICreateLanguagePayload, 'project_id'>): Promise<void> {
|
|
64
64
|
if (!currentProject.value) return
|
|
65
65
|
adding.value = true
|
|
66
66
|
try {
|
|
@@ -88,7 +88,7 @@ export function useLanguages() {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
async function setDefault(lang:
|
|
91
|
+
async function setDefault(lang: ILanguageItem): Promise<void> {
|
|
92
92
|
if (!currentProject.value) return
|
|
93
93
|
try {
|
|
94
94
|
await languageService.setDefault(lang, currentProject.value.id)
|
|
@@ -97,7 +97,7 @@ export function useLanguages() {
|
|
|
97
97
|
catch {}
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
async function setFallback(lang:
|
|
100
|
+
async function setFallback(lang: ILanguageItem, fallbackCode: string | null): Promise<void> {
|
|
101
101
|
await $fetch(`/api/languages/${lang.id}`, {
|
|
102
102
|
method: 'PUT',
|
|
103
103
|
body: { fallback_code: fallbackCode },
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { profileService } from '../services/profile.service'
|
|
2
2
|
import { authService } from '../services/auth.service'
|
|
3
3
|
import { userService } from '../services/user.service'
|
|
4
|
-
import type { ProfilePeriod } from '
|
|
4
|
+
import type { ProfilePeriod } from '~/interfaces/profile.interface'
|
|
5
5
|
|
|
6
6
|
export function useProfile(userId?: MaybeRefOrGetter<number | string>) {
|
|
7
7
|
const toast = useToast()
|
|
@@ -1,28 +1,13 @@
|
|
|
1
1
|
import { projectService } from '~/services/project.service'
|
|
2
2
|
import { scanService } from '~/services/scan.service'
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
export interface Project {
|
|
6
|
-
id: number
|
|
7
|
-
name: string
|
|
8
|
-
root_path: string
|
|
9
|
-
source_url?: string
|
|
10
|
-
locales_path: string
|
|
11
|
-
key_separator: string
|
|
12
|
-
color: string
|
|
13
|
-
description?: string
|
|
14
|
-
key_count?: number
|
|
15
|
-
language_count?: number
|
|
16
|
-
is_system?: boolean
|
|
17
|
-
git_repo?: { name?: string; url: string; branch?: string; token?: string } | null
|
|
18
|
-
}
|
|
3
|
+
import type { IProject, IProjectPayload } from '~/interfaces/project.interface'
|
|
19
4
|
|
|
20
|
-
export function canScanProject(project:
|
|
5
|
+
export function canScanProject(project: IProject): boolean {
|
|
21
6
|
if (project.root_path && project.root_path !== '__DASHBOARD_UI__') return true
|
|
22
7
|
return !!project.git_repo?.url
|
|
23
8
|
}
|
|
24
9
|
|
|
25
|
-
export function canSyncProject(project:
|
|
10
|
+
export function canSyncProject(project: IProject): boolean {
|
|
26
11
|
if (project.root_path && project.root_path !== '__DASHBOARD_UI__') return true
|
|
27
12
|
return !!project.git_repo?.url
|
|
28
13
|
}
|
|
@@ -36,20 +21,20 @@ export function canSyncProject(project: Project): boolean {
|
|
|
36
21
|
export function useProject() {
|
|
37
22
|
const { currentUser } = useAuth()
|
|
38
23
|
|
|
39
|
-
const { data: projectsData, pending, refresh: fetchProjects } = useAsyncData<
|
|
24
|
+
const { data: projectsData, pending, refresh: fetchProjects } = useAsyncData<IProject[]>(
|
|
40
25
|
'all-projects',
|
|
41
26
|
() => projectService.getAll(),
|
|
42
27
|
{ default: () => [], server: false },
|
|
43
28
|
)
|
|
44
29
|
|
|
45
|
-
const projects = computed(() => (projectsData.value ?? []) as
|
|
30
|
+
const projects = computed(() => (projectsData.value ?? []) as IProject[])
|
|
46
31
|
|
|
47
32
|
// Not route-dependent — safe to watch from anywhere (including layout onMount)
|
|
48
33
|
const systemProject = computed(() => projects.value.find(p => p.is_system) ?? null)
|
|
49
34
|
|
|
50
35
|
// Route-dependent: only returns a value when inside a /projects/[id]/* page
|
|
51
36
|
const route = useRoute()
|
|
52
|
-
const currentProject = computed(():
|
|
37
|
+
const currentProject = computed((): IProject | null => {
|
|
53
38
|
const paramId = route.params.id
|
|
54
39
|
if (!paramId) return null
|
|
55
40
|
const id = Number(Array.isArray(paramId) ? paramId[0] : paramId)
|
|
@@ -73,7 +58,7 @@ export function useProject() {
|
|
|
73
58
|
const router = useRouter()
|
|
74
59
|
|
|
75
60
|
const saving = ref(false)
|
|
76
|
-
async function createProject(payload:
|
|
61
|
+
async function createProject(payload: IProjectPayload): Promise<any> {
|
|
77
62
|
saving.value = true
|
|
78
63
|
try {
|
|
79
64
|
const project = await projectService.create(payload)
|
|
@@ -89,7 +74,7 @@ export function useProject() {
|
|
|
89
74
|
}
|
|
90
75
|
}
|
|
91
76
|
|
|
92
|
-
async function updateProject(id: number, payload: Partial<
|
|
77
|
+
async function updateProject(id: number, payload: Partial<IProjectPayload>): Promise<boolean> {
|
|
93
78
|
saving.value = true
|
|
94
79
|
try {
|
|
95
80
|
await projectService.update(id, payload)
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
import { keyService } from '../services/key.service'
|
|
2
2
|
import { translationService } from '../services/translation.service'
|
|
3
|
-
import { TRANSLATION_STATUS } from '
|
|
4
|
-
|
|
5
|
-
export interface ReviewItem {
|
|
6
|
-
id: number
|
|
7
|
-
key: string
|
|
8
|
-
key_description?: string
|
|
9
|
-
language_code: string
|
|
10
|
-
value: string
|
|
11
|
-
}
|
|
3
|
+
import { TRANSLATION_STATUS } from '~/enums/translation.enum'
|
|
4
|
+
import type { IReviewItem } from '../interfaces/review.interface'
|
|
12
5
|
|
|
13
6
|
export function useReview() {
|
|
14
7
|
const toast = useToast()
|
|
@@ -34,9 +27,9 @@ export function useReview() {
|
|
|
34
27
|
|
|
35
28
|
watch(() => currentProject.value?.id, refresh, { immediate: true })
|
|
36
29
|
|
|
37
|
-
const reviewItems = computed<
|
|
30
|
+
const reviewItems = computed<IReviewItem[]>(() => {
|
|
38
31
|
const keys = data.value?.data ?? []
|
|
39
|
-
const result:
|
|
32
|
+
const result: IReviewItem[] = []
|
|
40
33
|
for (const k of keys) {
|
|
41
34
|
for (const [lang, tr] of Object.entries(k.translations as Record<string, any>)) {
|
|
42
35
|
if (tr?.status === TRANSLATION_STATUS.DRAFT && tr?.value) {
|
|
@@ -50,7 +43,7 @@ export function useReview() {
|
|
|
50
43
|
const processingId = ref<number | null>(null)
|
|
51
44
|
const processingAction = ref('')
|
|
52
45
|
|
|
53
|
-
async function setStatus(item:
|
|
46
|
+
async function setStatus(item: IReviewItem, status: TRANSLATION_STATUS): Promise<void> {
|
|
54
47
|
processingId.value = item.id
|
|
55
48
|
processingAction.value = status
|
|
56
49
|
try {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { settingsService } from '../services/settings.service'
|
|
2
|
-
import type {
|
|
2
|
+
import type { ISettingsPayload } from '../interfaces/settings.interface'
|
|
3
3
|
|
|
4
4
|
export function useSettings() {
|
|
5
5
|
const toast = useToast()
|
|
@@ -26,7 +26,7 @@ export function useSettings() {
|
|
|
26
26
|
const settings = computed(() => data.value ?? {})
|
|
27
27
|
|
|
28
28
|
const saving = ref(false)
|
|
29
|
-
async function saveSettings(payload:
|
|
29
|
+
async function saveSettings(payload: ISettingsPayload): Promise<void> {
|
|
30
30
|
saving.value = true
|
|
31
31
|
try {
|
|
32
32
|
await settingsService.saveSettings(payload)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { statsService } from '../services/stats.service'
|
|
2
|
-
import type {
|
|
2
|
+
import type { IStatsResponse } from '../interfaces/stat.interface'
|
|
3
3
|
|
|
4
4
|
export function useStats() {
|
|
5
5
|
const { currentProject } = useProject()
|
|
6
6
|
|
|
7
|
-
const { data, pending, refresh } = useAsyncData<
|
|
7
|
+
const { data, pending, refresh } = useAsyncData<IStatsResponse | null>(
|
|
8
8
|
'project-stats',
|
|
9
9
|
() => statsService.getStats(currentProject.value?.id),
|
|
10
10
|
{ watch: [() => currentProject.value?.id] },
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { userService } from '../services/user.service'
|
|
2
|
-
import type {
|
|
2
|
+
import type { ICreateUserPayload, IRoleEntry } from '../interfaces/user.interface'
|
|
3
3
|
|
|
4
4
|
export function useUsers(scope: 'project' | 'global' = 'project') {
|
|
5
5
|
const toast = useToast()
|
|
@@ -37,7 +37,7 @@ export function useUsers(scope: 'project' | 'global' = 'project') {
|
|
|
37
37
|
// ── Mutations ──────────────────────────────────────────────────────────────
|
|
38
38
|
|
|
39
39
|
const saving = ref(false)
|
|
40
|
-
async function createUser(payload:
|
|
40
|
+
async function createUser(payload: ICreateUserPayload): Promise<string | null> {
|
|
41
41
|
saving.value = true
|
|
42
42
|
try {
|
|
43
43
|
const result = await userService.create(payload)
|
|
@@ -56,7 +56,7 @@ export function useUsers(scope: 'project' | 'global' = 'project') {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
const rolesSaving = ref(false)
|
|
59
|
-
async function updateRoles(userId: number, roles:
|
|
59
|
+
async function updateRoles(userId: number, roles: IRoleEntry[]): Promise<boolean> {
|
|
60
60
|
rolesSaving.value = true
|
|
61
61
|
try {
|
|
62
62
|
await userService.updateRoles(userId, roles)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Ref } from 'vue'
|
|
2
|
-
import type {
|
|
2
|
+
import type { IWidgetDataSource } from '~/interfaces/dashboard.interface'
|
|
3
3
|
|
|
4
|
-
export function useWidgetData(widgetId: string, dataSource: Ref<
|
|
4
|
+
export function useWidgetData(widgetId: string, dataSource: Ref<IWidgetDataSource | undefined>) {
|
|
5
5
|
const { currentProject, projects } = useProject()
|
|
6
6
|
|
|
7
7
|
const effectiveSource = computed(() => dataSource.value ?? { type: 'global' as const })
|
|
@@ -1,6 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export const PUBLIC_ROUTES = [
|
|
2
|
+
'/api/auth/login',
|
|
3
|
+
'/api/auth/logout',
|
|
4
|
+
'/api/auth/me',
|
|
5
|
+
'/api/auth/refresh',
|
|
6
|
+
'/api/auth/status',
|
|
7
|
+
'/api/setup',
|
|
8
|
+
'/api/ui-locale',
|
|
9
|
+
'/api/config',
|
|
10
|
+
// '/api/db-config' is intentionally NOT public — it can reconfigure and
|
|
11
|
+
// reset the entire database. It is accessible only during the onboarding
|
|
12
|
+
// wizard (before any user exists) via the auth middleware's setup-mode
|
|
13
|
+
// bypass, and requires super_admin authentication at all other times.
|
|
14
|
+
]
|
|
3
15
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
16
|
+
// Routes accessible without authentication only while onboarding is incomplete
|
|
17
|
+
// (no users in the database yet). Once a super admin exists, these routes
|
|
18
|
+
// require a valid session.
|
|
19
|
+
export const SETUP_ONLY_ROUTES = [
|
|
20
|
+
'/api/db-config',
|
|
21
|
+
]
|