@hostlink/nuxt-light 0.0.90 → 0.0.92
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 +0 -1
- package/dist/runtime/components/l-app.vue +11 -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-item.vue +0 -1
- package/dist/runtime/components/l-link.vue +2 -9
- package/dist/runtime/components/l-list.vue +19 -3
- package/dist/runtime/components/l-table.vue +31 -8
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.mjs +14 -0
- package/dist/runtime/lib/getGQLFields.mjs +5 -1
- package/dist/runtime/lib/getID.d.ts +1 -1
- package/dist/runtime/lib/getID.mjs +2 -10
- package/dist/runtime/lib/index.d.ts +1 -2
- package/dist/runtime/lib/index.mjs +0 -2
- package/dist/runtime/lib/list.d.ts +7 -1
- package/dist/runtime/lib/list.mjs +35 -32
- package/dist/runtime/lib/listObject.d.ts +2 -1
- package/dist/runtime/lib/listObject.mjs +8 -17
- package/dist/runtime/lib/loadObject.mjs +2 -2
- package/dist/runtime/locales/zh-hk.json +1 -0
- package/dist/runtime/pages/EventLog/index.vue +2 -38
- package/dist/runtime/pages/MailLog/index.vue +33 -32
- package/dist/runtime/pages/Permission/add.vue +2 -2
- package/dist/runtime/pages/Permission/export.vue +2 -2
- package/dist/runtime/pages/System/view_as.vue +1 -6
- package/dist/runtime/pages/Translate/index.vue +1 -1
- 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/index.vue +1 -1
- 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/dist/runtime/types/User.mjs +8 -0
- package/package.json +1 -1
- package/dist/runtime/lib/listData.d.ts +0 -1
- package/dist/runtime/lib/listData.mjs +0 -33
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { useLight } from "#imports";
|
|
2
|
+
import { useLight, watch } from "#imports";
|
|
3
3
|
import { useRuntimeConfig } from 'nuxt/app'
|
|
4
4
|
import { setApiUrl } from '@hostlink/light'
|
|
5
5
|
import { Dialog } from 'quasar'
|
|
6
6
|
import { q } from '../'
|
|
7
|
+
import { useRoute } from "#vue-router";
|
|
7
8
|
const config = useRuntimeConfig();
|
|
8
9
|
setApiUrl(config?.public?.apiBase ?? '/api/');
|
|
9
10
|
|
|
11
|
+
const route = useRoute();
|
|
12
|
+
const light = useLight()
|
|
13
|
+
|
|
14
|
+
light.setCurrentRoute(route);
|
|
15
|
+
watch(route, (to, from) => {
|
|
16
|
+
light.setCurrentRoute(to);
|
|
17
|
+
});
|
|
10
18
|
|
|
11
19
|
let app = null
|
|
12
|
-
const light = useLight()
|
|
13
20
|
try {
|
|
14
21
|
app = (await q({ app: ['company', 'companyLogo', 'logged', 'twoFactorAuthentication', 'googleClientId'] })).app;
|
|
15
22
|
light.setCompany(app.company);
|
|
@@ -30,13 +37,13 @@ try {
|
|
|
30
37
|
<q-layout v-if="!app.logged">
|
|
31
38
|
<q-page-container class="bg-grey-2" style="color:#1f1f1f">
|
|
32
39
|
<q-page padding>
|
|
33
|
-
<l-login :
|
|
40
|
+
<l-login :two-factor-authentication="app.twoFactorAuthentication"
|
|
34
41
|
:google-client-id="app.googleClientId"></l-login>
|
|
35
42
|
</q-page>
|
|
36
43
|
</q-page-container>
|
|
37
44
|
</q-layout>
|
|
38
45
|
|
|
39
|
-
<l-app-main>
|
|
46
|
+
<l-app-main v-else>
|
|
40
47
|
<slot></slot>
|
|
41
48
|
</l-app-main>
|
|
42
49
|
</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,5 +1,4 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { useRouter } from "vue-router"
|
|
3
2
|
const props = defineProps({
|
|
4
3
|
to: {
|
|
5
4
|
type: String,
|
|
@@ -11,15 +10,9 @@ const props = defineProps({
|
|
|
11
10
|
default: "primary"
|
|
12
11
|
},
|
|
13
12
|
})
|
|
14
|
-
const router = useRouter();
|
|
15
|
-
const navigate = () => {
|
|
16
|
-
if (props.to) {
|
|
17
|
-
router.push(props.to);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
13
|
</script>
|
|
21
14
|
<template>
|
|
22
|
-
<
|
|
15
|
+
<router-link :to="props.to" style="text-decoration: underline; color:var(--q-primary)">
|
|
23
16
|
<slot />
|
|
24
|
-
</
|
|
17
|
+
</router-link>
|
|
25
18
|
</template>
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
3
|
const props = defineProps({
|
|
6
4
|
modelValue: {
|
|
7
5
|
type: Object
|
|
@@ -11,11 +9,29 @@ const props = defineProps({
|
|
|
11
9
|
}
|
|
12
10
|
})
|
|
13
11
|
|
|
12
|
+
function getTo(field) {
|
|
13
|
+
|
|
14
|
+
const raw=field.getRaw();
|
|
15
|
+
|
|
16
|
+
if (raw.to) {
|
|
17
|
+
if (raw.to instanceof Function) {
|
|
18
|
+
return raw.to(props.modelValue);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (typeof raw.to == 'string') {
|
|
22
|
+
return raw.to;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
14
30
|
</script>
|
|
15
31
|
<template>
|
|
16
32
|
<q-list bordered separator>
|
|
17
33
|
<template v-if="fields">
|
|
18
|
-
<l-item v-for="field in fields" :label="field.getRaw().label">
|
|
34
|
+
<l-item v-for="field in fields" :label="field.getRaw().label" :to="getTo(field)">
|
|
19
35
|
{{ field.getFormattedValue(props.modelValue) }}
|
|
20
36
|
</l-item>
|
|
21
37
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { useQuasar, QTable } from 'quasar';
|
|
3
|
-
import { ref, computed, onMounted, useSlots,
|
|
4
|
-
import { t, deleteObject, q,
|
|
5
|
-
import { toQuery } from '@hostlink/light'
|
|
3
|
+
import { ref, computed, onMounted, useSlots, useAttrs } from "vue";
|
|
4
|
+
import { t, deleteObject, q, useLight, GQLFieldBuilder } from '../';
|
|
6
5
|
|
|
7
6
|
const errors = ref<InstanceType<any>>([]);
|
|
8
7
|
|
|
@@ -338,7 +337,9 @@ const getFilterValue = () => {
|
|
|
338
337
|
if (col.searchable) {
|
|
339
338
|
if (filters.value[col.name]) {
|
|
340
339
|
|
|
341
|
-
if (col.searchType == "
|
|
340
|
+
if (col.searchType == "number") {
|
|
341
|
+
f[col.name] = filters.value[col.name]
|
|
342
|
+
} else if (col.searchType == "date") {
|
|
342
343
|
if (filters.value[col.name].from) {
|
|
343
344
|
f[col.name] = {
|
|
344
345
|
between: [filters.value[col.name].from, filters.value[col.name].to]
|
|
@@ -406,7 +407,18 @@ const attrs = {
|
|
|
406
407
|
}
|
|
407
408
|
|
|
408
409
|
const filter = ref('');
|
|
410
|
+
|
|
411
|
+
const toColumns = props.columns?.filter((col: any) => {
|
|
412
|
+
return col.to;
|
|
413
|
+
}).map((col: any) => {
|
|
414
|
+
col.slot_name = 'body-cell-' + col.name;
|
|
415
|
+
return col;
|
|
416
|
+
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
console.log(ss);
|
|
409
420
|
</script>
|
|
421
|
+
|
|
410
422
|
<template>
|
|
411
423
|
<template v-if="errors.length > 0">
|
|
412
424
|
<div class="q-gutter-sm">
|
|
@@ -415,7 +427,8 @@ const filter = ref('');
|
|
|
415
427
|
</template>
|
|
416
428
|
|
|
417
429
|
<template v-if="debug">
|
|
418
|
-
<pre>
|
|
430
|
+
<pre>
|
|
431
|
+
primaryKey:{{ primaryKey }}
|
|
419
432
|
modelName:{{ modelName }}
|
|
420
433
|
filters:{{ filters }}
|
|
421
434
|
pagination:{{ pagination }}
|
|
@@ -428,6 +441,7 @@ const filter = ref('');
|
|
|
428
441
|
rows:{{ props.rows }}
|
|
429
442
|
</template>
|
|
430
443
|
|
|
444
|
+
|
|
431
445
|
<q-table v-bind="attrs" :row-key="rowKey" :loading="loading" :rows="rows" ref="table" @request="onRequest"
|
|
432
446
|
:rows-per-page-label="$t(props.rowsPerPageLabel)" :columns="renderColumns"
|
|
433
447
|
:rows-per-page-options="rowsPerPageOptions" :selection="selection" v-model:pagination="pagination" :filter="filter">
|
|
@@ -441,15 +455,19 @@ const filter = ref('');
|
|
|
441
455
|
|
|
442
456
|
<q-btn v-if="fullscreen" flat round dense :icon="props.inFullscreen ? 'fullscreen_exit' : 'fullscreen'"
|
|
443
457
|
@click="props.toggleFullscreen" class="q-ml-md" />
|
|
444
|
-
|
|
445
|
-
|
|
446
458
|
</template>
|
|
447
459
|
|
|
448
|
-
|
|
449
460
|
<template v-for="s in ss" v-slot:[s]="props">
|
|
450
461
|
<slot :name="s" v-bind="props"></slot>
|
|
451
462
|
</template>
|
|
452
463
|
|
|
464
|
+
<template v-for="col in toColumns" v-slot:[col.slot_name]="props">
|
|
465
|
+
<q-td :props="props">
|
|
466
|
+
<l-link :to="col.to(props.row)">
|
|
467
|
+
{{ col.field(props.row) }}
|
|
468
|
+
</l-link>
|
|
469
|
+
</q-td>
|
|
470
|
+
</template>
|
|
453
471
|
|
|
454
472
|
<template #body-cell-_actions="props">
|
|
455
473
|
<q-td :props="props" auto-width>
|
|
@@ -479,6 +497,11 @@ const filter = ref('');
|
|
|
479
497
|
<q-td v-for="col in props.cols">
|
|
480
498
|
<template v-if="col.searchable">
|
|
481
499
|
|
|
500
|
+
<template v-if="col.searchType == 'number'">
|
|
501
|
+
<q-input dense clearable v-model.number="filters[col.name]" @keydown.enter.prevent="onFilters"
|
|
502
|
+
@clear="onFilters" mask="##########"></q-input>
|
|
503
|
+
</template>
|
|
504
|
+
|
|
482
505
|
<template v-if="col.searchType == 'select'">
|
|
483
506
|
<q-select dense v-model="filters[col.name]" @update:model-value="onFilters" clearable
|
|
484
507
|
:options="col.searchOptions" @clear="onFilters" emit-value />
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ interface Light {
|
|
|
9
9
|
setCompany(company: string): void;
|
|
10
10
|
getCompanyLogo(): string;
|
|
11
11
|
setCompanyLogo(logo: string): void;
|
|
12
|
+
setCurrentRoute(to: any, from: any): void;
|
|
13
|
+
getID(): Number | null;
|
|
12
14
|
}
|
|
13
15
|
export declare const useLight: () => Light;
|
|
14
16
|
export * from "./lib";
|
package/dist/runtime/index.mjs
CHANGED
|
@@ -5,6 +5,7 @@ const app = {
|
|
|
5
5
|
company: "",
|
|
6
6
|
companyLogo: ""
|
|
7
7
|
};
|
|
8
|
+
let currentRoute = null;
|
|
8
9
|
export const useLight = () => {
|
|
9
10
|
return {
|
|
10
11
|
setCompany: (company) => {
|
|
@@ -42,6 +43,19 @@ export const useLight = () => {
|
|
|
42
43
|
},
|
|
43
44
|
setStyles(s) {
|
|
44
45
|
styles = s;
|
|
46
|
+
},
|
|
47
|
+
setCurrentRoute(to, from) {
|
|
48
|
+
currentRoute = to;
|
|
49
|
+
},
|
|
50
|
+
getID() {
|
|
51
|
+
if (currentRoute == null)
|
|
52
|
+
return null;
|
|
53
|
+
let name = currentRoute.name?.toString();
|
|
54
|
+
if (name == void 0)
|
|
55
|
+
return 0;
|
|
56
|
+
let parts = name.split("-");
|
|
57
|
+
const keyname = parts[1];
|
|
58
|
+
return parseInt(currentRoute.params[keyname]);
|
|
45
59
|
}
|
|
46
60
|
};
|
|
47
61
|
};
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import GQLFieldBuilder from "./GQLFieldBuilder.mjs";
|
|
2
|
+
import { getModelField } from "@hostlink/light";
|
|
2
3
|
export default (name, fields) => {
|
|
3
4
|
const builder = GQLFieldBuilder();
|
|
4
5
|
fields.forEach((field) => {
|
|
5
|
-
|
|
6
|
+
const modelField = getModelField(name, field);
|
|
7
|
+
if (modelField) {
|
|
8
|
+
builder.add(modelField.getGQLField());
|
|
9
|
+
}
|
|
6
10
|
});
|
|
7
11
|
return builder.get();
|
|
8
12
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: () => Number;
|
|
1
|
+
declare const _default: () => Number | null;
|
|
2
2
|
export default _default;
|
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const route = useRoute();
|
|
1
|
+
import { useLight } from "../index.mjs";
|
|
3
2
|
export default () => {
|
|
4
|
-
|
|
5
|
-
if (name == void 0)
|
|
6
|
-
return 0;
|
|
7
|
-
let parts = name.split("-");
|
|
8
|
-
const module = parts[0];
|
|
9
|
-
const moduleLower = module.charAt(0).toLowerCase() + module.slice(1);
|
|
10
|
-
const keyname = parts[1];
|
|
11
|
-
return parseInt(route.params[keyname]);
|
|
3
|
+
return useLight().getID();
|
|
12
4
|
};
|
|
@@ -4,7 +4,6 @@ import getApiUrl from "./getApiUrl";
|
|
|
4
4
|
import getCurrentUser from "./getCurrentUser";
|
|
5
5
|
import getObject from "./getObject";
|
|
6
6
|
import list from "./list";
|
|
7
|
-
import listData from "./listData";
|
|
8
7
|
import m from "./m";
|
|
9
8
|
import q from "./q";
|
|
10
9
|
import removeObject from "./removeObject";
|
|
@@ -22,4 +21,4 @@ declare const notify: (message: string, color?: string) => void;
|
|
|
22
21
|
import getID from "./getID";
|
|
23
22
|
declare const getApiBase: () => {};
|
|
24
23
|
import { getGQLFields } from '@hostlink/light';
|
|
25
|
-
export { addObject, f, getApiUrl, getCurrentUser, getObject, list,
|
|
24
|
+
export { addObject, f, getApiUrl, getCurrentUser, getObject, list, m, q, removeObject, t, updateObject, notify, getID, deleteObject, listObject, isGranted, getApiBase, loadObject, GQLFieldBuilder, getModelField, getModelFields, getModelColumns, getGQLFields };
|
|
@@ -6,7 +6,6 @@ import getApiUrl from "./getApiUrl.mjs";
|
|
|
6
6
|
import getCurrentUser from "./getCurrentUser.mjs";
|
|
7
7
|
import getObject from "./getObject.mjs";
|
|
8
8
|
import list from "./list.mjs";
|
|
9
|
-
import listData from "./listData.mjs";
|
|
10
9
|
import m from "./m.mjs";
|
|
11
10
|
import q from "./q.mjs";
|
|
12
11
|
import removeObject from "./removeObject.mjs";
|
|
@@ -40,7 +39,6 @@ export {
|
|
|
40
39
|
getCurrentUser,
|
|
41
40
|
getObject,
|
|
42
41
|
list,
|
|
43
|
-
listData,
|
|
44
42
|
m,
|
|
45
43
|
q,
|
|
46
44
|
removeObject,
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import { Fields } from "@hostlink/light";
|
|
2
|
+
export default function list(name: string, props?: {
|
|
3
|
+
sort?: string;
|
|
4
|
+
filters?: object;
|
|
5
|
+
offset?: number;
|
|
6
|
+
limit?: number;
|
|
7
|
+
} | null, fields?: Fields): Promise<any>;
|
|
@@ -1,35 +1,38 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { query, toQuery } from "@hostlink/light";
|
|
2
|
+
export default async function list(name, props = null, fields = []) {
|
|
3
|
+
let q = {};
|
|
4
|
+
if (props) {
|
|
5
|
+
if (props.sort) {
|
|
6
|
+
q.__args = q.__args || {};
|
|
7
|
+
q.__args.sort = props.sort;
|
|
8
|
+
}
|
|
9
|
+
if (props.filters) {
|
|
10
|
+
q.__args = q.__args || {};
|
|
11
|
+
q.__args.filters = props.filters;
|
|
12
|
+
}
|
|
7
13
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
q.data = {};
|
|
15
|
+
if (props) {
|
|
16
|
+
if (props.offset) {
|
|
17
|
+
q.data.__args = q.data.__args || {};
|
|
18
|
+
q.data.__args.offset = props.offset;
|
|
19
|
+
}
|
|
20
|
+
if (props.limit) {
|
|
21
|
+
q.data.__args = q.data.__args || {};
|
|
22
|
+
q.data.__args.limit = props.limit;
|
|
23
|
+
}
|
|
13
24
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
props.done({
|
|
28
|
-
rows: data.data,
|
|
29
|
-
total: data.meta.total,
|
|
30
|
-
key: data.meta.key,
|
|
31
|
-
name: data.meta.name
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
return data.data;
|
|
25
|
+
q.data = {
|
|
26
|
+
...q.data,
|
|
27
|
+
...toQuery(fields)
|
|
28
|
+
};
|
|
29
|
+
q.meta = {
|
|
30
|
+
total: true,
|
|
31
|
+
key: true,
|
|
32
|
+
name: true
|
|
33
|
+
};
|
|
34
|
+
const resp = await query({
|
|
35
|
+
[`list${name}`]: q
|
|
36
|
+
});
|
|
37
|
+
return resp[`list${name}`];
|
|
35
38
|
}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { Fields } from "@hostlink/light";
|
|
2
|
+
export default function listObject(name: string, filters: {} | undefined, sort: string, offset: number, limit: number, fields?: Fields): Promise<any>;
|
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import f from "./f.mjs";
|
|
1
|
+
import list from "./list.mjs";
|
|
3
2
|
export default async function listObject(name, filters = {}, sort, offset, limit, fields = []) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
let params = {};
|
|
12
|
-
if (sort) {
|
|
13
|
-
params.sort = sort;
|
|
14
|
-
}
|
|
15
|
-
if (filters) {
|
|
16
|
-
params.filters = filters;
|
|
17
|
-
}
|
|
18
|
-
return await q(`list${name}`, params, [f("data", offset_limit, fields), f("meta", ["total", "key", "name"])]);
|
|
3
|
+
const resp = await list(name, {
|
|
4
|
+
filters,
|
|
5
|
+
sort,
|
|
6
|
+
offset,
|
|
7
|
+
limit
|
|
8
|
+
}, fields);
|
|
9
|
+
return resp.data;
|
|
19
10
|
}
|
|
@@ -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>
|
|
@@ -31,10 +31,10 @@ const onSave = async () => {
|
|
|
31
31
|
|
|
32
32
|
<l-input label="Permission name" v-model="obj.value" required></l-input>
|
|
33
33
|
|
|
34
|
-
<
|
|
34
|
+
<l-field label="Roles" stack-label>
|
|
35
35
|
<q-option-group type="checkbox" :options="roles" v-model="obj.roles" inline>
|
|
36
36
|
</q-option-group>
|
|
37
|
-
</
|
|
37
|
+
</l-field>
|
|
38
38
|
|
|
39
39
|
</l-form>
|
|
40
40
|
|
|
@@ -62,10 +62,10 @@ const submit = () => {
|
|
|
62
62
|
<template>
|
|
63
63
|
<l-page>
|
|
64
64
|
<l-form submit-label="Export" submit-icon="sym_o_download" @submit="submit">
|
|
65
|
-
<
|
|
65
|
+
<l-field label="Roles" stack-label>
|
|
66
66
|
<q-option-group type="checkbox" :options="roles" v-model="obj.roles" inline>
|
|
67
67
|
</q-option-group>
|
|
68
|
-
</
|
|
68
|
+
</l-field>
|
|
69
69
|
</l-form>
|
|
70
70
|
|
|
71
71
|
|
|
@@ -2,11 +2,7 @@
|
|
|
2
2
|
import { list, m } from '../../'
|
|
3
3
|
import { useRouter } from "vue-router"
|
|
4
4
|
|
|
5
|
-
let users = await list("User",
|
|
6
|
-
fields: [
|
|
7
|
-
"user_id", "username", "name", "roles"
|
|
8
|
-
]
|
|
9
|
-
});
|
|
5
|
+
let { data: users } = await list("User", null, ["user_id", "username", "name", "roles"]);
|
|
10
6
|
|
|
11
7
|
let columns = [
|
|
12
8
|
{
|
|
@@ -44,7 +40,6 @@ const onCickView = async (id) => {
|
|
|
44
40
|
</script>
|
|
45
41
|
<template>
|
|
46
42
|
<l-page>
|
|
47
|
-
|
|
48
43
|
<q-table flat :columns="columns" :rows="users">
|
|
49
44
|
<template #body-cell-view="props">
|
|
50
45
|
<q-td :props="props">
|
|
@@ -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>
|
|
@@ -4,7 +4,7 @@ import getModelColumns from "../../lib/getModelColumns";
|
|
|
4
4
|
const onRequest = async (request) => {
|
|
5
5
|
request.loadObjects("User", { status: status.value });
|
|
6
6
|
};
|
|
7
|
-
const columns = getModelColumns("User", ["username", "first_name", "label_name", "email", "phone", "join_date", "status"]);
|
|
7
|
+
const columns = getModelColumns("User", [ "username", "first_name", "label_name", "email", "phone", "join_date", "status"]);
|
|
8
8
|
const status = ref("0");
|
|
9
9
|
</script>
|
|
10
10
|
|
|
@@ -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
|
+
};
|
|
@@ -40,4 +40,12 @@ export default {
|
|
|
40
40
|
return ["Active", "Inactive"][value];
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
+
/* ,
|
|
44
|
+
test: {
|
|
45
|
+
label: "Test",
|
|
46
|
+
name: "_test",
|
|
47
|
+
to: (row: any) => `/User/${row.user_id}/view`,
|
|
48
|
+
gqlField: ["user_id", "first_name"],
|
|
49
|
+
field: (row: any) => row.first_name,
|
|
50
|
+
} */
|
|
43
51
|
};
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default function listData(name: string, props?: any, fields?: Array<string | Object> | Object): Promise<any>;
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { query, toQuery } from "@hostlink/light";
|
|
2
|
-
export default async function listData(name, props = {}, fields = []) {
|
|
3
|
-
let json = {};
|
|
4
|
-
if (props.sort) {
|
|
5
|
-
json.__args = json.__args || {};
|
|
6
|
-
json.__args.sort = props.sort;
|
|
7
|
-
}
|
|
8
|
-
if (props.filters) {
|
|
9
|
-
json.__args = json.__args || {};
|
|
10
|
-
json.__args.filters = props.filters;
|
|
11
|
-
}
|
|
12
|
-
json.data = {};
|
|
13
|
-
if (props.offset) {
|
|
14
|
-
json.data.__args = json.data.__args || {};
|
|
15
|
-
json.data.__args.offset = props.offset;
|
|
16
|
-
}
|
|
17
|
-
if (props.limit) {
|
|
18
|
-
json.data.__args = json.data.__args || {};
|
|
19
|
-
json.data.__args.limit = props.limit;
|
|
20
|
-
}
|
|
21
|
-
Object.entries(toQuery(fields)).forEach(([key, value]) => {
|
|
22
|
-
json.data[key] = value;
|
|
23
|
-
});
|
|
24
|
-
json.meta = {
|
|
25
|
-
total: true,
|
|
26
|
-
key: true,
|
|
27
|
-
name: true
|
|
28
|
-
};
|
|
29
|
-
const q = {};
|
|
30
|
-
q[`list${name}`] = json;
|
|
31
|
-
let data = await query(q);
|
|
32
|
-
return data[`list${name}`];
|
|
33
|
-
}
|