@hostlink/nuxt-light 1.64.3 → 1.66.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.
Files changed (30) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +5 -0
  3. package/dist/runtime/components/L/CustomField/Add.vue +6 -1
  4. package/dist/runtime/components/L/Database/create-table-dialog.vue +34 -26
  5. package/dist/runtime/components/L/DocumentViewer.d.vue.ts +50 -0
  6. package/dist/runtime/components/L/DocumentViewer.vue +154 -0
  7. package/dist/runtime/components/L/DocumentViewer.vue.d.ts +50 -0
  8. package/dist/runtime/components/L/DocumentViewerDialog.d.vue.ts +65 -0
  9. package/dist/runtime/components/L/DocumentViewerDialog.vue +67 -0
  10. package/dist/runtime/components/L/DocumentViewerDialog.vue.d.ts +65 -0
  11. package/dist/runtime/components/l-customizer.d.vue.ts +19 -3
  12. package/dist/runtime/components/l-customizer.vue.d.ts +19 -3
  13. package/dist/runtime/components/l-file-manager-labels.d.vue.ts +5 -1
  14. package/dist/runtime/components/l-file-manager-labels.vue.d.ts +5 -1
  15. package/dist/runtime/components/l-file-manager-preview.vue +23 -22
  16. package/dist/runtime/components/l-file-manager.vue +14 -26
  17. package/dist/runtime/components/l-form.vue +16 -10
  18. package/dist/runtime/components/l-repeater.d.vue.ts +1 -1
  19. package/dist/runtime/components/l-repeater.vue.d.ts +1 -1
  20. package/dist/runtime/composables/showDocumentDialog.d.ts +9 -0
  21. package/dist/runtime/composables/showDocumentDialog.js +15 -0
  22. package/dist/runtime/pages/CustomField/index.vue +5 -5
  23. package/dist/runtime/pages/System/database/table.vue +49 -62
  24. package/dist/runtime/pages/System/setting.vue +2 -2
  25. package/dist/runtime/pages/Translate/index.vue +178 -62
  26. package/dist/runtime/pages/User/createAccessToken.d.vue.ts +3 -0
  27. package/dist/runtime/pages/User/createAccessToken.vue +63 -0
  28. package/dist/runtime/pages/User/createAccessToken.vue.d.ts +3 -0
  29. package/dist/runtime/pages/User/profile.vue +1 -0
  30. package/package.json +4 -4
@@ -1,6 +1,10 @@
1
1
  declare const _default: typeof __VLS_export;
2
2
  export default _default;
3
- declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
3
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
4
+ "update:modelValue": (...args: any[]) => void;
5
+ }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
6
+ "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
7
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
4
8
  type __VLS_ModelProps = {
5
9
  modelValue?: string | undefined;
6
10
  };
@@ -1,8 +1,7 @@
1
1
  <script setup>
2
2
  import { format, useQuasar, date } from "quasar";
3
3
  import { computed } from "vue";
4
- import { getApiClient, query } from "@hostlink/light";
5
- const api = getApiClient();
4
+ import { query } from "@hostlink/light";
6
5
  const { humanStorageSize } = format;
7
6
  const quasar = useQuasar();
