@hostlink/nuxt-light 1.35.0 → 1.37.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/runtime/components/L/System/Setting/developer.vue +11 -28
- package/dist/runtime/components/L/System/Setting/developer.vue.d.ts +8 -8
- package/dist/runtime/components/L/System/Setting/forget-password.vue +13 -33
- package/dist/runtime/components/L/System/Setting/forget-password.vue.d.ts +10 -9
- package/dist/runtime/components/L/System/Setting/general.vue +12 -19
- package/dist/runtime/components/L/System/Setting/general.vue.d.ts +16 -23
- package/dist/runtime/components/L/User/overview.vue +19 -26
- package/dist/runtime/components/l-app-main.vue +7 -9
- package/dist/runtime/components/l-app-main.vue.d.ts +2 -2
- package/dist/runtime/components/l-fav-menu.vue +1 -1
- package/dist/runtime/components/l-item.vue.d.ts +2 -2
- package/dist/runtime/components/l-select.vue +11 -5
- package/dist/runtime/components/l-table.vue +15 -7
- package/dist/runtime/components/l-table.vue.d.ts +1 -1
- package/dist/runtime/composables/defineLightModel.d.ts +2 -0
- package/dist/runtime/composables/useLight.d.ts +4 -4
- package/dist/runtime/composables/useLight.js +2 -1
- package/dist/runtime/pages/System/setting.vue +3 -3
- package/dist/runtime/pages/User/_user_id/view.vue +13 -14
- package/dist/runtime/pages/User/setting/my_favorite.vue +131 -41
- package/dist/runtime/types/User.d.ts +1 -1
- package/dist/runtime/types/User.js +1 -1
- package/package.json +2 -2
package/dist/module.json
CHANGED
|
@@ -2,40 +2,23 @@
|
|
|
2
2
|
import { q, m } from "#imports";
|
|
3
3
|
import { useQuasar } from "quasar";
|
|
4
4
|
const $q = useQuasar();
|
|
5
|
-
const
|
|
6
|
-
required: true
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
if (modelValue.value.custom_field_models) {
|
|
14
|
-
modelValue.value.custom_field_models = modelValue.value.custom_field_models.split(",");
|
|
15
|
-
} else {
|
|
16
|
-
modelValue.value.custom_field_models = [];
|
|
17
|
-
}
|
|
5
|
+
const props = defineProps({
|
|
6
|
+
mode: { type: String, required: true, default: "dev" },
|
|
7
|
+
custom_field_models: { type: String, required: true, default: "" }
|
|
8
|
+
});
|
|
9
|
+
const emit = defineEmits(["submit"]);
|
|
10
|
+
const processedMode = props.mode !== "prod" ? "dev" : "prod";
|
|
11
|
+
const processedCustomFieldModels = props.custom_field_models ? props.custom_field_models.split(",") : [];
|
|
18
12
|
const onSubmit = async (d) => {
|
|
19
|
-
|
|
20
|
-
Object.keys(d).forEach((key) => {
|
|
21
|
-
data.push({
|
|
22
|
-
name: key,
|
|
23
|
-
value: d[key]
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
await m("updateAppConfigs", { data });
|
|
27
|
-
Object.keys(d).forEach((key) => {
|
|
28
|
-
modelValue.value[key] = d[key];
|
|
29
|
-
});
|
|
30
|
-
$q.notify({ message: "Settings saved", color: "positive" });
|
|
13
|
+
emit("submit", d);
|
|
31
14
|
};
|
|
32
15
|
</script>
|
|
33
16
|
|
|
34
17
|
<template>
|
|
35
18
|
<FormKit type="l-form" :bordered="false" :value="{
|
|
36
|
-
mode:
|
|
37
|
-
custom_field_models:
|
|
38
|
-
}" @submit="onSubmit"
|
|
19
|
+
mode: processedMode,
|
|
20
|
+
custom_field_models: processedCustomFieldModels
|
|
21
|
+
}" @submit="onSubmit">
|
|
39
22
|
|
|
40
23
|
<form-kit type="l-select" name="custom_field_models" label="Custom Field Model" use-input use-chips multiple
|
|
41
24
|
hide-dropdown-icon input-debounce="0" new-value-mode="add-unique" />
|
|
@@ -2,12 +2,12 @@ export interface LSystemSettingDeveloperProps {
|
|
|
2
2
|
mode: string;
|
|
3
3
|
custom_field_models: string;
|
|
4
4
|
}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
5
|
+
declare const _default: import("vue").DefineComponent<LSystemSettingDeveloperProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
+
submit: (data: Record<string, any>) => any;
|
|
7
|
+
}, string, import("vue").PublicProps, Readonly<LSystemSettingDeveloperProps> & Readonly<{
|
|
8
|
+
onSubmit?: ((data: Record<string, any>) => any) | undefined;
|
|
9
|
+
}>, {
|
|
10
|
+
mode: string;
|
|
11
|
+
custom_field_models: string;
|
|
12
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
13
13
|
export default _default;
|
|
@@ -1,43 +1,23 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
if (!modelValue.value.forget_password_subject) {
|
|
12
|
-
modelValue.value.forget_password_subject = "Password Reset Code";
|
|
13
|
-
}
|
|
14
|
-
if (!modelValue.value.forget_password_template) {
|
|
15
|
-
modelValue.value.forget_password_template = "Your password reset code is: {code}";
|
|
16
|
-
}
|
|
2
|
+
const props = defineProps({
|
|
3
|
+
forget_password_enabled: { type: String, required: false, default: "0" },
|
|
4
|
+
forget_password_subject: { type: String, required: false, default: "" },
|
|
5
|
+
forget_password_template: { type: String, required: false, default: "" }
|
|
6
|
+
});
|
|
7
|
+
const emit = defineEmits(["submit"]);
|
|
8
|
+
const processedEnabled = props.forget_password_enabled !== "0" ? "1" : props.forget_password_enabled;
|
|
9
|
+
const processedSubject = props.forget_password_subject || "Password Reset Code";
|
|
10
|
+
const processedTemplate = props.forget_password_template || "Your password reset code is: {code}";
|
|
17
11
|
const onSubmit = async (d) => {
|
|
18
|
-
|
|
19
|
-
Object.keys(d).forEach((key) => {
|
|
20
|
-
if (d[key] === void 0) {
|
|
21
|
-
d[key] = "";
|
|
22
|
-
}
|
|
23
|
-
data.push({
|
|
24
|
-
name: key,
|
|
25
|
-
value: d[key]
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
await m("updateAppConfigs", { data });
|
|
29
|
-
modelValue.value.forget_password_enabled = d.forget_password_enabled;
|
|
30
|
-
modelValue.value.forget_password_subject = d.forget_password_subject;
|
|
31
|
-
modelValue.value.forget_password_template = d.forget_password_template;
|
|
32
|
-
$q.notify({ message: "Settings saved", color: "positive" });
|
|
12
|
+
emit("submit", d);
|
|
33
13
|
};
|
|
34
14
|
</script>
|
|
35
15
|
|
|
36
16
|
<template>
|
|
37
17
|
<form-kit type="l-form" :value="{
|
|
38
|
-
forget_password_enabled:
|
|
39
|
-
forget_password_subject:
|
|
40
|
-
forget_password_template:
|
|
18
|
+
forget_password_enabled: processedEnabled,
|
|
19
|
+
forget_password_subject: processedSubject,
|
|
20
|
+
forget_password_template: processedTemplate
|
|
41
21
|
}" @submit="onSubmit">
|
|
42
22
|
<form-kit type="l-checkbox" label="Forget Password Enabled" name="forget_password_enabled" true-value="1"
|
|
43
23
|
false-value="0" />
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
export type LSystemSettingForgetPasswordProps = {
|
|
2
|
+
forget_password_enabled?: string;
|
|
3
|
+
forget_password_subject?: string;
|
|
4
|
+
forget_password_template?: string;
|
|
5
|
+
};
|
|
6
|
+
declare const _default: import("vue").DefineComponent<LSystemSettingForgetPasswordProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
7
|
+
submit: (data: Record<string, any>) => any;
|
|
8
|
+
}, string, import("vue").PublicProps, Readonly<LSystemSettingForgetPasswordProps> & Readonly<{
|
|
9
|
+
onSubmit?: ((data: Record<string, any>) => any) | undefined;
|
|
10
|
+
}>, {
|
|
2
11
|
forget_password_enabled: string;
|
|
3
12
|
forget_password_subject: string;
|
|
4
13
|
forget_password_template: string;
|
|
5
|
-
}
|
|
6
|
-
type __VLS_PublicProps = {
|
|
7
|
-
modelValue: LSystemSettingForgetPasswordProps;
|
|
8
|
-
};
|
|
9
|
-
declare const _default: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
10
|
-
"update:modelValue": (value: LSystemSettingForgetPasswordProps) => any;
|
|
11
|
-
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
12
|
-
"onUpdate:modelValue"?: ((value: LSystemSettingForgetPasswordProps) => any) | undefined;
|
|
13
|
-
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
14
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
14
15
|
export default _default;
|
|
@@ -1,30 +1,23 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { q, m } from "#imports";
|
|
3
2
|
import { useQuasar } from "quasar";
|
|
4
|
-
const
|
|
5
|
-
|
|
3
|
+
const props = defineProps({
|
|
4
|
+
company: { type: String, required: false, default: "" },
|
|
5
|
+
company_logo: { type: String, required: false, default: "" },
|
|
6
|
+
copyright_name: { type: String, required: false, default: "" },
|
|
7
|
+
copyright_year: { type: String, required: false, default: "" }
|
|
8
|
+
});
|
|
9
|
+
const emit = defineEmits(["submit"]);
|
|
6
10
|
const onSubmit = async (d, form) => {
|
|
7
|
-
|
|
8
|
-
Object.keys(d).forEach((key) => {
|
|
9
|
-
data.push({
|
|
10
|
-
name: key,
|
|
11
|
-
value: d[key]
|
|
12
|
-
});
|
|
13
|
-
});
|
|
14
|
-
await m("updateAppConfigs", { data });
|
|
15
|
-
Object.keys(d).forEach((key) => {
|
|
16
|
-
modelValue.value[key] = d[key];
|
|
17
|
-
});
|
|
18
|
-
$q.notify({ message: "Settings saved", color: "positive" });
|
|
11
|
+
emit("submit", d);
|
|
19
12
|
};
|
|
20
13
|
</script>
|
|
21
14
|
|
|
22
15
|
<template>
|
|
23
16
|
<FormKit type="l-form" :bordered="false" :value="{
|
|
24
|
-
company:
|
|
25
|
-
company_logo:
|
|
26
|
-
copyright_name:
|
|
27
|
-
copyright_year:
|
|
17
|
+
company: props.company,
|
|
18
|
+
company_logo: props.company_logo,
|
|
19
|
+
copyright_name: props.copyright_name,
|
|
20
|
+
copyright_year: props.copyright_year
|
|
28
21
|
}" @submit="onSubmit">
|
|
29
22
|
|
|
30
23
|
<FormKit type="l-input" label="Company" name="company" validation="required"></FormKit>
|
|
@@ -1,24 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}, string, import("vue").
|
|
17
|
-
"onUpdate:modelValue"?: ((value: {
|
|
18
|
-
company: string;
|
|
19
|
-
company_logo: string;
|
|
20
|
-
copyright_name: string;
|
|
21
|
-
copyright_year: string;
|
|
22
|
-
} | undefined) => any) | undefined;
|
|
23
|
-
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
1
|
+
interface Props {
|
|
2
|
+
company?: string;
|
|
3
|
+
company_logo?: string;
|
|
4
|
+
copyright_name?: string;
|
|
5
|
+
copyright_year?: string;
|
|
6
|
+
}
|
|
7
|
+
declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
8
|
+
submit: (data: Record<string, any>) => any;
|
|
9
|
+
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
10
|
+
onSubmit?: ((data: Record<string, any>) => any) | undefined;
|
|
11
|
+
}>, {
|
|
12
|
+
company: string;
|
|
13
|
+
company_logo: string;
|
|
14
|
+
copyright_name: string;
|
|
15
|
+
copyright_year: string;
|
|
16
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
24
17
|
export default _default;
|
|
@@ -21,30 +21,23 @@ const obj = await collect("User", {
|
|
|
21
21
|
</script>
|
|
22
22
|
|
|
23
23
|
<template>
|
|
24
|
-
<
|
|
25
|
-
<q-
|
|
26
|
-
<l-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}}</l-item>
|
|
44
|
-
</q-list>
|
|
45
|
-
</l-col>
|
|
46
|
-
|
|
47
|
-
</l-row>
|
|
48
|
-
</q-card-section>
|
|
49
|
-
</l-card>
|
|
24
|
+
<div class="row q-gutter-md">
|
|
25
|
+
<q-list dense separator class="col-md-6 col-sm-12">
|
|
26
|
+
<l-item label="Username">{{ obj.username }}</l-item>
|
|
27
|
+
<l-item label="First name">{{ obj.first_name }}</l-item>
|
|
28
|
+
<l-item label="Last name">{{ obj.last_name }}</l-item>
|
|
29
|
+
<l-item label="Email">{{ obj.email }}</l-item>
|
|
30
|
+
<l-item label="Phone">{{ obj.phone }}</l-item>
|
|
31
|
+
<l-item label="Roles">
|
|
32
|
+
<div class="q-gutter-xs float-left">
|
|
33
|
+
<q-badge v-for="role in obj.roles" :key="role" :color="$light.color">{{ role
|
|
34
|
+
}}</q-badge>
|
|
35
|
+
</div>
|
|
36
|
+
</l-item>
|
|
37
|
+
<l-item label="Status">{{ model("User").columns(["status"])[0].format(obj.status) }}</l-item>
|
|
38
|
+
<l-item label="Join date">{{ obj.join_date }}</l-item>
|
|
39
|
+
<l-item label="Two factor authentication">{{ obj.twoFactorEnabled ? "Yes" : "No"
|
|
40
|
+
}}</l-item>
|
|
41
|
+
</q-list>
|
|
42
|
+
</div>
|
|
50
43
|
</template>
|
|
@@ -183,7 +183,7 @@ const onToggleFav = async () => {
|
|
|
183
183
|
message: "Enter favorite label",
|
|
184
184
|
prompt: {
|
|
185
185
|
//get window title, remove - and replace with space
|
|
186
|
-
model: route.name.replace(/-/g, " "),
|
|
186
|
+
model: String(route.name || "Untitled").replace(/-/g, " "),
|
|
187
187
|
isValid: (val) => val !== ""
|
|
188
188
|
},
|
|
189
189
|
cancel: true,
|
|
@@ -237,12 +237,10 @@ const onLogout = async () => {
|
|
|
237
237
|
</template>
|
|
238
238
|
</q-toolbar-title>
|
|
239
239
|
|
|
240
|
-
|
|
241
|
-
<slot name="header" ></slot>
|
|
242
|
-
|
|
243
|
-
|
|
244
240
|
<q-space />
|
|
245
241
|
|
|
242
|
+
<slot name="header"></slot>
|
|
243
|
+
|
|
246
244
|
<q-btn :icon="isFav ? 'favorite' : 'sym_o_favorite'" round flat dense class="q-mr-xs"
|
|
247
245
|
@click="onToggleFav" v-if="app.hasFavorite">
|
|
248
246
|
</q-btn>
|
|
@@ -293,11 +291,11 @@ const onLogout = async () => {
|
|
|
293
291
|
<q-btn flat round dense icon="sym_o_person" class="q-mr-sm">
|
|
294
292
|
<q-menu max-width="250px">
|
|
295
293
|
<q-list>
|
|
296
|
-
<q-item v-close-popup to="/User/profile"
|
|
294
|
+
<q-item v-close-popup to="/User/profile">
|
|
297
295
|
<q-item-section avatar>
|
|
298
296
|
<q-icon name="sym_o_person" />
|
|
299
297
|
</q-item-section>
|
|
300
|
-
<q-item-section
|
|
298
|
+
<q-item-section>{{ $t("Profile") }}</q-item-section>
|
|
301
299
|
</q-item>
|
|
302
300
|
|
|
303
301
|
<q-item v-close-popup to="/User/setting">
|
|
@@ -365,12 +363,12 @@ const onLogout = async () => {
|
|
|
365
363
|
<q-expansion-item expand-separator :label="error.message">
|
|
366
364
|
<q-card>
|
|
367
365
|
<q-card-section style="white-space: pre-wrap; overflow: auto;">
|
|
368
|
-
|
|
366
|
+
{{ error.stack }}
|
|
369
367
|
</q-card-section>
|
|
370
368
|
</q-card>
|
|
371
369
|
</q-expansion-item>
|
|
372
370
|
|
|
373
|
-
<template v-slot:action>
|
|
371
|
+
<template v-slot:action>
|
|
374
372
|
<q-btn flat icon="sym_o_close" round dense @click="$light.removeError(error)" />
|
|
375
373
|
</template>
|
|
376
374
|
</q-banner>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
declare var
|
|
1
|
+
declare var __VLS_30: {};
|
|
2
2
|
type __VLS_Slots = {} & {
|
|
3
|
-
header?: (props: typeof
|
|
3
|
+
header?: (props: typeof __VLS_30) => any;
|
|
4
4
|
};
|
|
5
5
|
declare const __VLS_component: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
6
|
logout: (...args: any[]) => void;
|
|
@@ -19,7 +19,7 @@ const color2 = computed(() => {
|
|
|
19
19
|
|
|
20
20
|
<template>
|
|
21
21
|
<q-expansion-item :label="$t('My favorite')" :dense="dense" icon="sym_o_favorite">
|
|
22
|
-
<q-list class="q-pl-md menu-list">
|
|
22
|
+
<q-list class="q-pl-md menu-list" :dense="dense">
|
|
23
23
|
<q-item v-ripple :to="item.path" v-for="item in value">
|
|
24
24
|
<q-item-section avatar>
|
|
25
25
|
<q-icon :name="item.icon ?? 'sym_o_link'" />
|
|
@@ -4,7 +4,7 @@ export interface LItemProps extends QItemProps {
|
|
|
4
4
|
name?: string;
|
|
5
5
|
top?: boolean;
|
|
6
6
|
labelTop?: boolean;
|
|
7
|
-
alignItems?: 'flex-start' | 'center' | 'flex-end';
|
|
7
|
+
alignItems?: 'flex-start' | 'center' | 'flex-end' | 'stretch';
|
|
8
8
|
}
|
|
9
9
|
declare var __VLS_10: {}, __VLS_24: {}, __VLS_30: {};
|
|
10
10
|
type __VLS_Slots = {} & {
|
|
@@ -15,7 +15,7 @@ type __VLS_Slots = {} & {
|
|
|
15
15
|
end?: (props: typeof __VLS_30) => any;
|
|
16
16
|
};
|
|
17
17
|
declare const __VLS_component: import("vue").DefineComponent<LItemProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<LItemProps> & Readonly<{}>, {
|
|
18
|
-
alignItems: "flex-start" | "center" | "flex-end";
|
|
18
|
+
alignItems: "flex-start" | "center" | "flex-end" | "stretch";
|
|
19
19
|
top: boolean;
|
|
20
20
|
labelTop: boolean;
|
|
21
21
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -115,15 +115,21 @@ const normalizeOption = (option) => {
|
|
|
115
115
|
return option;
|
|
116
116
|
};
|
|
117
117
|
const normalizeOptions = (options) => {
|
|
118
|
+
if (!options) {
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
118
121
|
if (Array.isArray(options)) {
|
|
119
122
|
return options.map((option) => normalizeOption(option));
|
|
120
123
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
124
|
+
if (typeof options === "object") {
|
|
125
|
+
return Object.keys(options).map((value) => ({
|
|
126
|
+
label: options[value],
|
|
127
|
+
value
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
return [];
|
|
125
131
|
};
|
|
126
|
-
const select_options = ref(props.options);
|
|
132
|
+
const select_options = ref(normalizeOptions(props.options || []));
|
|
127
133
|
const filterFn = (val, update, abort) => {
|
|
128
134
|
if (props.onFilter) {
|
|
129
135
|
props.onFilter(val, update, abort);
|
|
@@ -271,12 +271,13 @@ const onLocalRequest = async (p) => {
|
|
|
271
271
|
let c = collect(model2, builder.get());
|
|
272
272
|
if (localFilters) {
|
|
273
273
|
for (let [key, value] of Object.entries(localFilters)) {
|
|
274
|
-
if (typeof value == "object") {
|
|
275
|
-
|
|
276
|
-
|
|
274
|
+
if (typeof value == "object" && value !== null) {
|
|
275
|
+
const filterValue = value;
|
|
276
|
+
if (filterValue.contains) {
|
|
277
|
+
c = c.whereContains(key, filterValue.contains);
|
|
277
278
|
}
|
|
278
|
-
if (
|
|
279
|
-
c = c.whereBetween(key,
|
|
279
|
+
if (filterValue.between) {
|
|
280
|
+
c = c.whereBetween(key, filterValue.between);
|
|
280
281
|
}
|
|
281
282
|
} else {
|
|
282
283
|
c = c.where(key, value);
|
|
@@ -454,12 +455,19 @@ const localSearchOptions = ref({});
|
|
|
454
455
|
const searchSelectFilter = (val, update, name) => {
|
|
455
456
|
if (val == "") {
|
|
456
457
|
update(() => {
|
|
457
|
-
|
|
458
|
+
const column = props.columns?.find((col) => col.name == name);
|
|
459
|
+
localSearchOptions.value[name] = column?.searchOptions;
|
|
458
460
|
});
|
|
459
461
|
} else {
|
|
460
462
|
update(() => {
|
|
461
463
|
const needle = val.toLocaleLowerCase();
|
|
462
|
-
|
|
464
|
+
const column = props.columns?.find((col) => col.name == name);
|
|
465
|
+
const options = column?.searchOptions;
|
|
466
|
+
if (Array.isArray(options)) {
|
|
467
|
+
localSearchOptions.value[name] = options.filter((v) => v.label.toLocaleLowerCase().indexOf(needle) > -1);
|
|
468
|
+
} else {
|
|
469
|
+
localSearchOptions.value[name] = options;
|
|
470
|
+
}
|
|
463
471
|
console.log(localSearchOptions.value[name]);
|
|
464
472
|
});
|
|
465
473
|
}
|
|
@@ -268,10 +268,10 @@ declare const light: {
|
|
|
268
268
|
align: string;
|
|
269
269
|
left: string;
|
|
270
270
|
right: string;
|
|
271
|
-
bold: string;
|
|
272
271
|
code: string;
|
|
273
272
|
hr: string;
|
|
274
273
|
center: string;
|
|
274
|
+
bold: string;
|
|
275
275
|
fontSize: string;
|
|
276
276
|
url: string;
|
|
277
277
|
italic: string;
|
|
@@ -364,11 +364,11 @@ declare const light: {
|
|
|
364
364
|
align: string;
|
|
365
365
|
left: string;
|
|
366
366
|
right: string;
|
|
367
|
-
bold: string;
|
|
368
367
|
code: string;
|
|
369
368
|
hr: string;
|
|
370
369
|
center: string;
|
|
371
370
|
font: string;
|
|
371
|
+
bold: string;
|
|
372
372
|
fontSize: string;
|
|
373
373
|
italic: string;
|
|
374
374
|
strikethrough: string;
|
|
@@ -872,10 +872,10 @@ declare const _default: () => {
|
|
|
872
872
|
align: string;
|
|
873
873
|
left: string;
|
|
874
874
|
right: string;
|
|
875
|
-
bold: string;
|
|
876
875
|
code: string;
|
|
877
876
|
hr: string;
|
|
878
877
|
center: string;
|
|
878
|
+
bold: string;
|
|
879
879
|
fontSize: string;
|
|
880
880
|
url: string;
|
|
881
881
|
italic: string;
|
|
@@ -968,11 +968,11 @@ declare const _default: () => {
|
|
|
968
968
|
align: string;
|
|
969
969
|
left: string;
|
|
970
970
|
right: string;
|
|
971
|
-
bold: string;
|
|
972
971
|
code: string;
|
|
973
972
|
hr: string;
|
|
974
973
|
center: string;
|
|
975
974
|
font: string;
|
|
975
|
+
bold: string;
|
|
976
976
|
fontSize: string;
|
|
977
977
|
italic: string;
|
|
978
978
|
strikethrough: string;
|
|
@@ -55,12 +55,12 @@ const onSubmit = async (d) => {
|
|
|
55
55
|
</q-tabs>
|
|
56
56
|
</template>
|
|
57
57
|
<template #after>
|
|
58
|
-
<l-system-setting-general v-if="tab == 'general'" v-
|
|
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
61
|
<l-system-setting-modules v-if="tab == 'Modules'" v-bind="obj" @submit="onSubmit" />
|
|
62
|
-
<l-system-setting-developer v-if="tab == 'developer'" v-
|
|
63
|
-
<l-system-setting-forget-password v-if="tab == 'forget-password'" v-
|
|
62
|
+
<l-system-setting-developer v-if="tab == 'developer'" v-bind="obj" @submit="onSubmit" />
|
|
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" />
|
|
65
65
|
|
|
66
66
|
|
|
@@ -5,7 +5,6 @@ import { ref } from "vue";
|
|
|
5
5
|
const route = useRoute();
|
|
6
6
|
const { data: obj } = await useAsyncObject({ canUpdate: true, canDelete: true });
|
|
7
7
|
const light = useLight();
|
|
8
|
-
const tab = ref("overview");
|
|
9
8
|
const id = route.params.user_id;
|
|
10
9
|
const reset2fa = async () => {
|
|
11
10
|
await light.dialog({
|
|
@@ -43,19 +42,19 @@ const reset2fa = async () => {
|
|
|
43
42
|
</template>
|
|
44
43
|
|
|
45
44
|
<q-card flat bordered>
|
|
46
|
-
<
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
<
|
|
51
|
-
v-if="$light.isGranted('
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
45
|
+
<l-tabs :active-color="$light.color" inline-label align="justify">
|
|
46
|
+
<l-tab name="overview" icon="sym_o_person" :label="$t('Overview')">
|
|
47
|
+
<l-user-overview :id="id" />
|
|
48
|
+
</l-tab>
|
|
49
|
+
<l-tab name="userlog" icon="sym_o_description" :label="$t('User log')"
|
|
50
|
+
v-if="$light.isGranted('userlog.list')">
|
|
51
|
+
<l-user-userlog :id="id" />
|
|
52
|
+
</l-tab>
|
|
53
|
+
<l-tab name="eventlog" icon="sym_o_description" :label="$t('Event log')"
|
|
54
|
+
v-if="$light.isGranted('eventlog.list')">
|
|
55
|
+
<l-user-eventlog :id="id" />
|
|
56
|
+
</l-tab>
|
|
57
|
+
</l-tabs>
|
|
59
58
|
|
|
60
59
|
</q-card>
|
|
61
60
|
|
|
@@ -1,15 +1,62 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { useLight, model, q } from "#imports";
|
|
3
|
-
import { ref } from "vue";
|
|
4
3
|
import { useQuasar } from "quasar";
|
|
4
|
+
import { ref, watch } from "vue";
|
|
5
|
+
import { useDragAndDrop } from "@formkit/drag-and-drop/vue";
|
|
6
|
+
import { animations } from "@formkit/drag-and-drop";
|
|
5
7
|
const light = useLight();
|
|
6
8
|
const $q = useQuasar();
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const { my } = await q({
|
|
10
|
+
my: {
|
|
11
|
+
myFavorites: {
|
|
12
|
+
my_favorite_id: true,
|
|
13
|
+
label: true,
|
|
14
|
+
path: true,
|
|
15
|
+
icon: true,
|
|
16
|
+
sequence: true
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
const [dragParent, rows] = useDragAndDrop(my.myFavorites, {
|
|
21
|
+
plugins: [animations()],
|
|
22
|
+
dragHandle: ".drag-handle"
|
|
23
|
+
});
|
|
24
|
+
const isUpdating = ref(false);
|
|
25
|
+
watch(rows, async (newRows) => {
|
|
26
|
+
if (isUpdating.value) return;
|
|
27
|
+
let hasChanged = false;
|
|
28
|
+
for (let i = 0; i < newRows.length; i++) {
|
|
29
|
+
if (newRows[i].sequence !== i + 1) {
|
|
30
|
+
hasChanged = true;
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (!hasChanged) return;
|
|
35
|
+
isUpdating.value = true;
|
|
36
|
+
try {
|
|
37
|
+
for (let i = 0; i < newRows.length; i++) {
|
|
38
|
+
const item = newRows[i];
|
|
39
|
+
await model("MyFavorite").update(item.my_favorite_id, {
|
|
40
|
+
sequence: i + 1
|
|
41
|
+
});
|
|
42
|
+
item.sequence = i + 1;
|
|
43
|
+
}
|
|
44
|
+
await light.reloadMyFavorites();
|
|
45
|
+
$q.notify({
|
|
46
|
+
message: "\u9806\u5E8F\u5DF2\u66F4\u65B0",
|
|
47
|
+
color: "positive",
|
|
48
|
+
icon: "check"
|
|
49
|
+
});
|
|
50
|
+
} catch (error) {
|
|
51
|
+
$q.notify({
|
|
52
|
+
message: "\u66F4\u65B0\u5931\u6557: " + error.message,
|
|
53
|
+
color: "negative",
|
|
54
|
+
icon: "error"
|
|
55
|
+
});
|
|
56
|
+
} finally {
|
|
57
|
+
isUpdating.value = false;
|
|
58
|
+
}
|
|
59
|
+
}, { deep: true });
|
|
13
60
|
const onSave = async (id, data) => {
|
|
14
61
|
await model("MyFavorite").update(id, data);
|
|
15
62
|
$q.notify({
|
|
@@ -17,50 +64,93 @@ const onSave = async (id, data) => {
|
|
|
17
64
|
color: "positive",
|
|
18
65
|
icon: "check"
|
|
19
66
|
});
|
|
67
|
+
const index = rows.value.findIndex((item) => item.my_favorite_id === id);
|
|
68
|
+
if (index !== -1) {
|
|
69
|
+
Object.assign(rows.value[index], data);
|
|
70
|
+
}
|
|
20
71
|
await light.reloadMyFavorites();
|
|
21
72
|
};
|
|
22
73
|
const onRemove = async (id) => {
|
|
23
74
|
await model("MyFavorite").delete(id);
|
|
75
|
+
const index = rows.value.findIndex((item) => item.my_favorite_id === id);
|
|
76
|
+
if (index !== -1) {
|
|
77
|
+
rows.value.splice(index, 1);
|
|
78
|
+
}
|
|
24
79
|
await light.reloadMyFavorites();
|
|
25
80
|
};
|
|
26
81
|
</script>
|
|
27
82
|
|
|
28
83
|
<template>
|
|
29
|
-
<
|
|
84
|
+
<div>
|
|
85
|
+
<q-list ref="dragParent" bordered separator class="drag-list">
|
|
86
|
+
<q-item
|
|
87
|
+
v-for="(row, index) in rows"
|
|
88
|
+
:key="row.my_favorite_id"
|
|
89
|
+
class="drag-item"
|
|
90
|
+
clickable
|
|
91
|
+
>
|
|
92
|
+
<!-- 拖拽手柄 -->
|
|
93
|
+
<q-item-section avatar class="drag-handle">
|
|
94
|
+
<q-icon name="drag_handle" class="cursor-move" color="grey-6" />
|
|
95
|
+
</q-item-section>
|
|
30
96
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
97
|
+
<!-- 主要內容 -->
|
|
98
|
+
<q-item-section>
|
|
99
|
+
<q-item-label>
|
|
100
|
+
<div class="row items-center q-gutter-sm">
|
|
101
|
+
<!-- Icon -->
|
|
102
|
+
<l-icon-picker
|
|
103
|
+
v-model="row.icon"
|
|
104
|
+
flat
|
|
105
|
+
round
|
|
106
|
+
size="sm"
|
|
107
|
+
@update:model-value="onSave(row.my_favorite_id, { 'icon': $event })"
|
|
108
|
+
/>
|
|
109
|
+
|
|
110
|
+
<!-- Label -->
|
|
111
|
+
<span class="text-weight-medium">
|
|
112
|
+
{{ row.label }}
|
|
113
|
+
<q-popup-edit v-model="row.label" #default="scope" buttons
|
|
114
|
+
@save="onSave(row.my_favorite_id, { 'label': $event })">
|
|
115
|
+
<q-input v-model="scope.value" dense autofocus counter @keyup.enter="scope.set" />
|
|
116
|
+
</q-popup-edit>
|
|
117
|
+
</span>
|
|
118
|
+
</div>
|
|
119
|
+
</q-item-label>
|
|
120
|
+
|
|
121
|
+
<q-item-label caption class="text-grey-7">
|
|
122
|
+
{{ row.path }}
|
|
123
|
+
<q-popup-edit v-model="row.path" #default="scope" buttons
|
|
124
|
+
@save="onSave(row.my_favorite_id, { 'path': $event })">
|
|
125
|
+
<q-input v-model="scope.value" dense autofocus counter @keyup.enter="scope.set" />
|
|
126
|
+
</q-popup-edit>
|
|
127
|
+
</q-item-label>
|
|
128
|
+
</q-item-section>
|
|
36
129
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
130
|
+
<!-- 操作按鈕 -->
|
|
131
|
+
<q-item-section side>
|
|
132
|
+
<q-btn
|
|
133
|
+
flat
|
|
134
|
+
round
|
|
135
|
+
icon="sym_o_delete"
|
|
136
|
+
size="sm"
|
|
137
|
+
color="negative"
|
|
138
|
+
@click="onRemove(row.my_favorite_id)"
|
|
139
|
+
>
|
|
140
|
+
<q-tooltip>刪除</q-tooltip>
|
|
141
|
+
</q-btn>
|
|
142
|
+
</q-item-section>
|
|
143
|
+
</q-item>
|
|
144
|
+
</q-list>
|
|
45
145
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
<q-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
@save="onSave(props.row.my_favorite_id, { 'path': $event })">
|
|
53
|
-
<q-input v-model="scope.value" dense autofocus counter @keyup.enter="scope.set" />
|
|
54
|
-
</q-popup-edit>
|
|
55
|
-
</q-td>
|
|
56
|
-
</template>
|
|
57
|
-
|
|
58
|
-
<template #body-cell-icon="props">
|
|
59
|
-
<q-td key="icon">
|
|
60
|
-
<l-icon-picker v-model="props.row.icon" flat round @update:model-value="onSave(
|
|
61
|
-
props.row.my_favorite_id, { 'icon': $event })"></l-icon-picker>
|
|
62
|
-
</q-td>
|
|
63
|
-
</template>
|
|
64
|
-
|
|
65
|
-
</q-table>
|
|
146
|
+
<!-- 狀態提示 -->
|
|
147
|
+
<div v-if="isUpdating" class="q-mt-md">
|
|
148
|
+
<q-linear-progress indeterminate color="primary" />
|
|
149
|
+
<div class="text-center q-mt-sm text-grey-6">正在更新順序...</div>
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
66
152
|
</template>
|
|
153
|
+
|
|
154
|
+
<style scoped>
|
|
155
|
+
.drag-list{border-radius:8px;overflow:hidden}.drag-item{transition:all .2s}.drag-item:hover{background-color:rgba(0,0,0,.02)}.drag-handle{cursor:move;min-width:40px;padding:0 8px}.drag-handle:hover .q-icon{color:var(--q-primary)!important}:deep(.formkit-dnd-is-dragging){background-color:rgba(25,118,210,.05);box-shadow:0 4px 12px rgba(0,0,0,.15);opacity:.7;transform:scale(1.02)}:deep(.formkit-dnd-placeholder){align-items:center;background-color:rgba(25,118,210,.1);border:2px dashed var(--q-primary);border-radius:4px;display:flex;height:72px;justify-content:center;margin:2px 0}:deep(.formkit-dnd-placeholder:before){color:var(--q-primary);content:"放置在此處";font-size:14px;font-weight:500}
|
|
156
|
+
</style>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hostlink/nuxt-light",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.37.0",
|
|
4
4
|
"description": "HostLink Nuxt Light Framework",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@azure/msal-browser": "^3.26.1",
|
|
34
34
|
"@formkit/drag-and-drop": "^0.5.3",
|
|
35
|
-
"@hostlink/light": "^2.
|
|
35
|
+
"@hostlink/light": "^2.8.0",
|
|
36
36
|
"@nuxt/module-builder": "^1.0.1",
|
|
37
37
|
"@quasar/extras": "^1.16.11",
|
|
38
38
|
"@quasar/quasar-ui-qmarkdown": "^2.0.5",
|