@hostlink/nuxt-light 0.0.108 → 0.0.110
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-input.vue +56 -6
- package/dist/runtime/components/l-table.vue +1 -1
- package/dist/runtime/locales/en.json +3 -2
- package/dist/runtime/locales/zh-hk.json +2 -2
- package/dist/runtime/pages/System/view_as.vue +1 -1
- package/dist/runtime/pages/User/_user_id/change-password.vue +9 -24
- package/dist/runtime/pages/User/add.vue +3 -1
- package/dist/runtime/pages/User/setting/password.vue +15 -5
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { computed, ref,
|
|
2
|
+
import { computed, ref, useAttrs } from "vue";
|
|
3
3
|
import { useI18n } from 'vue-i18n';
|
|
4
4
|
import tc2sc from "../lib/tc2sc";
|
|
5
5
|
import { useLight } from '../';
|
|
6
6
|
|
|
7
7
|
const i18n = useI18n();
|
|
8
8
|
const light = useLight();
|
|
9
|
-
const slots = useSlots();
|
|
10
9
|
|
|
11
10
|
const props = defineProps({
|
|
12
11
|
modelValue: {
|
|
@@ -38,11 +37,13 @@ const props = defineProps({
|
|
|
38
37
|
});
|
|
39
38
|
const emit = defineEmits(["update:modelValue"]);
|
|
40
39
|
|
|
40
|
+
//clone rules to new_rules
|
|
41
41
|
const new_rules = props.rules || [];
|
|
42
42
|
|
|
43
|
+
|
|
43
44
|
//has required prop (in properties)
|
|
44
|
-
if (props.required) {
|
|
45
|
-
new_rules.push(val => !!val || i18n.t('input_required',[i18n.t(props.label)]));
|
|
45
|
+
if (props.required || (new_rules.indexOf("required") >= 0)) {
|
|
46
|
+
new_rules.push(val => !!val || i18n.t('input_required', [i18n.t(props.label)]));
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
if (props.type == "email") {
|
|
@@ -53,6 +54,57 @@ if (props.type == "email") {
|
|
|
53
54
|
});
|
|
54
55
|
}
|
|
55
56
|
|
|
57
|
+
if (new_rules.indexOf("containUpper") >= 0) {
|
|
58
|
+
new_rules.push(val => {
|
|
59
|
+
if (val && !val.match(/[A-Z]/)) {
|
|
60
|
+
return i18n.t("Must contain at least one uppercase letter");
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (new_rules.indexOf("containLower") >= 0) {
|
|
66
|
+
new_rules.push(val => {
|
|
67
|
+
if (val && !val.match(/[a-z]/)) {
|
|
68
|
+
return i18n.t("Must contain at least one lowercase letter");
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (new_rules.indexOf("containNumber") >= 0) {
|
|
74
|
+
new_rules.push(val => {
|
|
75
|
+
if (val && !val.match(/[0-9]/)) {
|
|
76
|
+
return i18n.t("Must contain at least one number");
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (new_rules.indexOf("containSpecial") >= 0) {
|
|
82
|
+
new_rules.push(val => {
|
|
83
|
+
if (val && !val.match(/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/)) {
|
|
84
|
+
return i18n.t("Must contain at least one symbol");
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
//find mniLength:x in rules
|
|
90
|
+
const minLength = new_rules.find(rule => {
|
|
91
|
+
if (typeof rule != "string") return false;
|
|
92
|
+
return rule.startsWith("minLength:")
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
if (minLength) {
|
|
96
|
+
const min = parseInt(minLength.replace("minLength:", ""));
|
|
97
|
+
new_rules.push(val => {
|
|
98
|
+
if (val && val.length < min) {
|
|
99
|
+
return i18n.t("input_min", [min]);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
56
108
|
|
|
57
109
|
const localValue = computed({
|
|
58
110
|
get: () => props.modelValue,
|
|
@@ -100,8 +152,6 @@ const onClickTc2Sc = () => {
|
|
|
100
152
|
localValue.value = tc2sc(localValue.value);
|
|
101
153
|
}
|
|
102
154
|
|
|
103
|
-
|
|
104
|
-
|
|
105
155
|
const attrs = {
|
|
106
156
|
...{
|
|
107
157
|
filled: light.getStyle("inputFilled", false),
|
|
@@ -636,7 +636,7 @@ const getCellClass = (col: any, row: any) => {
|
|
|
636
636
|
|
|
637
637
|
<template v-if="!col.searchType">
|
|
638
638
|
<q-input dense clearable v-model="filters[col.name]" @keydown.enter.prevent="onFilters"
|
|
639
|
-
@clear="onFilters"></q-input>
|
|
639
|
+
@clear="onFilters" enterkeyhint="search"></q-input>
|
|
640
640
|
|
|
641
641
|
</template>
|
|
642
642
|
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"Theme Customizer": "Theme Customizer",
|
|
12
12
|
"Customize & Preview in Real Time": "Customize & Preview in Real Time",
|
|
13
13
|
"Permission": "Permission",
|
|
14
|
-
"storage_usage":"{0} free of {1}",
|
|
15
|
-
"input_required": "Please input {0}"
|
|
14
|
+
"storage_usage": "{0} free of {1}",
|
|
15
|
+
"input_required": "Please input {0}",
|
|
16
|
+
"input_min": "Please input at least {0} characters"
|
|
16
17
|
}
|
|
@@ -40,7 +40,7 @@ const onCickView = async (id) => {
|
|
|
40
40
|
</script>
|
|
41
41
|
<template>
|
|
42
42
|
<l-page>
|
|
43
|
-
<q-table flat :columns="columns" :rows="users">
|
|
43
|
+
<q-table flat :columns="columns" :rows="users" :rows-per-page-options="[0]">
|
|
44
44
|
<template #body-cell-view="props">
|
|
45
45
|
<q-td :props="props">
|
|
46
46
|
<q-btn rounded outline color="primary" @click="onCickView(props.row.user_id)" label="view"
|
|
@@ -1,35 +1,20 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { q } from '../../../'
|
|
2
|
+
import { q, m } from '../../../'
|
|
3
3
|
import { useRouter, useRoute } from "vue-router"
|
|
4
4
|
import { reactive } from "vue"
|
|
5
5
|
const system = await q("system", ["passwordPolicy"]);
|
|
6
|
-
const rules = system.passwordPolicy.map((rule) => {
|
|
7
|
-
let s = rule.split(":");
|
|
8
|
-
|
|
9
|
-
switch (s[0]) {
|
|
10
|
-
case "required":
|
|
11
|
-
return (v) => !!v || "Required";
|
|
12
|
-
case "containUpper":
|
|
13
|
-
return (v) => /[A-Z]/.test(v) || "Must contain at least one uppercase letter";
|
|
14
|
-
case "containLower":
|
|
15
|
-
return (v) => /[a-z]/.test(v) || "Must contain at least one lowercase letter";
|
|
16
|
-
case "containNumber":
|
|
17
|
-
return (v) => /[0-9]/.test(v) || "Must contain at least one number";
|
|
18
|
-
case "containSpecial":
|
|
19
|
-
return (v) => /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(v) || "Must contain at least one special character";
|
|
20
|
-
case "minLength":
|
|
21
|
-
return (v) => v.length >= parseInt(s[1]) || `Must be at least ${s[1]} characters`;
|
|
22
|
-
}
|
|
23
|
-
})
|
|
24
6
|
const router = useRouter();
|
|
25
7
|
const route = useRoute();
|
|
26
|
-
const obj = reactive({
|
|
27
|
-
id: parseInt(route.params.user_id)
|
|
28
|
-
})
|
|
29
8
|
|
|
9
|
+
const obj = reactive({
|
|
10
|
+
password: "",
|
|
11
|
+
});
|
|
30
12
|
|
|
31
13
|
const onUpdatePassword = async () => {
|
|
32
|
-
if (await m("
|
|
14
|
+
if (await m("updateUserPassword", {
|
|
15
|
+
id: route.params.user_id,
|
|
16
|
+
password: obj.password
|
|
17
|
+
})) {
|
|
33
18
|
router.push("/User");
|
|
34
19
|
}
|
|
35
20
|
}
|
|
@@ -38,7 +23,7 @@ const onUpdatePassword = async () => {
|
|
|
38
23
|
<template>
|
|
39
24
|
<l-page>
|
|
40
25
|
<l-form @save="onUpdatePassword">
|
|
41
|
-
<l-input type="password" label="New password"
|
|
26
|
+
<l-input type="password" label="New password" v-model="obj.password" :rules="system.passwordPolicy">
|
|
42
27
|
</l-input>
|
|
43
28
|
</l-form>
|
|
44
29
|
|
|
@@ -18,6 +18,7 @@ roles = roles.map((role) => {
|
|
|
18
18
|
};
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
+
const system = await q("system", ["passwordPolicy"]);
|
|
21
22
|
</script>
|
|
22
23
|
<template>
|
|
23
24
|
<l-page>
|
|
@@ -25,7 +26,8 @@ roles = roles.map((role) => {
|
|
|
25
26
|
<l-row>
|
|
26
27
|
<l-col md="6" gutter="md">
|
|
27
28
|
<l-input label="Username" v-model="obj.username" required />
|
|
28
|
-
<l-input label="Password" v-model="obj.password" required type="password"
|
|
29
|
+
<l-input label="Password" v-model="obj.password" required type="password"
|
|
30
|
+
:rules="system.passwordPolicy" />
|
|
29
31
|
<l-input label="First name" v-model="obj.first_name" required />
|
|
30
32
|
<l-input label="Last name" v-model="obj.last_name" />
|
|
31
33
|
<l-input label="Email" v-model="obj.email" required type="email" />
|
|
@@ -3,6 +3,8 @@ import { reactive } from "vue"
|
|
|
3
3
|
import { notify } from '../../../'
|
|
4
4
|
import { updatePassword } from "@hostlink/light"
|
|
5
5
|
|
|
6
|
+
import { q } from "#imports"
|
|
7
|
+
|
|
6
8
|
const obj = reactive({
|
|
7
9
|
old_password: "",
|
|
8
10
|
new_password: "",
|
|
@@ -17,16 +19,24 @@ const onSave = async () => {
|
|
|
17
19
|
}
|
|
18
20
|
}
|
|
19
21
|
|
|
22
|
+
const system = await q("system", ["passwordPolicy"])
|
|
23
|
+
|
|
20
24
|
</script>
|
|
21
25
|
<template>
|
|
22
26
|
<l-form @save="onSave" :bordered="false">
|
|
23
|
-
<l-input label="Old password" v-model="obj.old_password" type="password"
|
|
24
|
-
|
|
25
|
-
<l-input label="New password" v-model="obj.new_password" type="password"
|
|
26
|
-
:rules="[v => !!v || 'New password is required']" />
|
|
27
|
+
<l-input label="Old password" v-model="obj.old_password" type="password" required />
|
|
28
|
+
<l-input label="New password" v-model="obj.new_password" type="password" :rules="system.passwordPolicy" />
|
|
27
29
|
<l-input label="Confirm password" v-model="obj.confirm_password" type="password" :rules="[
|
|
28
|
-
v => !!v || 'Confirm password is required',
|
|
29
30
|
v => v == obj.new_password || 'Confirm password does not match'
|
|
30
31
|
]" />
|
|
31
32
|
</l-form>
|
|
33
|
+
|
|
34
|
+
<div>
|
|
35
|
+
<div>Password policy</div>
|
|
36
|
+
<ul>
|
|
37
|
+
<li v-for="rule in system.passwordPolicy" :key="rule">
|
|
38
|
+
{{ rule }}
|
|
39
|
+
</li>
|
|
40
|
+
</ul>
|
|
41
|
+
</div>
|
|
32
42
|
</template>
|