@hostlink/nuxt-light 0.0.89 → 0.0.91
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/runtime/components/l-app-main.vue +4 -9
- package/dist/runtime/components/l-app.vue +7 -4
- package/dist/runtime/components/l-date-picker.vue +13 -4
- package/dist/runtime/components/l-field.vue +8 -0
- package/dist/runtime/components/l-login.vue +4 -8
- package/dist/runtime/components/l-menu.vue +30 -9
- package/dist/runtime/components/l-page.vue +13 -4
- package/dist/runtime/components/l-table.vue +8 -1
- package/dist/runtime/index.d.ts +5 -1
- package/dist/runtime/index.mjs +18 -2
- package/dist/runtime/locales/zh-hk.json +7 -1
- package/dist/runtime/pages/EventLog/index.vue +2 -38
- package/dist/runtime/pages/MailLog/index.vue +33 -32
- package/dist/runtime/pages/User/_user_id/update-role.vue +2 -3
- package/dist/runtime/pages/User/add.vue +2 -2
- package/dist/runtime/pages/User/profile.vue +72 -14
- package/dist/runtime/plugin.mjs +4 -0
- package/dist/runtime/types/EventLog.d.ts +33 -0
- package/dist/runtime/types/EventLog.mjs +32 -0
- package/dist/runtime/types/MailLog.d.ts +30 -0
- package/dist/runtime/types/MailLog.mjs +29 -0
- package/package.json +1 -1
- package/dist/runtime/system_menus.d.ts +0 -10
- package/dist/runtime/system_menus.mjs +0 -37
package/dist/module.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { useLight } from "#imports";
|
|
2
3
|
import { useQuasar } from 'quasar';
|
|
3
4
|
import { useI18n } from 'vue-i18n';
|
|
4
|
-
import {
|
|
5
|
+
import { q, getCurrentUser, m, f } from '../';
|
|
5
6
|
import { ref, computed, reactive, provide, watch } from 'vue';
|
|
6
7
|
import { useRuntimeConfig } from 'nuxt/app';
|
|
7
8
|
|
|
@@ -17,12 +18,6 @@ const quasar = useQuasar();
|
|
|
17
18
|
quasar.dark.set(false);
|
|
18
19
|
const light = useLight();
|
|
19
20
|
|
|
20
|
-
const props = defineProps({
|
|
21
|
-
company: {
|
|
22
|
-
type: String
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
|
|
26
21
|
const tt = await q({
|
|
27
22
|
app: ["menus", "viewAsMode", "languages", { i18nMessages: ["name", "value"] }],
|
|
28
23
|
my: ["styles", "language", f('granted_storage:granted', { right: "system.storage" }, [])],
|
|
@@ -204,7 +199,7 @@ const storageUsagePercent = computed(() => {
|
|
|
204
199
|
<q-btn dense flat round icon="menu" class="q-mr-sm" @click="toggleLeftDrawer" />
|
|
205
200
|
|
|
206
201
|
<q-toolbar-title>
|
|
207
|
-
{{
|
|
202
|
+
{{ light.getCompany() }}
|
|
208
203
|
</q-toolbar-title>
|
|
209
204
|
|
|
210
205
|
<q-space />
|
|
@@ -338,7 +333,7 @@ const storageUsagePercent = computed(() => {
|
|
|
338
333
|
<q-footer class="bg-white text-grey" bordered>
|
|
339
334
|
<q-item>
|
|
340
335
|
<q-item-section>
|
|
341
|
-
{{
|
|
336
|
+
{{ light.getCompany() }} {{ appVersion }} - Copyright 2023 HostLink(HK). Build {{ light.getVersion() }}
|
|
342
337
|
</q-item-section>
|
|
343
338
|
</q-item>
|
|
344
339
|
</q-footer>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { useLight } from "#imports";
|
|
2
3
|
import { useRuntimeConfig } from 'nuxt/app'
|
|
3
4
|
import { setApiUrl } from '@hostlink/light'
|
|
4
5
|
import { Dialog } from 'quasar'
|
|
@@ -8,9 +9,11 @@ setApiUrl(config?.public?.apiBase ?? '/api/');
|
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
let app = null
|
|
11
|
-
|
|
12
|
+
const light = useLight()
|
|
12
13
|
try {
|
|
13
14
|
app = (await q({ app: ['company', 'companyLogo', 'logged', 'twoFactorAuthentication', 'googleClientId'] })).app;
|
|
15
|
+
light.setCompany(app.company);
|
|
16
|
+
light.setCompanyLogo(app.companyLogo);
|
|
14
17
|
} catch (e) {
|
|
15
18
|
Dialog.create({
|
|
16
19
|
title: 'Error',
|
|
@@ -27,13 +30,13 @@ try {
|
|
|
27
30
|
<q-layout v-if="!app.logged">
|
|
28
31
|
<q-page-container class="bg-grey-2" style="color:#1f1f1f">
|
|
29
32
|
<q-page padding>
|
|
30
|
-
<l-login :
|
|
31
|
-
:
|
|
33
|
+
<l-login :two-factor-authentication="app.twoFactorAuthentication"
|
|
34
|
+
:google-client-id="app.googleClientId"></l-login>
|
|
32
35
|
</q-page>
|
|
33
36
|
</q-page-container>
|
|
34
37
|
</q-layout>
|
|
35
38
|
|
|
36
|
-
<l-app-main v-else
|
|
39
|
+
<l-app-main v-else>
|
|
37
40
|
<slot></slot>
|
|
38
41
|
</l-app-main>
|
|
39
42
|
</template>
|
|
@@ -45,14 +45,21 @@ const localValue = computed({
|
|
|
45
45
|
|
|
46
46
|
const rules = [];
|
|
47
47
|
|
|
48
|
-
if (props.required
|
|
48
|
+
if (props.required) {
|
|
49
49
|
rules.push((val) => {
|
|
50
50
|
if (!val) {
|
|
51
51
|
return "Required";
|
|
52
52
|
}
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!props.range) {
|
|
57
|
+
rules.push((val) => {
|
|
53
58
|
//check val is YYYY-MM-DD
|
|
54
|
-
if (
|
|
55
|
-
|
|
59
|
+
if (val) {
|
|
60
|
+
if (!val.match(/^\d{4}-\d{2}-\d{2}$/)) {
|
|
61
|
+
return "Invalid date format";
|
|
62
|
+
}
|
|
56
63
|
}
|
|
57
64
|
});
|
|
58
65
|
}
|
|
@@ -70,9 +77,11 @@ const attrs = {
|
|
|
70
77
|
...useAttrs(),
|
|
71
78
|
}
|
|
72
79
|
|
|
80
|
+
const mask = props.range ? "####-##-## - ####-##-##" : "####-##-##";
|
|
81
|
+
|
|
73
82
|
</script>
|
|
74
83
|
<template>
|
|
75
|
-
<q-input v-bind="attrs" v-model="localValue" :rules="rules" :label="$t(label)" hide-bottom-space>
|
|
84
|
+
<q-input v-bind="attrs" v-model="localValue" :rules="rules" :label="$t(label)" hide-bottom-space :mask="mask">
|
|
76
85
|
<template v-slot:prepend>
|
|
77
86
|
<q-btn icon="sym_o_event" round dense flat>
|
|
78
87
|
<q-popup-proxy cover transition-show="scale" transition-hide="scale" ref="popup">
|
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { useLight } from "#imports";
|
|
2
3
|
import { ref, reactive, onMounted } from 'vue'
|
|
3
4
|
import { useQuasar, Notify } from 'quasar';
|
|
4
5
|
import { useI18n } from 'vue-i18n';
|
|
5
6
|
import { m, notify } from '../';
|
|
6
7
|
|
|
7
|
-
import { useRuntimeConfig } from 'nuxt/app';
|
|
8
|
-
|
|
9
8
|
import { login, webauthnLogin } from '@hostlink/light';
|
|
10
9
|
|
|
11
|
-
const
|
|
12
|
-
|
|
10
|
+
const light = useLight();
|
|
13
11
|
|
|
14
12
|
const props = defineProps({
|
|
15
|
-
company: String,
|
|
16
|
-
companyLogo: String,
|
|
17
13
|
twoFactorAuthentication: Boolean,
|
|
18
14
|
googleClientId: String
|
|
19
15
|
})
|
|
@@ -178,9 +174,9 @@ onMounted(() => {
|
|
|
178
174
|
<template>
|
|
179
175
|
<q-card bordered flat style="min-width:400px;max-width: 400px;" class="fixed-center">
|
|
180
176
|
<q-card-section>
|
|
181
|
-
<q-img :src="
|
|
177
|
+
<q-img :src="light.getCompanyLogo()" class="full-width" />
|
|
182
178
|
<div class="text-h6">
|
|
183
|
-
{{
|
|
179
|
+
{{ light.getCompany() }}
|
|
184
180
|
</div>
|
|
185
181
|
<q-form ref="form1">
|
|
186
182
|
<div class="q-gutter-sm">
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import {
|
|
3
|
-
const
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
const props = defineProps(["value", "dense"])
|
|
4
|
+
const menus = ref(null);
|
|
4
5
|
|
|
5
|
-
defineProps(["value", "dense"])
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const expansion = ref(null);
|
|
8
|
+
|
|
9
|
+
const onShowChild = (menu) => {
|
|
10
|
+
menus.value.forEach((m) => {
|
|
11
|
+
if (m.value() !== menu) {
|
|
12
|
+
m.hide()
|
|
13
|
+
}
|
|
14
|
+
})
|
|
15
|
+
}
|
|
8
16
|
|
|
17
|
+
defineExpose({
|
|
18
|
+
hide: () => {
|
|
19
|
+
if (expansion.value) {
|
|
20
|
+
expansion.value.hide();
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
value: () => {
|
|
24
|
+
return props.value;
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
</script>
|
|
9
29
|
|
|
10
30
|
<style scoped>
|
|
11
31
|
.menu-list .q-item {
|
|
@@ -19,11 +39,12 @@ defineProps(["value", "dense"])
|
|
|
19
39
|
color: #fff;
|
|
20
40
|
}
|
|
21
41
|
</style>
|
|
22
|
-
|
|
23
42
|
<template>
|
|
24
|
-
<q-expansion-item v-if="value.children?.length > 0" :label="
|
|
43
|
+
<q-expansion-item v-if="value.children?.length > 0" :label="$t(value.label)" :icon="value.icon" :dense="dense"
|
|
44
|
+
ref="expansion">
|
|
25
45
|
<q-list class="q-pl-md">
|
|
26
|
-
<l-menu :value="menu" v-for="menu in value.children" :dense="dense"
|
|
46
|
+
<l-menu :value="menu" v-for="menu in value.children" :dense="dense" @show="onShowChild(menu)"
|
|
47
|
+
ref="menus"></l-menu>
|
|
27
48
|
</q-list>
|
|
28
49
|
</q-expansion-item>
|
|
29
50
|
<q-list v-else class="menu-list" :dense="dense">
|
|
@@ -32,8 +53,8 @@ defineProps(["value", "dense"])
|
|
|
32
53
|
<q-icon :name="value.icon" />
|
|
33
54
|
</q-item-section>
|
|
34
55
|
<q-item-section>
|
|
35
|
-
<q-item-label v-text="
|
|
56
|
+
<q-item-label v-text="$t(value.label)"></q-item-label>
|
|
36
57
|
</q-item-section>
|
|
37
58
|
</q-item>
|
|
38
59
|
</q-list>
|
|
39
|
-
</template>
|
|
60
|
+
</template>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { useHead, useLight } from "#imports";
|
|
2
3
|
import { useRouter, useRoute } from "vue-router"
|
|
3
4
|
import { removeObject, getID } from '../'
|
|
4
|
-
import { useI18n } from 'vue-i18n';
|
|
5
5
|
|
|
6
|
-
const i18n = useI18n();
|
|
7
6
|
const router = useRouter();
|
|
8
7
|
const route = useRoute();
|
|
8
|
+
const light = useLight();
|
|
9
9
|
|
|
10
10
|
const props = defineProps({
|
|
11
11
|
type: {
|
|
@@ -71,7 +71,12 @@ if (props.addBtn) {
|
|
|
71
71
|
showAddBtn = true
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
let title = props.title || route.path.split("/")[1].replace(/([a-z])(?=[A-Z])/g, '$1 ').replace(/([A-Z]*)(?=[A-Z][a-z])/g, '$1 ')
|
|
75
|
+
|
|
76
|
+
//remove double space
|
|
77
|
+
title = title.replace(/\s\s+/g, ' ');
|
|
78
|
+
//trim title
|
|
79
|
+
title = title.trim()
|
|
75
80
|
const module = route.path.split("/")[1];
|
|
76
81
|
const onDelete = async () => {
|
|
77
82
|
|
|
@@ -79,6 +84,10 @@ const onDelete = async () => {
|
|
|
79
84
|
router.push(`/${module}`);
|
|
80
85
|
}
|
|
81
86
|
}
|
|
87
|
+
|
|
88
|
+
useHead({
|
|
89
|
+
title: light.getCompany() + " - " + title,
|
|
90
|
+
})
|
|
82
91
|
</script>
|
|
83
92
|
|
|
84
93
|
<template>
|
|
@@ -88,7 +97,7 @@ const onDelete = async () => {
|
|
|
88
97
|
<l-add-btn v-if="showAddBtn" />
|
|
89
98
|
<l-edit-btn v-if="showEditBtn" />
|
|
90
99
|
<l-delete-btn v-if="showDeleteBtn" @submit="onDelete" />
|
|
91
|
-
<q-toolbar-title>{{
|
|
100
|
+
<q-toolbar-title>{{ $t(title) }}</q-toolbar-title>
|
|
92
101
|
</q-toolbar>
|
|
93
102
|
|
|
94
103
|
<div class="q-gutter-sm q-mb-sm">
|
|
@@ -338,7 +338,9 @@ const getFilterValue = () => {
|
|
|
338
338
|
if (col.searchable) {
|
|
339
339
|
if (filters.value[col.name]) {
|
|
340
340
|
|
|
341
|
-
if (col.searchType == "
|
|
341
|
+
if (col.searchType == "number") {
|
|
342
|
+
f[col.name] = filters.value[col.name]
|
|
343
|
+
} else if (col.searchType == "date") {
|
|
342
344
|
if (filters.value[col.name].from) {
|
|
343
345
|
f[col.name] = {
|
|
344
346
|
between: [filters.value[col.name].from, filters.value[col.name].to]
|
|
@@ -479,6 +481,11 @@ const filter = ref('');
|
|
|
479
481
|
<q-td v-for="col in props.cols">
|
|
480
482
|
<template v-if="col.searchable">
|
|
481
483
|
|
|
484
|
+
<template v-if="col.searchType == 'number'">
|
|
485
|
+
<q-input dense clearable v-model.number="filters[col.name]" @keydown.enter.prevent="onFilters"
|
|
486
|
+
@clear="onFilters" mask="##########"></q-input>
|
|
487
|
+
</template>
|
|
488
|
+
|
|
482
489
|
<template v-if="col.searchType == 'select'">
|
|
483
490
|
<q-select dense v-model="filters[col.name]" @update:model-value="onFilters" clearable
|
|
484
491
|
:options="col.searchOptions" @clear="onFilters" emit-value />
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -5,6 +5,10 @@ interface Light {
|
|
|
5
5
|
getStyle: (name: String, defaultValue: any) => any;
|
|
6
6
|
setStyles: (styles: Object) => void;
|
|
7
7
|
getVersion(): string;
|
|
8
|
+
getCompany(): string;
|
|
9
|
+
setCompany(company: string): void;
|
|
10
|
+
getCompanyLogo(): string;
|
|
11
|
+
setCompanyLogo(logo: string): void;
|
|
8
12
|
}
|
|
9
|
-
export declare
|
|
13
|
+
export declare const useLight: () => Light;
|
|
10
14
|
export * from "./lib";
|
package/dist/runtime/index.mjs
CHANGED
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
import packageJson from "../../package.json";
|
|
2
2
|
const errors = [];
|
|
3
3
|
let styles = {};
|
|
4
|
-
|
|
4
|
+
const app = {
|
|
5
|
+
company: "",
|
|
6
|
+
companyLogo: ""
|
|
7
|
+
};
|
|
8
|
+
export const useLight = () => {
|
|
5
9
|
return {
|
|
10
|
+
setCompany: (company) => {
|
|
11
|
+
app.company = company;
|
|
12
|
+
},
|
|
13
|
+
getCompany: () => {
|
|
14
|
+
return app.company;
|
|
15
|
+
},
|
|
16
|
+
setCompanyLogo: (logo) => {
|
|
17
|
+
app.companyLogo = logo;
|
|
18
|
+
},
|
|
19
|
+
getCompanyLogo: () => {
|
|
20
|
+
return app.companyLogo;
|
|
21
|
+
},
|
|
6
22
|
getVersion: () => {
|
|
7
23
|
return packageJson.version;
|
|
8
24
|
},
|
|
@@ -28,5 +44,5 @@ export function useLight() {
|
|
|
28
44
|
styles = s;
|
|
29
45
|
}
|
|
30
46
|
};
|
|
31
|
-
}
|
|
47
|
+
};
|
|
32
48
|
export * from "./lib/index.mjs";
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"System": "系統",
|
|
19
19
|
"SystemBackup": "系統備份",
|
|
20
20
|
"SystemValue": "系統值",
|
|
21
|
+
"System Value": "系統值",
|
|
21
22
|
"Translate": "翻譯",
|
|
22
23
|
"User": "使用者",
|
|
23
24
|
"Setting": "設定",
|
|
@@ -151,5 +152,10 @@
|
|
|
151
152
|
"Login": "登入",
|
|
152
153
|
"Forget password": "忘記密碼",
|
|
153
154
|
"Password is required": "密碼為必填",
|
|
154
|
-
"Username is required": "使用者名稱為必填"
|
|
155
|
+
"Username is required": "使用者名稱為必填",
|
|
156
|
+
"Export": "匯出",
|
|
157
|
+
"Event Log": "事件紀錄",
|
|
158
|
+
"Mail Log": "郵件紀錄",
|
|
159
|
+
"User Log": "使用者紀錄"
|
|
160
|
+
|
|
155
161
|
}
|
|
@@ -1,42 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
label: "EventLog ID",
|
|
5
|
-
name: "eventlog_id",
|
|
6
|
-
sortable: true,
|
|
7
|
-
searchable: true,
|
|
8
|
-
},
|
|
9
|
-
|
|
10
|
-
{
|
|
11
|
-
label: "Class",
|
|
12
|
-
name: "class",
|
|
13
|
-
sortable: true,
|
|
14
|
-
searchable: true,
|
|
15
|
-
},
|
|
16
|
-
|
|
17
|
-
{
|
|
18
|
-
label: "ID",
|
|
19
|
-
name: "id",
|
|
20
|
-
sortable: true,
|
|
21
|
-
searchable: true,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
label: "Action",
|
|
25
|
-
name: "action",
|
|
26
|
-
sortable: true,
|
|
27
|
-
searchable: true,
|
|
28
|
-
}, {
|
|
29
|
-
label: "Created time",
|
|
30
|
-
name: "created_time",
|
|
31
|
-
sortable: true,
|
|
32
|
-
searchable: true,
|
|
33
|
-
}, {
|
|
34
|
-
label: "Username",
|
|
35
|
-
name: "username",
|
|
36
|
-
sortable: true,
|
|
37
|
-
searchable: true,
|
|
38
|
-
}
|
|
39
|
-
]
|
|
2
|
+
import { getModelColumns } from "#imports"
|
|
3
|
+
const columns = getModelColumns('EventLog', ['eventlog_id', 'class', 'id', 'action', 'created_time', 'username'])
|
|
40
4
|
|
|
41
5
|
</script>
|
|
42
6
|
|
|
@@ -1,40 +1,41 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
name: "maillog_id",
|
|
6
|
-
sortable: true,
|
|
7
|
-
searchable: true,
|
|
8
|
-
}, {
|
|
9
|
-
label: "From",
|
|
10
|
-
name: "from",
|
|
11
|
-
sortable: true,
|
|
12
|
-
searchable: true,
|
|
13
|
-
}, {
|
|
14
|
-
label: "To",
|
|
15
|
-
name: "to",
|
|
16
|
-
sortable: true,
|
|
17
|
-
searchable: true,
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
label: "Subject",
|
|
21
|
-
name: "subject",
|
|
22
|
-
sortable: true,
|
|
23
|
-
searchable: true,
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
label: "Created time",
|
|
27
|
-
name: "created_time",
|
|
28
|
-
sortable: true,
|
|
29
|
-
searchable: true,
|
|
30
|
-
searchType: "date",
|
|
31
|
-
}
|
|
32
|
-
]
|
|
2
|
+
import { getModelColumns } from "#imports"
|
|
3
|
+
import { ref } from 'vue'
|
|
4
|
+
const columns = getModelColumns("MailLog", ["maillog_id", "from", "to", "subject", "created_time"])
|
|
33
5
|
|
|
6
|
+
|
|
7
|
+
columns.push({
|
|
8
|
+
label: "Content",
|
|
9
|
+
name: "_act",
|
|
10
|
+
gqlField: ["body"]
|
|
11
|
+
})
|
|
12
|
+
const show = ref(false)
|
|
13
|
+
const content = ref("")
|
|
34
14
|
</script>
|
|
35
15
|
|
|
36
16
|
<template>
|
|
37
17
|
<l-page>
|
|
38
|
-
<
|
|
18
|
+
<q-dialog v-model="show" full-width>
|
|
19
|
+
<l-card>
|
|
20
|
+
<q-card-section>
|
|
21
|
+
<iframe width="100%" height="500px" :srcdoc="content" frameborder="0"></iframe>
|
|
22
|
+
</q-card-section>
|
|
23
|
+
</l-card>
|
|
24
|
+
</q-dialog>
|
|
25
|
+
<l-table row-key="maillog_id" @request="$event.loadObjects('MailLog')" :columns="columns" sort-by="maillog_id:desc">
|
|
26
|
+
|
|
27
|
+
<template #body-cell-_act="props">
|
|
28
|
+
<q-td :props="props">
|
|
29
|
+
<l-btn @click="
|
|
30
|
+
content = props.row.body;
|
|
31
|
+
show = true" label="Show" icon="sym_o_visibility">
|
|
32
|
+
</l-btn>
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
</q-td>
|
|
36
|
+
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
</l-table>
|
|
39
40
|
</l-page>
|
|
40
41
|
</template>
|
|
@@ -42,11 +42,10 @@ const submit = async () => {
|
|
|
42
42
|
<template>
|
|
43
43
|
<l-page>
|
|
44
44
|
<l-form @submit="submit">
|
|
45
|
-
<
|
|
45
|
+
<l-field label="Roles" stack-label>
|
|
46
46
|
<q-option-group type="checkbox" :options="roles" v-model="obj.roles" inline>
|
|
47
47
|
</q-option-group>
|
|
48
|
-
</
|
|
49
|
-
|
|
48
|
+
</l-field>
|
|
50
49
|
</l-form>
|
|
51
50
|
|
|
52
51
|
</l-page>
|
|
@@ -58,10 +58,10 @@ roles = roles.map((role) => {
|
|
|
58
58
|
|
|
59
59
|
<l-input label="Default page" v-model="obj.default_page"></l-input>
|
|
60
60
|
|
|
61
|
-
<
|
|
61
|
+
<l-field label="Roles" stack-label>
|
|
62
62
|
<q-option-group type="checkbox" :options="roles" v-model="obj.roles" inline>
|
|
63
63
|
</q-option-group>
|
|
64
|
-
</
|
|
64
|
+
</l-field>
|
|
65
65
|
</l-col>
|
|
66
66
|
</l-row>
|
|
67
67
|
</l-form>
|
|
@@ -1,6 +1,50 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { q } from '../../'
|
|
3
|
-
|
|
2
|
+
import { q, getModelColumns } from '../../'
|
|
3
|
+
import { getGQLFields } from '#imports'
|
|
4
|
+
import { toQuery } from '@hostlink/light';
|
|
5
|
+
|
|
6
|
+
const { my } = await q(
|
|
7
|
+
{
|
|
8
|
+
my: ["user_id", "username", "first_name", "last_name", "email", "phone", "roles", "addr1", "addr2", "addr3", "join_date", {
|
|
9
|
+
userLog: {
|
|
10
|
+
__args: {
|
|
11
|
+
sort: "userlog_id:desc"
|
|
12
|
+
},
|
|
13
|
+
data: {
|
|
14
|
+
__args: {
|
|
15
|
+
limit: 10
|
|
16
|
+
},
|
|
17
|
+
...toQuery(getGQLFields('UserLog', ['login_dt', 'result', "user_agent"]))
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
eventLog: {
|
|
21
|
+
__args: {
|
|
22
|
+
sort: "eventlog_id:desc"
|
|
23
|
+
},
|
|
24
|
+
data: {
|
|
25
|
+
__args: {
|
|
26
|
+
limit: 10
|
|
27
|
+
},
|
|
28
|
+
...toQuery(getGQLFields('EventLog', ['class', 'id', 'action', "created_time"]))
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}]
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
const userlogColumns = getModelColumns('UserLog', ['login_dt', 'result', 'user_agent']);
|
|
36
|
+
//remove all searchable
|
|
37
|
+
userlogColumns.forEach(col => {
|
|
38
|
+
col.searchable = false;
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
const eventLogCols = getModelColumns('EventLog', ['class', 'action', 'created_time']);
|
|
43
|
+
//remove all searchable
|
|
44
|
+
eventLogCols.forEach(col => {
|
|
45
|
+
col.searchable = false;
|
|
46
|
+
})
|
|
47
|
+
|
|
4
48
|
</script>
|
|
5
49
|
<template>
|
|
6
50
|
<l-page title="User profile">
|
|
@@ -8,18 +52,32 @@ const my = await q("my", ["user_id", "username", "first_name", "last_name", "ema
|
|
|
8
52
|
<l-btn icon="sym_o_key" to="update-password" label="Update password" />
|
|
9
53
|
<l-btn icon="sym_o_key" to="two-factor-auth" label="Two factor auth" />
|
|
10
54
|
</template>
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<l-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
55
|
+
|
|
56
|
+
<div class="q-gutter-md q-mt-md">
|
|
57
|
+
<l-card>
|
|
58
|
+
<l-list>
|
|
59
|
+
<l-item label="Username">{{ my.username }}</l-item>
|
|
60
|
+
<l-item label="First name">{{ my.first_name }}</l-item>
|
|
61
|
+
<l-item label="Last name">{{ my.last_name }}</l-item>
|
|
62
|
+
<l-item label="Email">{{ my.email }}</l-item>
|
|
63
|
+
<l-item label="Phone">{{ my.phone }}</l-item>
|
|
64
|
+
<l-item label="Address">{{ my.addr1 }} {{ my.addr2 }} {{ my.addr3 }}</l-item>
|
|
65
|
+
<l-item label="Join date">{{ my.join_date }}</l-item>
|
|
66
|
+
<l-item label="Roles">{{ my.roles.join(",") }}</l-item>
|
|
67
|
+
</l-list>
|
|
68
|
+
</l-card>
|
|
69
|
+
|
|
70
|
+
<l-card title="User Log">
|
|
71
|
+
<l-table :rows="my.userLog.data" :columns="userlogColumns" searchable :rows-per-page-options="[0]">
|
|
72
|
+
</l-table>
|
|
73
|
+
</l-card>
|
|
74
|
+
|
|
75
|
+
<l-card title="Event Log">
|
|
76
|
+
<l-table :rows="my.eventLog.data" :columns="eventLogCols" searchable :rows-per-page-options="[0]">
|
|
77
|
+
</l-table>
|
|
78
|
+
</l-card>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
23
81
|
|
|
24
82
|
</l-page>
|
|
25
83
|
</template>
|
package/dist/runtime/plugin.mjs
CHANGED
|
@@ -12,10 +12,14 @@ import { useLight } from "./index.mjs";
|
|
|
12
12
|
import TypeUser from "./types/User.mjs";
|
|
13
13
|
import TypeUserLog from "./types/UserLog.mjs";
|
|
14
14
|
import TypeSystemValue from "./types/SystemValue.mjs";
|
|
15
|
+
import TypeMailLog from "./types/MailLog.mjs";
|
|
16
|
+
import TypeEventLog from "./types/EventLog.mjs";
|
|
15
17
|
export default defineNuxtPlugin((nuxtApp) => {
|
|
16
18
|
defineModel("User", TypeUser);
|
|
17
19
|
defineModel("UserLog", TypeUserLog);
|
|
18
20
|
defineModel("SystemValue", TypeSystemValue);
|
|
21
|
+
defineModel("MailLog", TypeMailLog);
|
|
22
|
+
defineModel("EventLog", TypeEventLog);
|
|
19
23
|
nuxtApp.vueApp.config.errorHandler = (error) => {
|
|
20
24
|
console.log(error);
|
|
21
25
|
const light = useLight();
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
eventlog_id: {
|
|
3
|
+
label: string;
|
|
4
|
+
sortable: boolean;
|
|
5
|
+
searchable: boolean;
|
|
6
|
+
};
|
|
7
|
+
class: {
|
|
8
|
+
label: string;
|
|
9
|
+
sortable: boolean;
|
|
10
|
+
searchable: boolean;
|
|
11
|
+
};
|
|
12
|
+
id: {
|
|
13
|
+
label: string;
|
|
14
|
+
sortable: boolean;
|
|
15
|
+
searchable: boolean;
|
|
16
|
+
};
|
|
17
|
+
action: {
|
|
18
|
+
label: string;
|
|
19
|
+
sortable: boolean;
|
|
20
|
+
searchable: boolean;
|
|
21
|
+
};
|
|
22
|
+
created_time: {
|
|
23
|
+
label: string;
|
|
24
|
+
sortable: boolean;
|
|
25
|
+
searchable: boolean;
|
|
26
|
+
};
|
|
27
|
+
username: {
|
|
28
|
+
label: string;
|
|
29
|
+
sortable: boolean;
|
|
30
|
+
searchable: boolean;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export default _default;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
eventlog_id: {
|
|
3
|
+
label: "EventLog ID",
|
|
4
|
+
sortable: true,
|
|
5
|
+
searchable: true
|
|
6
|
+
},
|
|
7
|
+
class: {
|
|
8
|
+
label: "Class",
|
|
9
|
+
sortable: true,
|
|
10
|
+
searchable: true
|
|
11
|
+
},
|
|
12
|
+
id: {
|
|
13
|
+
label: "ID",
|
|
14
|
+
sortable: true,
|
|
15
|
+
searchable: true
|
|
16
|
+
},
|
|
17
|
+
action: {
|
|
18
|
+
label: "Action",
|
|
19
|
+
sortable: true,
|
|
20
|
+
searchable: true
|
|
21
|
+
},
|
|
22
|
+
created_time: {
|
|
23
|
+
label: "Created time",
|
|
24
|
+
sortable: true,
|
|
25
|
+
searchable: true
|
|
26
|
+
},
|
|
27
|
+
username: {
|
|
28
|
+
label: "Username",
|
|
29
|
+
sortable: true,
|
|
30
|
+
searchable: true
|
|
31
|
+
}
|
|
32
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
maillog_id: {
|
|
3
|
+
label: string;
|
|
4
|
+
sortable: boolean;
|
|
5
|
+
searchable: boolean;
|
|
6
|
+
searchType: string;
|
|
7
|
+
};
|
|
8
|
+
from: {
|
|
9
|
+
label: string;
|
|
10
|
+
sortable: boolean;
|
|
11
|
+
searchable: boolean;
|
|
12
|
+
};
|
|
13
|
+
to: {
|
|
14
|
+
label: string;
|
|
15
|
+
sortable: boolean;
|
|
16
|
+
searchable: boolean;
|
|
17
|
+
};
|
|
18
|
+
subject: {
|
|
19
|
+
label: string;
|
|
20
|
+
sortable: boolean;
|
|
21
|
+
searchable: boolean;
|
|
22
|
+
};
|
|
23
|
+
created_time: {
|
|
24
|
+
label: string;
|
|
25
|
+
sortable: boolean;
|
|
26
|
+
searchable: boolean;
|
|
27
|
+
searchType: string;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export default _default;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
maillog_id: {
|
|
3
|
+
label: "ID",
|
|
4
|
+
sortable: true,
|
|
5
|
+
searchable: true,
|
|
6
|
+
searchType: "number"
|
|
7
|
+
},
|
|
8
|
+
from: {
|
|
9
|
+
label: "From",
|
|
10
|
+
sortable: true,
|
|
11
|
+
searchable: true
|
|
12
|
+
},
|
|
13
|
+
to: {
|
|
14
|
+
label: "To",
|
|
15
|
+
sortable: true,
|
|
16
|
+
searchable: true
|
|
17
|
+
},
|
|
18
|
+
subject: {
|
|
19
|
+
label: "Subject",
|
|
20
|
+
sortable: true,
|
|
21
|
+
searchable: true
|
|
22
|
+
},
|
|
23
|
+
created_time: {
|
|
24
|
+
label: "Created time",
|
|
25
|
+
sortable: true,
|
|
26
|
+
searchable: true,
|
|
27
|
+
searchType: "date"
|
|
28
|
+
}
|
|
29
|
+
};
|
package/package.json
CHANGED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
export default [
|
|
2
|
-
{
|
|
3
|
-
label: "系統管理",
|
|
4
|
-
icon: "sym_o_settings",
|
|
5
|
-
menus: [
|
|
6
|
-
{
|
|
7
|
-
label: "使用者管理",
|
|
8
|
-
link: "/User",
|
|
9
|
-
icon: "sym_o_person"
|
|
10
|
-
}, {
|
|
11
|
-
label: "角色管理",
|
|
12
|
-
link: "/Role",
|
|
13
|
-
icon: "sym_o_group"
|
|
14
|
-
}, {
|
|
15
|
-
label: "權限管理",
|
|
16
|
-
link: "/Permission",
|
|
17
|
-
icon: "sym_o_key"
|
|
18
|
-
}, {
|
|
19
|
-
label: "系統設定",
|
|
20
|
-
link: "/Setting",
|
|
21
|
-
icon: "sym_o_settings"
|
|
22
|
-
}, {
|
|
23
|
-
label: "User log",
|
|
24
|
-
link: "/UserLog",
|
|
25
|
-
icon: "sym_o_description"
|
|
26
|
-
}, {
|
|
27
|
-
label: "Mail log",
|
|
28
|
-
link: "/MailLog",
|
|
29
|
-
icon: "sym_o_description"
|
|
30
|
-
}, {
|
|
31
|
-
label: "Event log",
|
|
32
|
-
link: "/EventLog",
|
|
33
|
-
icon: "sym_o_description"
|
|
34
|
-
}
|
|
35
|
-
]
|
|
36
|
-
}
|
|
37
|
-
];
|