8
7
  const props = defineProps({
@@ -60,27 +59,29 @@ const isVideo = computed(() => {
60
59
  </script>
61
60
 
62
61
  <template>
63
- <q-img :src="file.publicUrl" v-if="isImage"></q-img>
64
- <q-video :src="file.publicUrl" v-else-if="isVideo"></q-video>
62
+ <div>
63
+ <q-img :src="file.publicUrl" v-if="isImage"></q-img>
64
+ <q-video :src="file.publicUrl" v-else-if="isVideo"></q-video>
65
65
 
66
- <q-list dense>
67
- <l-item label="Name">{{ file.name }}</l-item>
68
- <l-item label="Size">{{ size }} ({{ file.size }})</l-item>
69
- <l-item label="Location">{{ file.path }}</l-item>
70
- <l-item label="Last modified">{{ lastModifiedHuman }}</l-item>
71
- <l-item label="MIME type">{{ file.mimeType }}</l-item>
66
+ <q-list dense>
67
+ <l-item label="Name">{{ file.name }}</l-item>
68
+ <l-item label="Size">{{ size }} ({{ file.size }})</l-item>
69
+ <l-item label="Location">{{ file.path }}</l-item>
70
+ <l-item label="Last modified">{{ lastModifiedHuman }}</l-item>
71
+ <l-item label="MIME type">{{ file.mimeType }}</l-item>
72
72
 
73
- <q-item>
74
- <q-item-section side>
75
- <q-item-label>URL</q-item-label>
76
- </q-item-section>
77
- <q-item-section style="align-items: flex-end;">
78
- <q-item-label lines="1">{{ file.publicUrl }}</q-item-label>
79
- </q-item-section>
73
+ <q-item>
74
+ <q-item-section side>
75
+ <q-item-label>URL</q-item-label>
76
+ </q-item-section>
77
+ <q-item-section style="align-items: flex-end;">
78
+ <q-item-label lines="1">{{ file.publicUrl }}</q-item-label>
79
+ </q-item-section>
80
80
 
81
- <q-item-section side>
82
- <q-btn size="md" flat dense round icon="sym_o_content_copy" @click="copyToClipboard(file.publicUrl)"></q-btn>
83
- </q-item-section>
84
- </q-item>
85
- </q-list>
81
+ <q-item-section side>
82
+ <q-btn size="md" flat dense round icon="sym_o_content_copy" @click="copyToClipboard(file.publicUrl)"></q-btn>
83
+ </q-item-section>
84
+ </q-item>
85
+ </q-list>
86
+ </div>
86
87
  </template>
@@ -2,7 +2,7 @@
2
2
  import { useI18n } from "vue-i18n";
3
3
  import { ref, watch, computed } from "vue";
4
4
  import { useQuasar, format, date } from "quasar";
5
- import { q, m, useLight, showUploadFilesDialog } from "#imports";
5
+ import { q, m, useLight, showUploadFilesDialog, showDocumentDialog } from "#imports";
6
6
  import { getGrantedRights } from "@hostlink/light";
7
7
  import { fs } from "@hostlink/light";
8
8
  const { humanStorageSize } = format;
@@ -347,18 +347,10 @@ const getFilePublicUrl = async (location) => {
347
347
  return file.publicUrl;
348
348
  };
349
349
  const onPreview = async (node) => {
350
- showPreviewImgDialog.value = true;
351
- previewImg.value = await getFilePublicUrl(node.location);
352
- };
353
- const onPreviewPDF = async (node) => {
354
- const height = window.innerHeight - 200;
355
- $q.dialog({
356
- autoClose: true,
357
- fullWidth: true,
358
- fullHeight: true,
359
- title: "Preview PDF",
360
- message: "<iframe src='" + await getFilePublicUrl(node.location) + "' width='100%' height='" + height + "px'></iframe>",
361
- html: true
350
+ showDocumentDialog({
351
+ url: await getFilePublicUrl(node.location),
352
+ mimeType: node.mimeType,
353
+ title: node.name
362
354
  });
363
355
  };
364
356
  const onClickInfo = async (row) => {
@@ -376,7 +368,7 @@ const canPreview = (file) => {
376
368
  if (!file.mimeType) {
377
369
  return false;
378
370
  }
379
- return file.mimeType.startsWith("image/");
371
+ return file.mimeType.startsWith("image/") || file.mimeType === "text/plain" || file.mimeType === "application/pdf" || file.mimeType.startsWith("video/") || file.mimeType.startsWith("audio/");
380
372
  };
381
373
  const onCheckTotalSize = async (folder) => {
382
374
  const d = $q.dialog({
@@ -562,8 +554,9 @@ const getFileIcon = (file) => {
562
554
  <q-toolbar>
563
555
  <l-file-manager-breadcrumbs v-model="selectedLocation" />
564
556
  <q-space></q-space>
565
- <q-btn flat round icon="sym_o_drive_file_move" v-if="selected.length > 0">
566
- <l-file-manager-move @selected="moveToFolder($event)" :current_location="selectedLocation"
557
+ <q-btn flat round icon="sym_o_drive_file_move" v-if="selected.length > 0 && selectedLocation">
558
+ <l-file-manager-move @selected="moveToFolder($event)"
559
+ :current_location="selectedLocation"
567
560
  :allow_cross_fs="selected.every(item => item.__typename == 'File')" />
568
561
  <q-tooltip>
569
562
  {{ $t('Move to') }}
@@ -624,7 +617,10 @@ const getFileIcon = (file) => {
624
617
  </q-item-section>
625
618
  </q-item>
626
619
 
627
- <q-img v-if="canPreview(props.row)" :src="props.row.url"></q-img>
620
+ <l-document-viewer :url="props.row.publicUrl"
621
+ height="100px"
622
+
623
+ :mime-type="props.row.mimeType" :title="props.row.name" v-if="props.row.mimeType.startsWith('image/')" />
628
624
 
629
625
  </q-card>
630
626
  </div>
@@ -636,7 +632,7 @@ const getFileIcon = (file) => {
636
632
  <q-table flat :columns="columns" :rows="items" @row-dblclick="onDblclickRow" @row-click="onClickRow"
637
633
  :pagination="pagination" row-key="location" selection="multiple" v-model:selected="selected" dense
638
634
  :loading="loading" :loading-label="$t('Loading...')" :no-data-label="$t('No data available')"
639
- separator="horizontal" :rows-per-page-options="[0]" color="primary">
635
+ separator="horizontal" :rows-per-page-options="[0]" color="primary" square>
640
636
  <template #body-cell-icon="props">
641
637
  <q-td auto-width>
642
638
  <q-icon name="sym_o_folder" v-if="props.row.__typename == 'Folder'" size="sm" />
@@ -695,14 +691,6 @@ const getFileIcon = (file) => {
695
691
  <q-item-section>{{ $t('Preview') }}</q-item-section>
696
692
  </q-item>
697
693
 
698
- <q-item clickable v-close-popup v-if="props.row.mimeType == 'application/pdf'"
699
- @click="onPreviewPDF(props.row)">
700
- <q-item-section avatar>
701
- <q-icon name="sym_o_preview"></q-icon>
702
- </q-item-section>
703
- <q-item-section>{{ $t('Preview') }}</q-item-section>
704
- </q-item>
705
-
706
694
  <q-item clickable v-close-popup @click="onClickInfo(props.row)" class="lt-lg">
707
695
  <q-item-section avatar>
708
696
  <q-icon name="sym_o_info"></q-icon>
@@ -1,7 +1,7 @@
1
1
  <script setup>
2
- import { computed, ref, useAttrs } from "vue";
2
+ import { computed, ref, useAttrs, getCurrentInstance } from "vue";
3
3
  import { useRouter, useRoute } from "vue-router";
4
- import { useQuasar } from "quasar";
4
+ import { useQuasar, QForm } from "quasar";
5
5
  import { model } from "#imports";
6
6
  const route = useRoute();
7
7
  const router = useRouter();
@@ -33,17 +33,24 @@ const props = defineProps({
33
33
  }
34
34
  });
35
35
  const loading = ref(false);
36
+ const attrs = useAttrs();
36
37
  const emit = defineEmits(["save", "submit", "submitted"]);
38
+ const instance = getCurrentInstance();
39
+ const hasSubmitListener = computed(() => {
40
+ return !!instance?.vnode?.props?.onSubmit;
41
+ });
37
42
  const save = async () => {
43
+ if (!form.value) return;
38
44
  let valid = await form.value.validate();
39
45
  if (!valid) return;
40
- if (valid) {
41
- loading.value = true;
42
- emit("save");
43
- emit("submit");
46
+ emit("save");
47
+ if (hasSubmitListener.value) {
48
+ emit("submit", () => {
49
+ loading.value = false;
50
+ });
51
+ return;
44
52
  }
45
- if (props.modelValue) {
46
- const [module, id_name] = route.name.split("-");
53
+ if (props.modelValue && route.name) {
47
54
  try {
48
55
  if (route.params[id_name]) {
49
56
  if (await model(module).update(parseInt(route.params[id_name]), props.modelValue)) {
@@ -76,7 +83,6 @@ const onSubmit = (e) => {
76
83
  e.preventDefault();
77
84
  save();
78
85
  };
79
- const attrs = useAttrs();
80
86
  const localClass = computed(() => {
81
87
  if (attrs.class) {
82
88
  return attrs.class;
@@ -93,7 +99,7 @@ const localClass = computed(() => {
93
99
  </q-card-section>
94
100
 
95
101
  <q-card-actions align="right">
96
- <l-btn :icon="submitIcon" :label="submitLabel" @click="save" :loading="loading" type="submit" />
102
+ <l-btn :icon="submitIcon" :label="submitLabel" :loading="loading" type="submit" />
97
103
  </q-card-actions>
98
104
  </l-card>
99
105
  </q-form>
@@ -80,8 +80,8 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
80
80
  bordered: boolean;
81
81
  separator: boolean;
82
82
  modelValue: unknown[];
83
- max: number;
84
83
  min: number;
84
+ max: number;
85
85
  addLabel: string;
86
86
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
87
87
  type __VLS_Slots = {
@@ -80,8 +80,8 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
80
80
  bordered: boolean;
81
81
  separator: boolean;
82
82
  modelValue: unknown[];
83
- max: number;
84
83
  min: number;
84
+ max: number;
85
85
  addLabel: string;
86
86
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
87
87
  type __VLS_Slots = {
@@ -0,0 +1,9 @@
1
+ export interface DocumentDialogOptions {
2
+ url: string;
3
+ mimeType?: string;
4
+ title?: string;
5
+ width?: string;
6
+ height?: string;
7
+ fit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
8
+ }
9
+ export declare function showDocumentDialog(options: DocumentDialogOptions): import("quasar").DialogChainObject;
@@ -0,0 +1,15 @@
1
+ import { Dialog } from "quasar";
2
+ import { LDocumentViewerDialog } from "#components";
3
+ export function showDocumentDialog(options) {
4
+ return Dialog.create({
5
+ component: LDocumentViewerDialog,
6
+ componentProps: {
7
+ url: options.url,
8
+ mimeType: options.mimeType ?? "",
9
+ title: options.title ?? "",
10
+ width: options.width ?? "100%",
11
+ height: options.height ?? "70vh",
12
+ fit: options.fit ?? "contain"
13
+ }
14
+ });
15
+ }
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
2
  import { model, q } from "#imports";
3
- import { resolveComponent } from "vue";
3
+ import { LCustomFieldAdd } from "#components";
4
4
  const onRequest = async (request) => {
5
5
  request.loadObjects("CustomField");
6
6
  };
@@ -15,7 +15,6 @@ const columns = model("CustomField").columns({
15
15
  type: true,
16
16
  validation: true
17
17
  });
18
- const addComponent = await resolveComponent("l-custom-field-add");
19
18
  </script>
20
19
 
21
20
  <template>
@@ -25,9 +24,10 @@ const addComponent = await resolveComponent("l-custom-field-add");
25
24
  on Customization settings page.
26
25
  </p>
27
26
 
28
- <l-table row-key="custom_field_id" @request-data="onRequest" :columns="columns" :add-component="addComponent" :add-component-props="{
29
- models: app.customFieldModels
30
- }" :actions="['edit', 'delete']">
27
+ <l-table row-key="custom_field_id" @request-data="onRequest" :columns="columns" :add-component="LCustomFieldAdd"
28
+ :add-component-props="{
29
+ models: app.customFieldModels
30
+ }" :actions="['edit', 'delete']">
31
31
  </l-table>
32
32
 
33
33
  </l-page>
@@ -1,6 +1,9 @@
1
1
  <script setup>
2
- import { q, m, useLight, useAsyncData } from "#imports";
3
- import { resolveComponent, ref, reactive, computed } from "vue";
2
+ import { q, m, useLight, useAsyncData, useQuasar } from "#imports";
3
+ import { ref, reactive, computed } from "vue";
4
+ import { LDatabaseCreateTableDialog, LDialogDatabaseFieldAdd } from "#components";
5
+ import { Dialog } from "quasar";
6
+ const $q = useQuasar();
4
7
  const light = useLight();
5
8
  const { data, refresh } = await useAsyncData("database", async () => {
6
9
  return await q({
@@ -14,18 +17,16 @@ const { data, refresh } = await useAsyncData("database", async () => {
14
17
  }
15
18
  }).then((res) => res.system.database);
16
19
  });
17
- const SYSTEM_TABLES = ["Config", "EventLog", "MailLog", "Permission", "Role", "SystemValue", "Translate", "User", "UserLog", "UserRole", "MyFavorite", "CustomField"];
20
+ const SYSTEM_TABLES = ["Config", "EventLog", "MailLog", "Permission", "Role", "SystemValue", "Translate", "User", "UserLog", "UserRole", "MyFavorite", "CustomField", "Revision"];
18
21
  const custom_tables = computed(() => {
19
22
  return (data.value?.tableStatus ?? []).filter((table) => !SYSTEM_TABLES.includes(table.Name));
20
23
  });
21
24
  const systables = computed(() => {
22
25
  return (data.value?.tableStatus ?? []).filter((table) => SYSTEM_TABLES.includes(table.Name));
23
26
  });
24
- const field_add = resolveComponent("l-dialog-database-field-add");
25
- const table_add = resolveComponent("l-database-create-table-dialog");
26
27
  const add = async (table) => {
27
- light.dialog({
28
- component: field_add
28
+ $q.dialog({
29
+ component: LDialogDatabaseFieldAdd
29
30
  }).onOk(async (data2) => {
30
31
  try {
31
32
  await m("lightDatabaseAddField", {
@@ -83,8 +84,8 @@ const removeField = async (table) => {
83
84
  });
84
85
  };
85
86
  const createTable = () => {
86
- light.dialog({
87
- component: table_add
87
+ Dialog.create({
88
+ component: LDatabaseCreateTableDialog
88
89
  }).onOk(async (data2) => {
89
90
  try {
90
91
  await m("lightDatabaseCreateTable", {
@@ -175,62 +176,48 @@ const truncatTable = async () => {
175
176
  </l-list>
176
177
  </l-card>
177
178
 
178
- <q-card>
179
- <q-list separator bordered>
180
- <q-expansion-item label="Table Status" dense>
181
- <div s>
182
-
183
- <q-table :rows="custom_tables" hide-pagination flat bordered separator="cell" dense
184
- :rows-per-page-options="[0]" v-model:selected="selectedTable" selection="multiple"
185
- row-key="Name">
186
-
187
- <template #top-left>
188
- <q-btn icon="sym_o_add" @click="createTable()" round flat size="sm">
189
- <q-tooltip>Create table</q-tooltip>
190
- </q-btn>
191
- <q-btn icon="sym_o_delete" @click="removeTable()" round flat size="sm"
192
- :disable="selectedTable.length == 0">
193
- <q-tooltip>Remove table</q-tooltip>
194
- </q-btn>
195
-
196
- <q-btn icon="sym_o_scan_delete" @click="truncatTable" round flat size="sm"
197
- :disable="selectedTable.length == 0">
198
- <q-tooltip>Truncate table</q-tooltip>
199
- </q-btn>
200
-
201
- </template>
202
- </q-table>
203
-
204
- <q-table :rows="systables" hide-pagination flat bordered separator="cell" dense
205
- :rows-per-page-options="[0]" row-key="Name" title="System tables">
179
+ <l-card>
180
+ <q-expansion-item label="Custom Tables" dense header-class="text-weight-medium">
181
+ <q-table :rows="custom_tables" hide-pagination flat separator="cell" dense :rows-per-page-options="[0]"
182
+ v-model:selected="selectedTable" selection="multiple" row-key="Name" class="q-ma-sm">
183
+ <template #top>
184
+ <div class="row items-center q-gutter-sm">
185
+ <q-btn icon="sym_o_add" @click="createTable" flat size="sm" label="Add Table"
186
+ color="primary" />
187
+ <q-btn icon="sym_o_delete" @click="removeTable" :disable="selectedTable.length == 0"
188
+ label="Remove" flat size="sm" color="negative" />
189
+ <q-btn icon="sym_o_scan_delete" @click="truncatTable" :disable="selectedTable.length == 0"
190
+ label="Truncate" flat size="sm" color="warning" />
191
+ </div>
192
+ </template>
193
+ </q-table>
194
+ </q-expansion-item>
206
195
 
207
- </q-table>
208
- </div>
209
- </q-expansion-item>
210
- </q-list>
211
- </q-card>
196
+ <q-separator />
212
197
 
213
- <q-card>
214
- <q-list separator bordered>
215
- <q-expansion-item :label="table.name" v-for="table in data.table" dense>
216
- <div class="q-ma-sm">
217
- <q-table row-key="name" :rows="table.columns" :rows-per-page-options="[0]" hide-pagination flat
218
- bordered selection="multiple" v-model:selected="selected[table.name]">
219
- <template #top-left>
220
- <q-btn icon="sym_o_add" @click="add(table.name)" round flat size="sm">
221
- <q-tooltip>Add field</q-tooltip>
222
- </q-btn>
223
- <q-btn icon="sym_o_delete" @click="removeField(table.name)" round flat size="sm"
224
- :disable="selected[table.name].length == 0">
225
- <q-tooltip>Remove field</q-tooltip>
226
- </q-btn>
227
- </template>
228
- </q-table>
229
- </div>
198
+ <q-expansion-item label="System Tables" dense header-class="text-weight-medium">
199
+ <q-table :rows="systables" hide-pagination flat separator="cell" dense :rows-per-page-options="[0]"
200
+ row-key="Name" class="q-ma-sm" />
201
+ </q-expansion-item>
202
+ </l-card>
230
203
 
231
- </q-expansion-item>
232
- </q-list>
233
- </q-card>
204
+ <l-card title="Tables">
205
+ <q-expansion-item v-for="table in data.table" :key="table.name" :label="table.name" dense
206
+ header-class="text-weight-medium">
207
+ <q-table row-key="name" :rows="table.columns" :rows-per-page-options="[0]" hide-pagination flat
208
+ separator="cell" dense selection="multiple" v-model:selected="selected[table.name]" class="q-ma-sm">
209
+ <template #top>
210
+ <div class="row items-center q-gutter-sm">
211
+ <q-btn icon="sym_o_add" @click="add(table.name)" flat size="sm" label="Add Field"
212
+ color="primary" />
213
+ <q-btn icon="sym_o_delete" @click="removeField(table.name)"
214
+ :disable="selected[table.name]?.length == 0" label="Remove Field" flat size="sm"
215
+ color="negative" />
216
+ </div>
217
+ </template>
218
+ </q-table>
219
+ </q-expansion-item>
220
+ </l-card>
234
221
 
235
222
  </l-page>
236
223
  </template>
@@ -47,7 +47,7 @@ const onSubmit = async (d) => {
47
47
  <q-tabs v-model="tab" vertical>
48
48
  <q-tab name="general" icon="sym_o_info" :label="$t('General')" />
49
49
  <q-tab name="security" icon="sym_o_security" :label="$t('Security')" />
50
- <q-tab name="Modules" icon="sym_o_apps" :label="$t('Modules')" />
50
+ <q-tab name="modules" icon="sym_o_apps" :label="$t('Modules')" />
51
51
  <q-tab name="mail" icon="sym_o_email" :label="$t('Mail')" />
52
52
  <q-tab name="forget-password" icon="sym_o_lock" :label="$t('Forget password')" />
53
53
  <q-tab name="authentication" icon="sym_o_passkey" :label="$t('Authentication')" />
@@ -58,7 +58,7 @@ const onSubmit = async (d) => {
58
58
  <l-system-setting-general v-if="tab == 'general'" v-bind="obj" @submit="onSubmit" />
59
59
  <l-system-setting-mail v-if="tab == 'mail'" v-bind="obj" @submit="onSubmit" />
60
60
  <l-system-setting-security v-if="tab == 'security'" v-bind="obj" @submit="onSubmit" />
61
- <l-system-setting-modules v-if="tab == 'Modules'" v-bind="obj" @submit="onSubmit" />
61
+ <l-system-setting-modules v-if="tab == 'modules'" v-bind="obj" @submit="onSubmit" />
62
62
  <l-system-setting-developer v-if="tab == 'developer'" v-bind="obj" @submit="onSubmit" />
63
63
  <l-system-setting-forget-password v-if="tab == 'forget-password'" v-bind="obj" @submit="onSubmit" />
64
64
  <l-system-setting-authentication v-if="tab == 'authentication'" v-bind="obj" @submit="onSubmit" />