@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.
- package/dist/module.json +1 -1
- package/dist/module.mjs +5 -0
- package/dist/runtime/components/L/CustomField/Add.vue +6 -1
- package/dist/runtime/components/L/Database/create-table-dialog.vue +34 -26
- package/dist/runtime/components/L/DocumentViewer.d.vue.ts +50 -0
- package/dist/runtime/components/L/DocumentViewer.vue +154 -0
- package/dist/runtime/components/L/DocumentViewer.vue.d.ts +50 -0
- package/dist/runtime/components/L/DocumentViewerDialog.d.vue.ts +65 -0
- package/dist/runtime/components/L/DocumentViewerDialog.vue +67 -0
- package/dist/runtime/components/L/DocumentViewerDialog.vue.d.ts +65 -0
- package/dist/runtime/components/l-customizer.d.vue.ts +19 -3
- package/dist/runtime/components/l-customizer.vue.d.ts +19 -3
- package/dist/runtime/components/l-file-manager-labels.d.vue.ts +5 -1
- package/dist/runtime/components/l-file-manager-labels.vue.d.ts +5 -1
- package/dist/runtime/components/l-file-manager-preview.vue +23 -22
- package/dist/runtime/components/l-file-manager.vue +14 -26
- package/dist/runtime/components/l-form.vue +16 -10
- package/dist/runtime/components/l-repeater.d.vue.ts +1 -1
- package/dist/runtime/components/l-repeater.vue.d.ts +1 -1
- package/dist/runtime/composables/showDocumentDialog.d.ts +9 -0
- package/dist/runtime/composables/showDocumentDialog.js +15 -0
- package/dist/runtime/pages/CustomField/index.vue +5 -5
- package/dist/runtime/pages/System/database/table.vue +49 -62
- package/dist/runtime/pages/System/setting.vue +2 -2
- package/dist/runtime/pages/Translate/index.vue +178 -62
- package/dist/runtime/pages/User/createAccessToken.d.vue.ts +3 -0
- package/dist/runtime/pages/User/createAccessToken.vue +63 -0
- package/dist/runtime/pages/User/createAccessToken.vue.d.ts +3 -0
- package/dist/runtime/pages/User/profile.vue +1 -0
- 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, {
|
|
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 {
|
|
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
|
-
<
|
|
64
|
-
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
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)"
|
|
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
|
-
<
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
emit("
|
|
43
|
-
|
|
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"
|
|
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 {
|
|
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="
|
|
29
|
-
|
|
30
|
-
|
|
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 {
|
|
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
|
-
|
|
28
|
-
component:
|
|
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
|
-
|
|
87
|
-
component:
|
|
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
|
-
<
|
|
179
|
-
<q-
|
|
180
|
-
<q-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
<
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
-
|
|
208
|
-
</div>
|
|
209
|
-
</q-expansion-item>
|
|
210
|
-
</q-list>
|
|
211
|
-
</q-card>
|
|
196
|
+
<q-separator />
|
|
212
197
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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="
|
|
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 == '
|
|
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" />
|