@hostlink/nuxt-light 1.1.8 → 1.3.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.
@@ -1,10 +1,10 @@
1
1
  <script setup>
2
+ import { ref } from 'vue'
2
3
  import { Notify } from 'quasar'
3
4
  import { reset } from "@formkit/core"
4
5
  import { useRouter } from 'vue-router'
5
- import { q, m } from '../../'
6
+ import { q, m } from '#imports'
6
7
 
7
- const router = useRouter()
8
8
  const { app } = await q({ app: { config: ["name", "value"] } })
9
9
  const obj = app.config.reduce((acc, cur) => {
10
10
  acc[cur.name] = cur.value
@@ -63,65 +63,104 @@ if (obj.mode != 'prod') {
63
63
  obj.mode = 'prod'
64
64
  }
65
65
 
66
+ const tab = ref('general')
66
67
 
67
68
  </script>
68
69
  <template>
69
70
  <l-page>
70
- <FormKit type="l-form" :value="obj" #default="{ value }" @submit="onSubmit">
71
- <FormKit type="l-input" label="Company" name="company" validation="required"></FormKit>
72
- <FormKit type="l-input" label="Company logo" name="company_logo"></FormKit>
73
-
74
- <q-separator />
75
-
76
- <q-field label="Password policy" stack-label>
77
- <FormKit type="q-checkbox" label="Upper Case" name="password_contains_uppercase" true-value="1"
78
- false-value="0" />
79
- <FormKit type="q-checkbox" label="Lower Case" name="password_contains_lowercase" true-value="1"
80
- false-value="0" />
81
- <FormKit type="q-checkbox" label="Number" name="password_contains_numeric" true-value="1" false-value="0" />
82
- <FormKit type="q-checkbox" label="Special Character" name="password_contains_symbol" true-value="1"
83
- false-value="0" />
84
- </q-field>
85
-
86
- <FormKit type="l-input" label="Password min Length" name="password_min_length" validation="required|number">
87
- </FormKit>
88
-
89
- <q-field label="File manager" stack-label>
90
- <FormKit type="q-checkbox" label="Show" name="file_manager" true-value="1" false-value="0" />
91
- </q-field>
92
-
93
- <q-field label="Two factor authentication" stack-label>
94
- <FormKit type="q-checkbox" label="Enable" name="two_factor_authentication" true-value="1" false-value="0" />
95
- </q-field>
96
-
97
- <FormKit label="Mode" type="l-select" :options="[
98
- { label: 'Production', value: 'prod' },
99
- { label: 'Development', value: 'dev' },
100
-
101
- ]" name="mode" validation="required">
102
- </FormKit>
103
-
104
- <q-separator />
105
-
106
- <FormKit label="Auth lockout duration" type="l-input" name="auth_lockout_duration"
107
- hint="The number of minutes the user is locked out after the maximum number of failed login attempts. Default is 15 minutes."
108
- validation="required" />
109
-
110
- <FormKit label="Auth lockout attempts" type="l-input" name="auth_lockout_attempts"
111
- hint="The number of failed login attempts before the user is locked out. Default is 5 attempts."
112
- validation="required" />
113
-
114
- <FormKit label="Access token expiration" type="l-input" name="access_token_expire"
115
- hint="The access token expiration time in seconds. Default is 28800 seconds (8 hours)."
116
- validation="required" />
117
-
118
- <q-separator />
119
-
120
- <FormKit label="Copyright name" type="l-input" name="copyright_name" validation="required" />
121
- <FormKit label="Copyright year" type="l-input" name="copyright_year" validation="required" />
122
-
123
-
124
- </FormKit>
125
71
 
72
+ <q-card flat bordered>
73
+ <q-splitter unit="px" :model-value="120">
74
+ <template #before>
75
+ <q-tabs v-model="tab" vertical :active-color="$light.color">
76
+ <q-tab name="general" icon="sym_o_info" :label="$t('General')" />
77
+ <q-tab name="security" icon="sym_o_security" :label="$t('Security')" />
78
+ <q-tab name="Modules" icon="sym_o_apps" :label="$t('Modules')" />
79
+ <q-tab name="Developer" icon="sym_o_code" :label="$t('Developer')" />
80
+ </q-tabs>
81
+ </template>
82
+ <template #after>
83
+ <FormKit type="l-form" :value="{
84
+ company: obj.company,
85
+ company_logo: obj.company_logo,
86
+ copyright_name: obj.copyright_name,
87
+ copyright_year: obj.copyright_year
88
+ }" v-if="tab == 'general'" @submit="onSubmit">
89
+ <FormKit type="l-input" label="Company" name="company" validation="required"></FormKit>
90
+ <FormKit type="l-input" label="Company logo" name="company_logo"></FormKit>
91
+
92
+ <FormKit label="Copyright name" type="l-input" name="copyright_name" validation="required" />
93
+ <FormKit label="Copyright year" type="l-input" name="copyright_year" validation="required" />
94
+
95
+ </FormKit>
96
+
97
+ <FormKit type="l-form" :value="{
98
+ password_contains_uppercase: obj.password_contains_uppercase,
99
+ password_contains_lowercase: obj.password_contains_lowercase,
100
+ password_contains_numeric: obj.password_contains_numeric,
101
+ password_contains_symbol: obj.password_contains_symbol,
102
+ password_min_length: obj.password_min_length,
103
+ two_factor_authentication: obj.two_factor_authentication,
104
+ auth_lockout_duration: obj.auth_lockout_duration,
105
+ auth_lockout_attempts: obj.auth_lockout_attempts,
106
+ access_token_expire: obj.access_token_expire,
107
+ }" v-if="tab == 'security'" @submit="onSubmit">
108
+ <q-field label="Password policy" stack-label>
109
+ <FormKit type="q-checkbox" label="Upper Case" name="password_contains_uppercase" true-value="1"
110
+ false-value="0" />
111
+ <FormKit type="q-checkbox" label="Lower Case" name="password_contains_lowercase" true-value="1"
112
+ false-value="0" />
113
+ <FormKit type="q-checkbox" label="Number" name="password_contains_numeric" true-value="1"
114
+ false-value="0" />
115
+ <FormKit type="q-checkbox" label="Special Character" name="password_contains_symbol"
116
+ true-value="1" false-value="0" />
117
+ </q-field>
118
+
119
+ <FormKit type="l-input" label="Password min Length" name="password_min_length"
120
+ validation="required|number">
121
+ </FormKit>
122
+
123
+
124
+ <q-field label="Two factor authentication" stack-label>
125
+ <FormKit type="q-checkbox" label="Enable" name="two_factor_authentication" true-value="1"
126
+ false-value="0" />
127
+ </q-field>
128
+
129
+ <FormKit label="Auth lockout duration" type="l-input" name="auth_lockout_duration"
130
+ hint="The number of minutes the user is locked out after the maximum number of failed login attempts. Default is 15 minutes."
131
+ validation="required" />
132
+
133
+ <FormKit label="Auth lockout attempts" type="l-input" name="auth_lockout_attempts"
134
+ hint="The number of failed login attempts before the user is locked out. Default is 5 attempts."
135
+ validation="required" />
136
+
137
+ <FormKit label="Access token expiration" type="l-input" name="access_token_expire"
138
+ hint="The access token expiration time in seconds. Default is 28800 seconds (8 hours)."
139
+ validation="required" />
140
+ </FormKit>
141
+
142
+ <FormKit type="l-form" :value="{
143
+ file_manager: obj.file_manager,
144
+
145
+ }" v-if="tab == 'Modules'" @submit="onSubmit">
146
+ <q-field label="File manager" stack-label>
147
+ <FormKit type="q-checkbox" label="Show" name="file_manager" true-value="1" false-value="0" />
148
+ </q-field>
149
+ </FormKit>
150
+
151
+ <FormKit type="l-form" :value="{
152
+ mode: obj.mode,
153
+
154
+ }" v-if="tab == 'Developer'" @submit="onSubmit">
155
+ <FormKit label="Mode" type="l-select" :options="[
156
+ { label: 'Production', value: 'prod' },
157
+ { label: 'Development', value: 'dev' },
158
+
159
+ ]" name="mode" validation="required">
160
+ </FormKit>
161
+ </FormKit>
162
+ </template>
163
+ </q-splitter>
164
+ </q-card>
126
165
  </l-page>
