@hostlink/nuxt-light 1.6.8 → 1.8.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 CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "light",
3
3
  "configKey": "light",
4
- "version": "1.6.8"
4
+ "version": "1.8.0"
5
5
  }
@@ -0,0 +1,187 @@
1
+ <script setup>
2
+ import { Dialog, Notify } from "quasar"
3
+ import { computed, ref, reactive } from "vue";
4
+ import { q, m } from "#imports";
5
+
6
+ const props = defineProps({
7
+ modelId: {
8
+ type: String,
9
+ required: true
10
+ },
11
+ modelClass: {
12
+ type: String,
13
+ required: true
14
+ }
15
+ });
16
+
17
+
18
+ const { revisionsByModel } = await q({
19
+ "revisionsByModel": {
20
+ __args: {
21
+ model_id: parseInt(props.modelId),
22
+ model_class: props.modelClass
23
+ },
24
+ revision_id: true,
25
+ revisionBy: true,
26
+ createdTime: true,
27
+ content: true,
28
+ delta: true
29
+ }
30
+ })
31
+
32
+
33
+ const num_of_revisions = computed(() => {
34
+ return revisionsByModel.length;
35
+ })
36
+
37
+ const showDialog = ref(false);
38
+
39
+ const selectedRevision = ref(null);
40
+ const onClick = (revision) => {
41
+ selectedRevision.value = revision;
42
+
43
+ showDialog.value = true;
44
+ }
45
+
46
+ const onRestore = () => {
47
+ //confirm restore
48
+ Dialog.create({
49
+ title: 'Restore',
50
+ message: 'Are you sure you want to restore selected fields?',
51
+ ok: 'Yes',
52
+ cancel: 'No'
53
+ }).onOk(async () => {
54
+ //restore
55
+ if (await m("restoreRevision", {
56
+ revision_id: selectedRevision.value.revision_id,
57
+ fields: restore_fields.value
58
+ })) {
59
+ Notify.create({
60
+ message: 'Restored successfully',
61
+ color: 'positive'
62
+ })
63
+
64
+ //reload
65
+ window.location.reload();
66
+
67
+ }
68
+
69
+
70
+ })
71
+
72
+ }
73
+
74
+ const restore_fields = ref([]);
75
+
76
+ const onToggleAll = () => {
77
+ if (restore_fields.value.length === 0) {
78
+ restore_fields.value = Object.keys(getFilteredContent.value);
79
+ } else {
80
+ restore_fields.value = [];
81
+ }
82
+ }
83
+
84
+ const isCheckedAll = computed(() => {
85
+ return restore_fields.value.length === Object.keys(getFilteredContent.value).length;
86
+ })
87
+
88
+ const isAllowRestore = computed(() => {
89
+ return restore_fields.value.length > 0;
90
+ })
91
+ const showOnlyDelta = ref(false);
92
+
93
+ const getFilteredContent = computed(() => {
94
+ if (showOnlyDelta.value) {
95
+ const contents = {};
96
+
97
+ for (const key in selectedRevision.value.delta) {
98
+ contents[key] = selectedRevision.value.content[key];
99
+ }
100
+
101
+ return contents;
102
+ } else {
103
+ return selectedRevision.value.content;
104
+ }
105
+
106
+ })
107
+ </script>
108
+ <template>
109
+ <div>
110
+
111
+
112
+ <q-dialog v-model="showDialog" full-height full-width>
113
+ <q-card>
114
+ <q-toolbar>
115
+ <l-btn label="Restore" icon="sym_o_restore" permission="revision.restore" @click="onRestore"
116
+ :disabled="!isAllowRestore" />
117
+
118
+ <q-checkbox label="Show delta only" v-model="showOnlyDelta" :color="$light.color"></q-checkbox>
119
+ <q-space />
120
+ <q-btn flat round dense icon="close" @click="showDialog = false" />
121
+ </q-toolbar>
122
+
123
+
124
+ <div class="q-pa-md">
125
+ <div class="text-h4 q-mb-md">
126
+ Revision
127
+ </div>
128
+
129
+ <q-markup-table dense separator="cell" flat bordered>
130
+ <thead>
131
+ <tr>
132
+ <th width="48px">
133
+ <q-checkbox @click="onToggleAll" v-model="isCheckedAll"
134
+ :color="$light.color"></q-checkbox>
135
+ </th>
136
+ <th>Field</th>
137
+ <th>Value</th>
138
+ <th>Delta</th>
139
+ </tr>
140
+ </thead>
141
+ <tbody>
142
+ <tr v-for="(value, key) in getFilteredContent" :key="key">
143
+
144
+ <td><q-checkbox v-model="restore_fields" :val="key" :color="$light.color"></q-checkbox>
145
+ </td>
146
+ <td :class="{ 'bg-yellow-3': selectedRevision.delta[key] != undefined }">
147
+ {{ key }}</td>
148
+ <td>
149
+ <pre>{{ value }}</pre>
150
+ </td>
151
+ <td>
152
+ <pre>{{ selectedRevision.delta[key] }}</pre>
153
+ </td>
154
+ </tr>
155
+ </tbody>
156
+
157
+
158
+ </q-markup-table>
159
+
160
+ </div>
161
+
162
+
163
+
164
+ </q-card>
165
+ </q-dialog>
166
+
167
+ <l-card>
168
+ <q-list>
169
+ <q-expansion-item :label="`Revisions: ${num_of_revisions}`" icon="sym_o_history" expand-separator>
170
+
171
+ <q-list>
172
+ <q-item v-for="revision in revisionsByModel" :key="revision.revision_id"
173
+ @click="onClick(revision)" clickable>
174
+ <q-item-section>
175
+ <q-item-label>Revision by: {{ revision.revisionBy }}</q-item-label>
176
+ <q-item-label caption>{{ revision.createdTime }}</q-item-label>
177
+
178
+ </q-item-section>
179
+ </q-item>
180
+ </q-list>
181
+
182
+ </q-expansion-item>
183
+
184
+ </q-list>
185
+ </l-card>
186
+ </div>
187
+ </template>
@@ -157,8 +157,10 @@ onMounted(() => {
157
157
  google.accounts.id.initialize({
158
158
  client_id: props.googleClientId,
159
159
  callback: handleGoogleCredentialResponse,
160
- });
160
+ use_fedcm_for_prompt: true
161
161
 
162
+ });
163
+ google.accounts.id.prompt();
162
164
  google.accounts.id.renderButton(
163
165
  document.getElementById('g_id_signin'),
164
166
  {
@@ -23,9 +23,12 @@ const fields = ["company", "company_logo",
23
23
  "auth_lockout_attempts",
24
24
  "access_token_expire",
25
25
  "copyright_year",
26
- "copyright_name"
26
+ "copyright_name",
27
+ "revision"
27
28
  ];
28
29
 
30
+ obj.revision = obj.revision ? obj.revision.split(',') : []
31
+
29
32
  //filter out fields that are not in the app.config table
30
33
  Object.keys(obj).forEach((key) => {
31
34
  if (!fields.includes(key)) {
@@ -80,11 +83,11 @@ const tab = ref('general')
80
83
  </template>
81
84
  <template #after>
82
85
  <FormKit type="l-form" :bordered="false" :value="{
83
- company: obj.company,
84
- company_logo: obj.company_logo,
85
- copyright_name: obj.copyright_name,
86
- copyright_year: obj.copyright_year
87
- }" v-if="tab == 'general'" @submit="onSubmit">
86
+ company: obj.company,
87
+ company_logo: obj.company_logo,
88
+ copyright_name: obj.copyright_name,
89
+ copyright_year: obj.copyright_year
90
+ }" v-if="tab == 'general'" @submit="onSubmit">
88
91
  <FormKit type="l-input" label="Company" name="company" validation="required"></FormKit>
89
92
  <FormKit type="l-input" label="Company logo" name="company_logo"></FormKit>
90
93
 
@@ -94,21 +97,21 @@ const tab = ref('general')
94
97
  </FormKit>
95
98
 
96
99
  <FormKit type="l-form" :bordered="false" :value="{
97
- password_contains_uppercase: obj.password_contains_uppercase,
98
- password_contains_lowercase: obj.password_contains_lowercase,
99
- password_contains_numeric: obj.password_contains_numeric,
100
- password_contains_symbol: obj.password_contains_symbol,
101
- password_min_length: obj.password_min_length,
102
- two_factor_authentication: obj.two_factor_authentication,
103
- auth_lockout_duration: obj.auth_lockout_duration,
104
- auth_lockout_attempts: obj.auth_lockout_attempts,
105
- access_token_expire: obj.access_token_expire,
106
- }" v-if="tab == 'security'" @submit="onSubmit">
100
+ password_contains_uppercase: obj.password_contains_uppercase,
101
+ password_contains_lowercase: obj.password_contains_lowercase,
102
+ password_contains_numeric: obj.password_contains_numeric,
103
+ password_contains_symbol: obj.password_contains_symbol,
104
+ password_min_length: obj.password_min_length,
105
+ two_factor_authentication: obj.two_factor_authentication,
106
+ auth_lockout_duration: obj.auth_lockout_duration,
107
+ auth_lockout_attempts: obj.auth_lockout_attempts,
108
+ access_token_expire: obj.access_token_expire,
109
+ }" v-if="tab == 'security'" @submit="onSubmit">
107
110
  <q-field label="Password policy" stack-label>
108
- <FormKit type="l-checkbox" label="Upper Case" name="password_contains_uppercase" true-value="1"
109
- false-value="0" />
110
- <FormKit type="l-checkbox" label="Lower Case" name="password_contains_lowercase" true-value="1"
111
- false-value="0" />
111
+ <FormKit type="l-checkbox" label="Upper Case" name="password_contains_uppercase"
112
+ true-value="1" false-value="0" />
113
+ <FormKit type="l-checkbox" label="Lower Case" name="password_contains_lowercase"
114
+ true-value="1" false-value="0" />
112
115
  <FormKit type="l-checkbox" label="Number" name="password_contains_numeric" true-value="1"
113
116
  false-value="0" />
114
117
  <FormKit type="l-checkbox" label="Special Character" name="password_contains_symbol"
@@ -139,23 +142,29 @@ const tab = ref('general')
139
142
  </FormKit>
140
143
 
141
144
  <FormKit type="l-form" :bordered="false" :value="{
142
- file_manager: obj.file_manager,
143
-
144
- }" v-if="tab == 'Modules'" @submit="onSubmit">
145
+ file_manager: obj.file_manager,
146
+ revision: obj.revision
147
+ }" v-if="tab == 'Modules'" @submit="onSubmit">
145
148
  <q-field label="File manager" stack-label>
