@hostlink/nuxt-light 0.0.17 → 0.0.18

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 CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "light",
3
3
  "configKey": "light",
4
- "version": "0.0.17"
4
+ "version": "0.0.18"
5
5
  }
@@ -1,10 +1,8 @@
1
1
  <script setup>
2
2
  import { useI18n } from 'vue-i18n';
3
- import { useLight, q, getCurrentUser } from '../light';
4
- import { ref, computed, reactive, provide } from 'vue';
5
-
6
-
7
-
3
+ import { useLight, q, getCurrentUser, m } from '../light';
4
+ import { ref, computed, reactive, provide, watch } from 'vue';
5
+ import packageJson from '../../package.json'
8
6
 
9
7
  const light = useLight();
10
8
  const props = defineProps({
@@ -14,6 +12,7 @@ const props = defineProps({
14
12
  });
15
13
 
16
14
  let app = await q("app", ["menus"]);
15
+ let my = await q("my", ["styles"]);
17
16
  const menus = ref(app.menus)
18
17
 
19
18
  const i18n = useI18n();
@@ -50,10 +49,10 @@ const layoutView = computed(() => {
50
49
  })
51
50
 
52
51
  const style = reactive({
53
- headerColor: 'bg-primary',
52
+ color: my.styles?.color || 'bg-primary',
54
53
  theme: 'semi-dark',
55
54
  miniState: false,
56
- dense: false
55
+ dense: my.styles?.dense
57
56
  });
58
57
 
59
58
 
@@ -109,12 +108,26 @@ const reloadMenu = async () => {
109
108
 
110
109
  provide('reloadMenu', reloadMenu)
111
110
 
111
+ watch(() => style.dense, async (value) => {
112
+ await m("updateMyStyle", {
113
+ name: "dense",
114
+ value: value
115
+ });
116
+ })
117
+
118
+ watch(() => style.color, async (value) => {
119
+ await m("updateMyStyle", {
120
+ name: "color",
121
+ value: value
122
+ });
123
+ })
124
+
112
125
  </script>
113
126
 
114
127
 
115
128
  <template>
116
129
  <q-layout :view="layoutView">
117
- <q-header bordered class="text-white" :class="style.headerColor">
130
+ <q-header bordered class="text-white" :class="style.color">
118
131
  <q-toolbar>
119
132
  <q-btn dense flat round icon="menu" class="q-mr-sm" @click="toggleLeftDrawer" />
120
133
 
@@ -149,20 +162,27 @@ provide('reloadMenu', reloadMenu)
149
162
 
150
163
 
151
164
  <q-btn flat round dense icon="sym_o_person" class="q-mr-sm">
152
- <q-menu max-width="200px">
165
+ <q-menu max-width="250px">
153
166
  <q-list>
154
167
  <q-item v-close-popup to="/User/profile">
155
168
  <q-item-section avatar>
156
169
  <q-icon name="sym_o_person" />
157
170
  </q-item-section>
158
- <q-item-section>Profile</q-item-section>
171
+ <q-item-section>{{ $t('Profile') }}</q-item-section>
172
+ </q-item>
173
+
174
+ <q-item v-close-popup to="/User/setting">
175
+ <q-item-section avatar>
176
+ <q-icon name="sym_o_settings" />
177
+ </q-item-section>
178
+ <q-item-section>{{ $t('Setting') }}</q-item-section>
159
179
  </q-item>
160
180
 
161
181
  <q-item v-close-popup v-if="showViewAs" to="/System/view_as">
162
182
  <q-item-section avatar>
163
183
  <q-icon name="sym_o_visibility" />
164
184
  </q-item-section>
165
- <q-item-section>View as</q-item-section>
185
+ <q-item-section>{{ $t('View as') }}</q-item-section>
166
186
  </q-item>
167
187
 
168
188
  <q-separator />
@@ -171,7 +191,7 @@ provide('reloadMenu', reloadMenu)
171
191
  <q-item-section avatar>
172
192
  <q-icon name="logout" />
173
193
  </q-item-section>
174
- <q-item-section>Logout</q-item-section>
194
+ <q-item-section>{{ $t('Logout') }}</q-item-section>
175
195
  </q-item>
176
196
  </q-list>
177
197
  </q-menu>
@@ -193,7 +213,7 @@ provide('reloadMenu', reloadMenu)
193
213
  <q-drawer overlay v-model="rightDrawerOpen" side="right" bordered>
194
214
  <!-- drawer content -->
195
215
  <q-scroll-area class="fit">
196
- <l-customizer v-model:headerColor="style.headerColor" v-model:theme="style.theme"
216
+ <l-customizer v-model:headerColor="style.color" v-model:theme="style.theme"
197
217
  v-model:miniState="style.miniState" v-model:dense="style.dense"
198
218
  v-model:menuOverlayHeader="style.menuOverlayHeader" />
199
219
  </q-scroll-area>
@@ -201,8 +221,6 @@ provide('reloadMenu', reloadMenu)
201
221
 
202
222
  <q-page-container class="bg-grey-2" style="color:#1f1f1f">
203
223
  <!-- Error message -->
204
-
205
-
206
224
  <q-card v-for="error in errors" flat class="q-ma-md" bordered style="border-color: var(--q-negative)">
207
225
  <q-card-section>
208
226
  <q-btn dense flat round icon="close" class="q-mr-sm" @click="light.removeError(error)"></q-btn>{{
@@ -10,6 +10,8 @@ if (props.permission) {
10
10
  if (my.granted) {
11
11
  granted.value = true;
12
12
  }
13
+ } else {
14
+ granted.value = true;
13
15
  }
14
16
 
15
17
  </script>
@@ -11,6 +11,10 @@ const form = ref(null);
11
11
  const props = defineProps({
12
12
  modelValue: {
13
13
  type: Object
14
+ },
15
+ bordered: {
16
+ type: Boolean,
17
+ default: true
14
18
  }
15
19
  });
16
20
 
@@ -63,7 +67,7 @@ const onSubmit = (e) => {
63
67
  </script>
64
68
  <template>
65
69
  <q-form ref="form" @submit="onSubmit">
66
- <l-card>
70
+ <l-card :bordered="bordered">
67
71
  <q-card-section>
68
72
  <slot></slot>
69
73
  </q-card-section>
@@ -14,4 +14,5 @@ import removeObject from "./removeObject";
14
14
  import t from "./t";
15
15
  import updateObject from "./updateObject";
16
16
  import viewAs from "./viewAs";
17
- export { addObject, f, getApiUrl, getCurrentUser, getObject, id, list, listData, login, m, mutation, q, removeObject, t, updateObject, viewAs };
17
+ declare const notify: (message: string, color?: string) => void;
18
+ export { addObject, f, getApiUrl, getCurrentUser, getObject, id, list, listData, login, m, mutation, q, removeObject, t, updateObject, viewAs, notify };
@@ -1,3 +1,4 @@
1
+ import { Notify } from "quasar";
1
2
  import addObject from "./addObject.mjs";
2
3
  import f from "./f.mjs";
3
4
  import getApiUrl from "./getApiUrl.mjs";
@@ -14,4 +15,11 @@ import removeObject from "./removeObject.mjs";
14
15
  import t from "./t.mjs";
15
16
  import updateObject from "./updateObject.mjs";
16
17
  import viewAs from "./viewAs.mjs";
17
- export { addObject, f, getApiUrl, getCurrentUser, getObject, id, list, listData, login, m, mutation, q, removeObject, t, updateObject, viewAs };
18
+ const notify = function(message, color = "green") {
19
+ Notify.create({
20
+ message,
21
+ color,
22
+ position: "top"
23
+ });
24
+ };
25
+ export { addObject, f, getApiUrl, getCurrentUser, getObject, id, list, listData, login, m, mutation, q, removeObject, t, updateObject, viewAs, notify };
@@ -4,4 +4,4 @@ interface Light {
4
4
  removeError: (error: String) => void;
5
5
  }
6
6
  export declare function useLight(): Light;
7
- export { addObject, f, getApiUrl, getCurrentUser, getObject, id, list, listData, login, m, mutation, q, removeObject, t, updateObject, viewAs } from "./lib";
7
+ export { notify, addObject, f, getApiUrl, getCurrentUser, getObject, id, list, listData, login, m, mutation, q, removeObject, t, updateObject, viewAs } from "./lib";
@@ -16,6 +16,7 @@ export function useLight() {
16
16
  };
17
17
  }
18
18
  export {
19
+ notify,
19
20
  addObject,
20
21
  f,
21
22
  getApiUrl,
@@ -6,7 +6,8 @@ const my = await q("my", ["username", "first_name", "last_name", "email", "phone
6
6
  <template>
7
7
  <l-page title="User profile">
8
8
  <template #header>
9
- <q-btn rounded icon="sym_o_key" to="update-password" outline color="primary" label="Update password"></q-btn>
9
+ <l-btn icon="sym_o_key" to="update-password" label="Update password" />
10
+ <l-btn icon="sym_o_key" to="two-factor-auth" label="Two factor auth" />
10
11
  </template>
11
12
  <l-card>
12
13
  <l-list>
@@ -0,0 +1,60 @@
1
+ <script setup>
2
+ import { reactive } from "vue"
3
+ import { m } from "../../light"
4
+ import { useQuasar } from "quasar";
5
+ const quasar = useQuasar()
6
+ const my2FA = await m("my2FA", [])
7
+ const obj = reactive({});
8
+ const save = async () => {
9
+
10
+ try {
11
+ await m("updateMy2FA", {
12
+ code: obj.code,
13
+ secret: my2FA.secret
14
+ });
15
+
16
+ } catch (e) {
17
+ quasar.notify({
18
+ message: e.message,
19
+ type: "negative",
20
+ position: "top"
21
+ })
22
+
23
+ return
24
+ }
25
+ }
26
+
27
+ </script>
28
+ <template>
29
+ <l-page>
30
+
31
+ <l-card>
32
+ <l-form @save="save">
33
+
34
+ <div>
35
+
36
+ <p>
37
+ Now download the app and scan the qrcode. Input the code to the
38
+ following input and submit
39
+ </p>
40
+ <p>
41
+ For Android user, install
42
+ <el-link type="primary" target="_blank"
43
+ href="https://play.google.com/store/apps/details?id=com.azure.authenticator">Authenticator</el-link>
44
+ </p>
45
+
46
+ <p>
47
+ For iOS user, install
48
+ <el-link type="primary" target="_blank"
49
+ href="https://apps.apple.com/us/app/microsoft-authenticator/id983156458">Authenticator</el-link>
50
+ </p>
51
+ </div>
52
+ <q-img :src="my2FA.image" width="250px" />
53
+ <l-input v-model="obj.code" label="Code"
54
+ hint="Please scan the QR code with your authenticator app, and enter the code" required />
55
+ </l-form>
56
+
57
+ </l-card>
58
+
59
+ </l-page>
60
+ </template>
@@ -0,0 +1,14 @@
1
+ <script setup>
2
+ import { reactive } from "vue"
3
+ import { q, m, notify } from "../../../light"
4
+ const app = q("app"["hasBioAuth"]);
5
+ </script>
6
+ <template>
7
+ <l-card :bordered="false">
8
+
9
+
10
+ <q-card-section v-if="!app.hasBioAuth">
11
+ Biometric authentication is not installed, please install web-auth/webauthn-lib on the server.
12
+ </q-card-section>
13
+ </l-card>
14
+ </template>
@@ -0,0 +1,34 @@
1
+ <script setup>
2
+ import { reactive } from "vue"
3
+ import { q, m, notify } from "../../../light"
4
+
5
+ const obj = reactive(await q("my", ["username", "email", "first_name", "last_name"]))
6
+ const save = async () => {
7
+ try {
8
+ await m("updateMy", {
9
+ data: {
10
+ email: obj.email,
11
+ first_name: obj.first_name,
12
+ last_name: obj.last_name
13
+
14
+ }
15
+ });
16
+ notify("Your profile has been updated")
17
+
18
+ } catch (e) {
19
+ notify(e.message, "red")
20
+ }
21
+
22
+
23
+
24
+ }
25
+ </script>
26
+ <template>
27
+ <l-form @save="save" :bordered="false">
28
+ <l-input label="Username" v-model="obj.username" readonly></l-input>
29
+ <l-input label="Email" v-model="obj.email" required></l-input>
30
+ <l-input label="First Name" v-model="obj.first_name" required></l-input>
31
+ <l-input label="Last Name" v-model="obj.last_name"></l-input>
32
+
33
+ </l-form>
34
+ </template>
@@ -0,0 +1,25 @@
1
+ <script setup>
2
+ import { reactive } from "vue"
3
+ import { q, m, notify } from "../../../light"
4
+ const obj = reactive(await q("my", ["phone", "addr1", "addr2", "addr3"]))
5
+ const save = async () => {
6
+ try {
7
+ await m("updateMy", {
8
+ data: obj
9
+ });
10
+ notify("Your information has been updated")
11
+
12
+ } catch (e) {
13
+ notify(e.message, "red")
14
+ }
15
+ }
16
+ </script>
17
+ <template>
18
+ <l-form @save="save" :bordered="false">
19
+ <l-input label="Phone" v-model="obj.phone"></l-input>
20
+ <l-input label="Address1" v-model="obj.addr1"></l-input>
21
+ <l-input label="Address2" v-model="obj.addr2"></l-input>
22
+ <l-input label="Address3" v-model="obj.addr3"></l-input>
23
+
24
+ </l-form>
25
+ </template>
@@ -0,0 +1,34 @@
1
+ <script setup>
2
+ import { reactive } from "vue"
3
+ import { q, m, notify } from "../../../light"
4
+
5
+ const obj = reactive({
6
+ old_password: "",
7
+ new_password: "",
8
+ confirm_password: ""
9
+ })
10
+
11
+ const onSave = async () => {
12
+ if (await m("updatePassword", {
13
+ old_password: obj.old_password,
14
+ new_password: obj.new_password,
15
+ })) {
16
+ notify("Your password has been updated")
17
+ } else {
18
+ notify("Old password is incorrect", "red")
19
+ }
20
+ }
21
+
22
+ </script>
23
+ <template>
24
+ <l-form @save="onSave" :bordered="false">
25
+ <l-input label="Old password" v-model="obj.old_password" type="password"
26
+ :rules="[v => !!v || 'Old password is required']" />
27
+ <l-input label="New password" v-model="obj.new_password" type="password"
28
+ :rules="[v => !!v || 'New password is required']" />
29
+ <l-input label="Confirm password" v-model="obj.confirm_password" type="password" :rules="[
30
+ v => !!v || 'Confirm password is required',
31
+ v => v == obj.new_password || 'Confirm password does not match'
32
+ ]" />
33
+ </l-form>
34
+ </template>
@@ -0,0 +1,3 @@
1
+ <template>
2
+ <div>Style</div>
3
+ </template>
@@ -0,0 +1,60 @@
1
+ <script setup>
2
+ import { ref, reactive } from "vue"
3
+ import { q, m, notify } from "../../../light"
4
+
5
+ const my = await q("my", ["twoFactorEnabled"])
6
+ const my2FA = await m("my2FA", [])
7
+ const obj = reactive({});
8
+ const save = async () => {
9
+
10
+ try {
11
+ await m("updateMy2FA", {
12
+ code: obj.code,
13
+ secret: my2FA.secret
14
+ });
15
+ notify("Your 2FA has been updated")
16
+
17
+ } catch (e) {
18
+ notify(e.message, "red")
19
+ }
20
+ }
21
+
22
+ const show = ref(true);
23
+
24
+ if (my.twoFactorEnabled) {
25
+ show.value = false;
26
+ }
27
+
28
+
29
+ </script>
30
+ <template>
31
+ <l-form @save="save" :bordered="false" v-if="show">
32
+ <div>
33
+ <p>
34
+ Now download the app and scan the qrcode. Input the code to the
35
+ following input and submit
36
+ </p>
37
+ <p>
38
+ For Android user, install
39
+ <el-link type="primary" target="_blank"
40
+ href="https://play.google.com/store/apps/details?id=com.azure.authenticator">Authenticator</el-link>
41
+ </p>
42
+
43
+ <p>
44
+ For iOS user, install
45
+ <el-link type="primary" target="_blank"
46
+ href="https://apps.apple.com/us/app/microsoft-authenticator/id983156458">Authenticator</el-link>
47
+ </p>
48
+ </div>
49
+ <q-img :src="my2FA.image" width="250px" />
50
+ <l-input v-model="obj.code" label="Code"
51
+ hint="Please scan the QR code with your authenticator app, and enter the code" required />
52
+ </l-form>
53
+ <div v-else>
54
+ <q-card-section>
55
+ Your 2FA is enabled
56
+ <l-btn @click="show = true" label="Reset Your 2FA" icon="sym_o_refresh" />
57
+ </q-card-section>
58
+
59
+ </div>
60
+ </template>
@@ -0,0 +1,33 @@
1
+ <script setup>
2
+ import { ref } from "vue"
3
+ const tab = ref("general")
4
+ </script>
5
+
6
+ <template>
7
+ <l-page>
8
+ <l-card>
9
+ <q-splitter unit="px" :model-value="120">
10
+ <template #before>
11
+ <q-tabs v-model="tab" vertical >
12
+ <q-route-tab name="general" icon="sym_o_info" :label="$t('General')" to="/User/setting" exact
13
+ replace />
14
+ <q-route-tab name="information" icon="sym_o_info" :label="$t('Information')"
15
+ to="/User/setting/information" exact replace />
16
+ <q-route-tab name="password" icon="sym_o_password" :label="$t('Password')"
17
+ to="/User/setting/password" exact replace />
18
+ <q-route-tab name="style" icon="sym_o_style" :label="$t('Style')" to="/User/setting/style" exact
19
+ replace />
20
+ <q-route-tab name="2fa" icon="sym_o_key" :label="$t('2FA')" to="/User/setting/two-factor-auth" exact replace />
21
+ <q-route-tab name="bio" icon="sym_o_fingerprint" :label="$t('Bio')" to="/User/setting/bio-auth"
22
+ exact replace />
23
+ </q-tabs>
24
+ </template>
25
+
26
+ <template #after>
27
+ <router-view>
28
+ </router-view>
29
+ </template>
30
+ </q-splitter>
31
+ </l-card>
32
+ </l-page>
33
+ </template>
@@ -1,7 +1,19 @@
1
- declare const _default: {
1
+ declare const _default: ({
2
2
  name: string;
3
3
  path: string;
4
4
  component: typeof index;
5
- }[];
5
+ children?: undefined;
6
+ } | {
7
+ path: string;
8
+ component: typeof User_setting;
9
+ children: {
10
+ name: string;
11
+ path: string;
12
+ component: typeof User_setting_index;
13
+ }[];
14
+ name?: undefined;
15
+ })[];
6
16
  export default _default;
7
17
  declare function index(): Promise<any>;
18
+ declare function User_setting(): Promise<any>;
19
+ declare function User_setting_index(): Promise<any>;
@@ -91,6 +91,46 @@ function User_profile() {
91
91
  /* webpackChunkName: "User-profile" */ './pages/User/profile.vue'
92
92
  )
93
93
  }
94
+ function User_setting() {
95
+ return import(
96
+ /* webpackChunkName: "User-setting" */ './pages/User/setting.vue'
97
+ )
98
+ }
99
+ function User_setting_index() {
100
+ return import(
101
+ /* webpackChunkName: "User-setting-index" */ './pages/User/setting/index.vue'
102
+ )
103
+ }
104
+ function User_setting_2fa() {
105
+ return import(
106
+ /* webpackChunkName: "User-setting-2fa" */ './pages/User/setting/2fa.vue'
107
+ )
108
+ }
109
+ function User_setting_bio_auth() {
110
+ return import(
111
+ /* webpackChunkName: "User-setting-bio-auth" */ './pages/User/setting/bio-auth.vue'
112
+ )
113
+ }
114
+ function User_setting_information() {
115
+ return import(
116
+ /* webpackChunkName: "User-setting-information" */ './pages/User/setting/information.vue'
117
+ )
118
+ }
119
+ function User_setting_password() {
120
+ return import(
121
+ /* webpackChunkName: "User-setting-password" */ './pages/User/setting/password.vue'
122
+ )
123
+ }
124
+ function User_setting_style() {
125
+ return import(
126
+ /* webpackChunkName: "User-setting-style" */ './pages/User/setting/style.vue'
127
+ )
128
+ }
129
+ function User_setting_two_factor_auth() {
130
+ return import(
131
+ /* webpackChunkName: "User-setting-two-factor-auth" */ './pages/User/setting/two-factor-auth.vue'
132
+ )
133
+ }
94
134
  function User_update_password() {
95
135
  return import(
96
136
  /* webpackChunkName: "User-update-password" */ './pages/User/update-password.vue'
@@ -233,6 +273,47 @@ export default [
233
273
  path: '/User/profile',
234
274
  component: User_profile,
235
275
  },
276
+ {
277
+ path: '/User/setting',
278
+ component: User_setting,
279
+ children: [
280
+ {
281
+ name: 'User-setting',
282
+ path: '',
283
+ component: User_setting_index,
284
+ },
285
+ {
286
+ name: 'User-setting-2fa',
287
+ path: '2fa',
288
+ component: User_setting_2fa,
289
+ },
290
+ {
291
+ name: 'User-setting-bio-auth',
292
+ path: 'bio-auth',
293
+ component: User_setting_bio_auth,
294
+ },
295
+ {
296
+ name: 'User-setting-information',
297
+ path: 'information',
298
+ component: User_setting_information,
299
+ },
300
+ {
301
+ name: 'User-setting-password',
302
+ path: 'password',
303
+ component: User_setting_password,
304
+ },
305
+ {
306
+ name: 'User-setting-style',
307
+ path: 'style',
308
+ component: User_setting_style,
309
+ },
310
+ {
311
+ name: 'User-setting-two-factor-auth',
312
+ path: 'two-factor-auth',
313
+ component: User_setting_two_factor_auth,
314
+ },
315
+ ],
316
+ },
236
317
  {
237
318
  name: 'User-update-password',
238
319
  path: '/User/update-password',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hostlink/nuxt-light",
3
- "version": "0.0.17",
3
+ "version": "0.0.18",
4
4
  "description": "HostLink Nuxt Light Framework",
5
5
  "repository": "@hostlink/nuxt-light",
6
6
  "license": "MIT",