127
166
  </template>
@@ -1,55 +1,41 @@
1
1
  <script setup>
2
- import { model, getObject, getModelFields, q } from '../../../';
2
+ import { useLight } from "#imports";
3
+ import { useRoute } from "vue-router"
4
+ import { ref } from 'vue';
3
5
 
4
- const obj = await getObject(["user_id", "username", "first_name", "last_name", "email", "phone", "roles", 'status', 'join_date']);
6
+ const route = useRoute();
7
+ const light = useLight();
5
8
 
9
+ const tab = ref('overview');
10
+ const splitter = ref(10);
11
+ const id = route.params.user_id;
6
12
  </script>
7
13
 
8
14
  <template>
9
- <l-page>
15
+ <l-page edit-btn>
10
16
  <template #header>
11
17
  <l-btn to="change-password" icon="sym_o_key" permission="user.changePassword" label="Change password"></l-btn>
12
18
  <l-btn to="update-role" icon="sym_o_people" permission="user.role.add" label="Update role"></l-btn>
13
19
  </template>
14
20
 
15
- <l-card class="q-mb-md">
16
- <l-list v-model="obj" :fields="getModelFields('User', [
17
- 'username',
18
- 'first_name',
19
- 'last_name',
20
- 'email',
21
- 'phone',
22
- 'roles',
23
- 'status',
24
- 'join_date'
25
- ])">
26
- </l-list>
27
- </l-card>
28
-
29
- <l-tabs>
30
- <l-tab label="Event log">
31
- <l-table row-key="eventlog_id" sort-by="eventlog_id:desc"
32
- :columns="model('EventLog').columns(['eventlog_id', 'class', 'id', 'action', 'created_time'])" @request="async (req) => {
33
- const a = {
34
- listUser: {
35
- __args: {
36
- filters: {
37
- user_id: obj.user_id
38
- }
39
- },
40
- data: {
41
- __args: {
42
- limit: 1
43
- },
44
- eventLog: req.gql
45
- }
46
- }
47
- }
48
-
49
- let resp = await q(a);
50
- req.setData(resp.listUser.data[0].eventLog)
51
- }" />
52
- </l-tab>
53
- </l-tabs>
21
+
22
+ <q-card flat bordered>
23
+ <q-tabs v-model="tab" :class="`text-${light.color}`" inline-label align="justify">
24
+ <q-tab name="overview" icon="sym_o_person" label="Overview" />
25
+ <q-tab name="userlog" icon="sym_o_description" label="User log" />
26
+ <q-tab name="eventlog" icon="sym_o_description" label="Event log" />
27
+ </q-tabs>
28
+
29
+ <l-user-overview v-if="tab === 'overview'" :id="id" />
30
+ <l-user-userlog v-if="tab === 'userlog'" :id="id" />
31
+ <l-user-eventlog v-if="tab === 'eventlog'" :id="id" />
32
+
33
+
34
+
35
+ </q-card>
36
+
37
+
38
+
39
+
54
40
  </l-page>