146
- <FormKit type="l-checkbox" label="Show" name="file_manager" true-value="1" false-value="0" />
149
+ <FormKit type="l-checkbox" label="Show" name="file_manager" true-value="1"
150
+ false-value="0" />
147
151
  </q-field>
152
+
153
+ <FormKit type="q-select" label="Revision" name="revision" use-input use-chips multiple
154
+ hide-dropdown-icon input-debounce="0" new-value-mode="add-unique" />
155
+
156
+
148
157
  </FormKit>
149
158
 
150
159
  <FormKit type="l-form" :bordered="false" :value="{
151
- mode: obj.mode,
160
+ mode: obj.mode,
152
161
 
153
- }" v-if="tab == 'Developer'" @submit="onSubmit">
162
+ }" v-if="tab == 'Developer'" @submit="onSubmit">
154
163
  <FormKit label="Mode" type="l-select" :options="[
155
- { label: 'Production', value: 'prod' },
156
- { label: 'Development', value: 'dev' },
164
+ { label: 'Production', value: 'prod' },
165
+ { label: 'Development', value: 'dev' },
157
166
 
158
- ]" name="mode" validation="required" >
167
+ ]" name="mode" validation="required">
159
168
  </FormKit>
160
169
  </FormKit>
161
170
  </template>
@@ -7,18 +7,17 @@ const route = useRoute();
7
7
  const light = useLight();
8
8
 
9
9
  const tab = ref('overview');
10
- const splitter = ref(10);
11
10
  const id = route.params.user_id;
12
11
  </script>
13
12
 
14
13
  <template>
15
14
  <l-page edit-btn>
16
15
  <template #header>
17
- <l-btn to="change-password" icon="sym_o_key" permission="user.changePassword" label="Change password"></l-btn>
16
+ <l-btn to="change-password" icon="sym_o_key" permission="user.changePassword"
17
+ label="Change password"></l-btn>
18
18
  <l-btn to="update-role" icon="sym_o_people" permission="user.role.add" label="Update role"></l-btn>
19
19
  </template>
20
20
 
21
-
22
21
  <q-card flat bordered>
23
22
  <q-tabs v-model="tab" :active-color="$light.color" inline-label align="justify">
24
23
  <q-tab name="overview" icon="sym_o_person" label="Overview" />
@@ -5,7 +5,7 @@ const onRequest = async (request) => {
5
5
  request.loadObjects("User", { status: status.value });
6
6
  //request.loadObjects("User");
7
7
  };
8
- const columns = model("User").columns(["username", "first_name", "label_name", "email", "phone", "join_date", "status"]);
8
+ const columns = model("User").columns(["username", "first_name", "label_name", "email", "phone", "join_date", "status","has2FA"]);
9
9
  const status = ref("0");
10
10
  const selected = ref([]);
11
11
  </script>
@@ -13,7 +13,6 @@ const selected = ref([]);
13
13
  <template>
14
14
  <l-page>
15
15
 
16
-
17
16
  <l-tabs v-model="status">
18
17
  <l-tab label="Active" name="0">
19
18
  <l-table row-key="user_id" @request="onRequest" :columns="columns"
@@ -52,5 +52,10 @@ declare const _default: {
52
52
  field: (row: any) => any;
53
53
  backgroundColor: (row: any) => "primary" | undefined;
54
54
  };
55
+ has2FA: {
56
+ label: string;
57
+ searchType: string;
58
+ format: (value: any) => "Yes" | "No";
59
+ };
55
60
  };
56
61
  export default _default;
@@ -67,5 +67,12 @@ export default {
67
67
  return "primary";
68
68
  }
69
69
  }
70
+ },
71
+ has2FA: {
72
+ label: "2FA",
73
+ searchType: "select",
74
+ format: (value) => {
75
+ return value ? "Yes" : "No";
76
+ }
70
77
  }
71
78
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hostlink/nuxt-light",
3
- "version": "1.6.8",
3
+ "version": "1.8.0",
4
4
  "description": "HostLink Nuxt Light Framework",
5
5
  "repository": "@hostlink/nuxt-light",
6
6
  "license": "MIT",