55
41
  </template>
@@ -51,29 +51,52 @@ eventLogCols.forEach(col => {
51
51
  <l-btn icon="sym_o_password" to="setting/password" label="Update password" />
52
52
  <l-btn icon="sym_o_key" to="setting/two-factor-auth" label="Two factor auth" />
53
53
  </template>
54
- <div class="q-gutter-md q-mt-md">
55
- <l-card>
56
- <l-list>
57
- <l-item label="Username">{{ my.username }}</l-item>
58
- <l-item label="First name">{{ my.first_name }}</l-item>
59
- <l-item label="Last name">{{ my.last_name }}</l-item>
60
- <l-item label="Email">{{ my.email }}</l-item>
61
- <l-item label="Phone">{{ my.phone }}</l-item>
62
- <l-item label="Address">{{ my.addr1 }} {{ my.addr2 }} {{ my.addr3 }}</l-item>
63
- <l-item label="Join date">{{ my.join_date }}</l-item>
64
- <l-item label="Roles">{{ my.roles.join(",") }}</l-item>
65
- </l-list>
66
- </l-card>
67
-
68
- <l-card title="User Log">
69
- <l-table :rows="my.userLog.data" :columns="userlogColumns" searchable :rows-per-page-options="[0]">
70
- </l-table>
71
- </l-card>
72
-
73
- <l-card title="Event Log">
74
- <l-table :rows="my.eventLog.data" :columns="eventLogCols" searchable :rows-per-page-options="[0]">
75
- </l-table>
76
- </l-card>
77
- </div>
54
+
55
+ <l-row>
56
+ <l-col md="4">
57
+
58
+ <l-card>
59
+
60
+ <q-card-section class="text-h5 text-center">
61
+ {{ my.first_name }} {{ my.last_name }}
62
+ </q-card-section>
63
+
64
+ <q-card-section class="text-center text-center q-pt-none">
65
+ <q-chip v-for="role in my.roles" :key="role" :label="role" :color="$light.color" text-color="white"
66
+ class="q-ma-xs" />
67
+ </q-card-section>
68
+
69
+
70
+ <q-separator />
71
+ <l-list :bordered="false">
72
+
73
+ <q-item-label header>Details</q-item-label>
74
+ <l-item label="Username">{{ my.username }}</l-item>
75
+ <l-item label="Email">{{ my.email }}</l-item>
76
+ <l-item label="Phone">{{ my.phone }}</l-item>
77
+ <l-item label="Address">{{ my.addr1 }} {{ my.addr2 }} {{ my.addr3 }}</l-item>
78
+ <l-item label="Join date">{{ my.join_date }}</l-item>
79
+ </l-list>
80
+ </l-card>
81
+ </l-col>
82
+
83
+ <l-col md="8">
84
+
85
+ <l-tabs>
86
+ <l-tab label="User Log">
87
+ <l-table :rows="my.userLog.data" :columns="userlogColumns" searchable :rows-per-page-options="[0]">
88
+ </l-table>
89
+ </l-tab>
90
+ <l-tab label="Event Log">
91
+ <l-table :rows="my.eventLog.data" :columns="eventLogCols" searchable :rows-per-page-options="[0]">
92
+ </l-table>
93
+ </l-tab>
94
+
95
+ </l-tabs>
96
+
97
+
98
+ </l-col>
99
+ </l-row>
100
+
78
101
  </l-page>
79
102
  </template>
@@ -0,0 +1,74 @@
1
+ <script setup>
2
+ import { useLight, model, q } from "#imports"
3
+ import { ref } from "vue"
4
+ import { Notify } from "quasar";
5
+ const light = useLight()
6
+
7
+ const columns = [
8
+ { name: "_delete", align: "center" },
9
+ { name: 'label', label: 'Label', align: 'left' },
10
+ { name: 'path', label: 'Path', align: 'left' },
11
+ { name: 'icon', label: 'Icon', align: 'left' }
12
+ ]
13
+
14
+ const onSave = async (id, data) => {
15
+
16
+ await model("MyFavorite").update(id, data);
17
+
18
+ //show success message
19
+ Notify.create({
20
+ message: "Updated successfully",
21
+ color: "positive",
22
+ icon: "check"
23
+ });
24
+
25
+
26
+ await light.reloadMyFavorites()
27
+
28
+ }
29
+
30
+ const onRemove = async (id) => {
31
+ await model("MyFavorite").delete(id);
32
+ await light.reloadMyFavorites()
33
+ }
34
+
35
+ </script>
36
+ <template>
37
+ <q-table :columns="columns" :rows="$light.myFavorites" :rows-per-page-options="[0]">
38
+
39
+ <template #body-cell-_delete="props">
40
+ <q-td auto-width>
41
+ <q-btn flat icon="sym_o_delete" round @click="onRemove(props.row.my_favorite_id)"></q-btn>
42
+ </q-td>
43
+ </template>
44
+
45
+ <template #body-cell-label="props">
46
+ <q-td key="label">
47
+ {{ props.row.label }}
48
+ <q-popup-edit v-model="props.row.label" #default="scope" buttons
49
+ @save="onSave(props.row.my_favorite_id, { 'label': $event })">
50
+ <q-input v-model="scope.value" dense autofocus counter @keyup.enter="scope.set" />
51
+ </q-popup-edit>
52
+ </q-td>
53
+
54
+ </template>
55
+
56
+ <template #body-cell-path="props">
57
+ <q-td key="path">
58
+ {{ props.row.path }}
59
+ <q-popup-edit v-model="props.row.path" #default="scope" buttons
60
+ @save="onSave(props.row.my_favorite_id, { 'path': $event })">
61
+ <q-input v-model="scope.value" dense autofocus counter @keyup.enter="scope.set" />
62
+ </q-popup-edit>
63
+ </q-td>
64
+ </template>
65
+
66
+ <template #body-cell-icon="props">
67
+ <q-td key="icon">
68
+ <l-icon-picker v-model="props.row.icon" flat round @update:model-value="onSave(
69
+ props.row.my_favorite_id, { 'icon': $event })"></l-icon-picker>
70
+ </q-td>
71
+ </template>
72
+
73
+ </q-table>
74
+ </template>
@@ -23,7 +23,10 @@ const route = useRoute()
23
23
  replace />
24
24
  <q-route-tab name="bio" icon="sym_o_fingerprint" :label="$t('Bio')" to="/User/setting/bio-auth"
25
25
  exact replace />
26
- <q-route-tab name="openid" icon="sym_o_key" :label="$t('Open ID')" to="/User/setting/open_id" exact replace />
26
+ <q-route-tab name="openid" icon="sym_o_key" :label="$t('Open ID')" to="/User/setting/open_id" exact
27
+ replace />
28
+ <q-route-tab name="myfav" icon="sym_o_star" :label="$t('My favorite')"
29
+ to="/User/setting/my_favorite" exact replace />
27
30
 
28
31
  </q-tabs>
29
32
  </template>
@@ -1,4 +1,4 @@
1
- import { Quasar, Dialog, Notify, Loading } from "quasar";
1
+ import { Quasar, Dialog, Notify, Loading, AppFullscreen } from "quasar";
2
2
  import { createI18n } from "vue-i18n";
3
3
  import { defineNuxtPlugin } from "#app";
4
4
  import { useRouter } from "vue-router";
@@ -24,6 +24,7 @@ export default defineNuxtPlugin((nuxtApp) => {
24
24
  defineModel("SystemValue", TypeSystemValue);
25
25
  defineModel("MailLog", TypeMailLog);
26
26
  defineModel("EventLog", TypeEventLog);
27
+ nuxtApp.vueApp.config.globalProperties.$light = useLight();
27
28
  nuxtApp.vueApp.config.errorHandler = (error) => {
28
29
  console.log(error);
29
30
  const light = useLight();
@@ -58,7 +59,8 @@ export default defineNuxtPlugin((nuxtApp) => {
58
59
  plugins: {
59
60
  Dialog,
60
61
  Notify,
61
- Loading
62
+ Loading,
63
+ AppFullscreen
62
64
  }
63
65
  });
64
66
  let locale = localStorage.getItem("locale") || "en";
@@ -131,6 +131,11 @@ function User_setting_information() {
131
131
  /* webpackChunkName: "User-setting-information" */ './pages/User/setting/information.vue'
132
132
  )
133
133
  }
134
+ function User_setting_my_favorite() {
135
+ return import(
136
+ /* webpackChunkName: "User-setting-my_favorite" */ './pages/User/setting/my_favorite.vue'
137
+ )
138
+ }
134
139
  function User_setting_open_id() {
135
140
  return import(
136
141
  /* webpackChunkName: "User-setting-open_id" */ './pages/User/setting/open_id.vue'
@@ -342,6 +347,11 @@ export default [
342
347
  path: 'information',
343
348
  component: User_setting_information,
344
349
  },
350
+ {
351
+ name: 'User-setting-my_favorite',
352
+ path: 'my_favorite',
353
+ component: User_setting_my_favorite,
354
+ },
345
355
  {
346
356
  name: 'User-setting-open_id',
347
357
  path: 'open_id',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hostlink/nuxt-light",
3
- "version": "1.1.8",
3
+ "version": "1.3.0",
4
4
  "description": "HostLink Nuxt Light Framework",
5
5
  "repository": "@hostlink/nuxt-light",
6
6
  "license": "MIT",