@hostlink/nuxt-light 1.7.1 → 1.8.1

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.7.1"
4
+ "version": "1.8.1"
5
5
  }
@@ -0,0 +1,232 @@
1
+ <script setup>
2
+ import { Dialog, Notify } from "quasar"
3
+ import { computed, ref, reactive } from "vue";
4
+ import { q, m } from "#imports";
5
+
6
+ import * as Diff2Html from 'diff2html';
7
+ import 'diff2html/bundles/css/diff2html.min.css';
8
+
9
+ /* const diffs = '--- a/server/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go\n+++ b/server/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go\n@@ -1035,6 +1035,17 @@ func Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (\n \n // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n \n+func Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {\n+\tr0, _, e1 := Syscall6(SYS_PSELECT6, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)))\n+\tn = int(r0)\n+\tif e1 != 0 {\n+\t\terr = errnoErr(e1)\n+\t}\n+\treturn\n+}\n+\n+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n+\n func read(fd int, p []byte) (n int, err error) {\n \tvar _p0 unsafe.Pointer\n \tif len(p) > 0 {\n';
10
+ const html = Diff2Html.html(diffs, {
11
+ drawFileList: true,
12
+ matching: 'lines',
13
+ outputFormat: 'side-by-side',
14
+ });
15
+ */
16
+
17
+ const props = defineProps({
18
+ modelId: {
19
+ type: String,
20
+ required: true
21
+ },
22
+ modelClass: {
23
+ type: String,
24
+ required: true
25
+ }
26
+ });
27
+
28
+
29
+ const { revisionsByModel } = await q({
30
+ "revisionsByModel": {
31
+ __args: {
32
+ model_id: parseInt(props.modelId),
33
+ model_class: props.modelClass
34
+ },
35
+ revision_id: true,
36
+ revisionBy: true,
37
+ createdTime: true,
38
+ content: true,
39
+ delta: true,
40
+ diff: true
41
+ }
42
+ })
43
+
44
+
45
+ const num_of_revisions = computed(() => {
46
+ return revisionsByModel.length;
47
+ })
48
+
49
+ const showDialog = ref(false);
50
+
51
+ const selectedRevision = ref(null);
52
+ const onClick = (revision) => {
53
+ selectedRevision.value = revision;
54
+
55
+ showDialog.value = true;
56
+ }
57
+
58
+ const onRestore = () => {
59
+ //confirm restore
60
+ Dialog.create({
61
+ title: 'Restore',
62
+ message: 'Are you sure you want to restore selected fields?',
63
+ ok: 'Yes',
64
+ cancel: 'No'
65
+ }).onOk(async () => {
66
+ //restore
67
+ if (await m("restoreRevision", {
68
+ revision_id: selectedRevision.value.revision_id,
69
+ fields: restore_fields.value
70
+ })) {
71
+ Notify.create({
72
+ message: 'Restored successfully',
73
+ color: 'positive'
74
+ })
75
+
76
+ //reload
77
+ window.location.reload();
78
+
79
+ }
80
+
81
+
82
+ })
83
+
84
+ }
85
+
86
+ const restore_fields = ref([]);
87
+
88
+ const onToggleAll = () => {
89
+ if (restore_fields.value.length === 0) {
90
+ restore_fields.value = Object.keys(getFilteredContent.value);
91
+ } else {
92
+ restore_fields.value = [];
93
+ }
94
+ }
95
+
96
+ const isCheckedAll = computed(() => {
97
+ return restore_fields.value.length === Object.keys(getFilteredContent.value).length;
98
+ })
99
+
100
+ const isAllowRestore = computed(() => {
101
+ return restore_fields.value.length > 0;
102
+ })
103
+ const showOnlyDelta = ref(false);
104
+
105
+ const getFilteredContent = computed(() => {
106
+ if (showOnlyDelta.value) {
107
+ const contents = {};
108
+
109
+ for (const key in selectedRevision.value.delta) {
110
+ contents[key] = selectedRevision.value.content[key];
111
+ }
112
+
113
+ return contents;
114
+ } else {
115
+ return selectedRevision.value.content;
116
+ }
117
+ })
118
+
119
+ const outputFormat = ref('side-by-side');
120
+ const getDiffHtml = (diffs) => {
121
+ if (!diffs) {
122
+ return '';
123
+ }
124
+ return Diff2Html.html(diffs, {
125
+ drawFileList: false,
126
+ matching: 'lines',
127
+ outputFormat: outputFormat.value,
128
+ highlight: true
129
+ });
130
+ }
131
+
132
+
133
+ </script>
134
+
135
+ <template>
136
+ <div>
137
+
138
+ <div v-html="html"></div>
139
+ <q-dialog v-model="showDialog" full-height full-width>
140
+ <q-card>
141
+ <q-toolbar>
142
+ <l-btn label="Restore" icon="sym_o_restore" permission="revision.restore" @click="onRestore"
143
+ :disabled="!isAllowRestore" />
144
+
145
+ <q-checkbox label="Show changed only" v-model="showOnlyDelta" :color="$light.color"></q-checkbox>
146
+
147
+ <q-btn-toggle class="q-mx-md" v-model="outputFormat" :toggle-color="$light.color" :options="[
148
+ { label: 'side-by-side', value: 'side-by-side' }, { label: 'line-by-line', value: 'line-by-line' }
149
+ ]" />
150
+ <q-space />
151
+ <q-btn flat round dense icon="close" @click="showDialog = false" />
152
+ </q-toolbar>
153
+
154
+
155
+ <div class="q-pa-md">
156
+
157
+ <div class="text-h6 q-mb-md">
158
+ Revision by: {{ selectedRevision.revisionBy }} <br>
159
+ Created at: {{ selectedRevision.createdTime }}
160
+
161
+ </div>
162
+
163
+ <q-markup-table dense separator="cell" flat bordered>
164
+ <thead>
165
+ <tr>
166
+ <th width="48px">
167
+ <q-checkbox @click="onToggleAll" v-model="isCheckedAll"
168
+ :color="$light.color"></q-checkbox>
169
+ </th>
170
+ <th>Field</th>
171
+ <th>Value</th>
172
+ <th>Changed</th>
173
+ </tr>
174
+ </thead>
175
+ <tbody>
176
+ <template v-for="(value, key) in getFilteredContent" :key="key">
177
+
178
+ <tr>
179
+
180
+ <td><q-checkbox v-model="restore_fields" :val="key"
181
+ :color="$light.color"></q-checkbox>
182
+ </td>
183
+ <td :class="{ 'bg-yellow-3': selectedRevision.delta[key] != undefined }">{{ key }}
184
+ </td>
185
+ <td>
186
+ <pre>{{ value }}</pre>
187
+ </td>
188
+ <td>
189
+ <pre>{{ selectedRevision.delta[key] }}</pre>
190
+ </td>
191
+
192
+ </tr>
193
+
194
+ <tr v-if="getDiffHtml(selectedRevision.diff[key])">
195
+ <td colspan="4">
196
+ <div v-html="getDiffHtml(selectedRevision.diff[key])"></div>
197
+ </td>
198
+ </tr>
199
+ </template>
200
+ </tbody>
201
+
202
+
203
+ </q-markup-table>
204
+
205
+ </div>
206
+
207
+
208
+
209
+ </q-card>
210
+ </q-dialog>
211
+
212
+ <l-card>
213
+ <q-list>
214
+ <q-expansion-item :label="`Revisions: ${num_of_revisions}`" icon="sym_o_history" expand-separator>
215
+
216
+ <q-list>
217
+ <q-item v-for="revision in revisionsByModel" :key="revision.revision_id"
218
+ @click="onClick(revision)" clickable>
219
+ <q-item-section>
220
+ <q-item-label>Revision by: {{ revision.revisionBy }}</q-item-label>
221
+ <q-item-label caption>{{ revision.createdTime }}</q-item-label>
222
+
223
+ </q-item-section>
224
+ </q-item>
225
+ </q-list>
226
+
227
+ </q-expansion-item>
228
+
229
+ </q-list>
230
+ </l-card>
231
+ </div>
232
+ </template>
@@ -0,0 +1,36 @@
1
+ <script setup>
2
+ import { computed } from 'vue';
3
+ import { format } from "quasar"
4
+ const { humanStorageSize } = format
5
+ const props = defineProps({
6
+ storage: {
7
+ type: Object,
8
+ required: true
9
+ },
10
+ })
11
+
12
+
13
+ const usagePercent = computed(() => {
14
+ return Math.round((props.storage.totalSpace - props.storage.freeSpace) / props.storage.totalSpace)
15
+ })
16
+
17
+ const progressColor = computed(() => {
18
+ if (usagePercent.value > 0.95) {
19
+ return "negative"
20
+ }
21
+ if (usagePercent.value > 0.9) {
22
+ return "warning"
23
+ }
24
+ return "primary"
25
+ })
26
+
27
+ </script>
28
+ <template>
29
+ <q-card>
30
+ <q-card-section>
31
+ {{ $t("Storage") }}
32
+ <q-linear-progress rounded size="20px" :value="usagePercent" :color="progressColor" class="q-mt-sm" />
33
+ {{ $t('storage_usage', [humanStorageSize(storage.freeSpace), humanStorageSize(storage.totalSpace)]) }}
34
+ </q-card-section>
35
+ </q-card>
36
+ </template>
@@ -3,29 +3,56 @@ import { useRoute, useRouter } from 'vue-router';
3
3
  import { useLight, q, m } from "#imports";
4
4
  import { useQuasar, Loading, Dialog } from 'quasar';
5
5
  import { useI18n } from 'vue-i18n';
6
- import { ref, computed, reactive, provide, watch, toRaw, inject } from 'vue';
6
+ import { ref, computed, reactive, provide, watch, toRaw } from 'vue';
7
7
  import { useRuntimeConfig } from 'nuxt/app';
8
8
 
9
9
  Loading.show()
10
- //download system value
11
- /* import { download } from './../lib/SystemValue'
12
- await download();
13
- */
10
+
14
11
  const config = useRuntimeConfig();
15
12
 
16
13
  const appVersion = config.public.appVersion ?? '0.0.1';
17
14
 
18
15
  const quasar = useQuasar();
19
16
  const tt = await q({
20
- system: ["devMode", "time"],
21
- app: ["menus", "viewAsMode", "languages",
22
- "copyrightYear",
23
- "copyrightName",
24
- "hasFavorite",
25
- { i18nMessages: ["name", "value"] }],
26
- my: ['username', 'first_name', 'last_name', 'roles', "styles", "language", "permissions", "default_page", { myFavorites: ["my_favorite_id", "label", "path", "icon"] }],
17
+ system: {
18
+ devMode: true,
19
+ time: true,
20
+ storage: {
21
+ freeSpace: true,
22
+ usageSpace: true,
23
+ totalSpace: true,
24
+ }
25
+ },
26
+ app: {
27
+ menus: true,
28
+ viewAsMode: true,
29
+ languages: true,
30
+ copyrightName: true,
31
+ copyrightYear: true,
32
+ hasFavorite: true,
33
+ i18nMessages: {
34
+ name: true,
35
+ value: true
36
+ }
37
+ }, my: {
38
+ username: true,
39
+ first_name: true,
40
+ last_name: true,
41
+ roles: true,
42
+ styles: true,
43
+ language: true,
44
+ permissions: true,
45
+ default_page: true,
46
+ myFavorites: {
47
+ my_favorite_id: true,
48
+ label: true,
49
+ path: true,
50
+ icon: true
51
+ }
52
+ }
27
53
  })
28
54
 
55
+
29
56
  let app = tt.app
30
57
  let my = reactive(tt.my)
31
58
 
@@ -54,13 +81,6 @@ i18n.locale = my.language || 'en';
54
81
 
55
82
  let system = tt.system;
56
83
 
57
- if (light.isGranted("system.storage")) {
58
- let s = await q("system", ["diskFreeSpace", "diskUsageSpace", "diskTotalSpace", "diskFreeSpacePercent"]);
59
- //merge system value
60
- system = { ...system, ...s };
61
-
62
- }
63
-
64
84
  // message
65
85
  let messages = i18n.messages.value[i18n.locale];
66
86
  for (let t of app.i18nMessages) {
@@ -168,35 +188,17 @@ const exitViewAs = async () => {
168
188
  }
169
189
 
170
190
  const storageColor = computed(() => {
171
- if (system) {
172
- if (system.diskFreeSpacePercent < 0.05) {
191
+ if (system.storage) {
192
+ const percent = system.storage.freeSpace / system.storage.totalSpace;
193
+ if (percent < 0.05) {
173
194
  return "negative"
174
195
  }
175
- if (system.diskFreeSpacePercent < 0.1) {
196
+ if (percent < 0.1) {
176
197
  return "warning"
177
198
  }
178
199
  }
179
200
  })
180
201
 
181
- const storageProgressColor = computed(() => {
182
- if (system) {
183
- if (system.diskFreeSpacePercent < 0.05) {
184
- return "negative"
185
- }
186
- if (system.diskFreeSpacePercent < 0.1) {
187
- return "warning"
188
- }
189
- }
190
- return "primary"
191
- })
192
-
193
- const storageUsagePercent = computed(() => {
194
- if (system) {
195
- return 1 - system.diskFreeSpacePercent;
196
- }
197
- return 0;
198
- })
199
-
200
202
  const containerClass = computed(() => {
201
203
  return (light.theme == 'dark') ? {} : { 'bg-grey-2': true }
202
204
  })
@@ -223,8 +225,6 @@ const onToggleFav = async () => {
223
225
 
224
226
  //reload my.myFavorites
225
227
  light.reloadMyFavorites();
226
-
227
-
228
228
  return;
229
229
  }
230
230
 
@@ -320,24 +320,13 @@ if (route.fullPath == "/" && my.default_page) {
320
320
  </q-item>
321
321
  </q-list>
322
322
  </q-menu>
323
-
324
-
325
323
  </q-btn>
326
324
 
327
- <q-btn icon="sym_o_storage" flat round dense class="q-mr-sm" v-if="system" :color="storageColor">
325
+ <q-btn icon="sym_o_storage" flat round dense class="q-mr-sm" v-if="system.storage"
326
+ :color="storageColor">
328
327
  <q-menu>
329
- <q-card style="width:250px">
330
- <q-card-section>
331
- {{ $t("Storage") }}
332
- <q-linear-progress rounded size="20px" :value="storageUsagePercent"
333
- :color="storageProgressColor" class="q-mt-sm" />
334
- {{ $t('storage_usage', [system.diskFreeSpace, system.diskTotalSpace]) }}
335
- </q-card-section>
336
-
337
- </q-card>
328
+ <l-storage :storage="system.storage" style="width:250px" />
338
329
  </q-menu>
339
-
340
-
341
330
  </q-btn>
342
331
 
343
332
  <div class="q-mx-sm" v-if="$q.screen.gt.xs">
@@ -422,7 +411,8 @@ if (route.fullPath == "/" && my.default_page) {
422
411
  </q-scroll-area>
423
412
  </q-drawer>
424
413
 
425
- <q-page-container :class="containerClass" :style="containerStyle"> <!-- Error message -->
414
+ <q-page-container :class="containerClass" :style="containerStyle"> <!-- Error message -->
415
+ <slot name="header"></slot>
426
416
  <q-banner dense inline-actions class="bg-grey-4 q-ma-md" v-for=" error in errors " rounded>
427
417
  {{ error }}
428
418
 
@@ -448,9 +438,8 @@ if (route.fullPath == "/" && my.default_page) {
448
438
  <q-item>
449
439
  <q-item-section>
450
440
  {{ light.getCompany() }} {{ appVersion }} - Copyright {{ app.copyrightYear }} {{ app.copyrightName
451
- }}.
452
- Build {{
453
- light.getVersion() }}
441
+ }}. Build
442
+ {{ light.getVersion() }}
454
443
  </q-item-section>
455
444
  </q-item>
456
445
  </q-footer>
@@ -48,7 +48,13 @@ provide('color', color)
48
48
  </q-layout>
49
49
 
50
50
  <l-app-main v-else>
51
+
52
+ <template #header>
53
+ <slot name="header"></slot>
54
+ </template>
55
+
51
56
  <slot></slot>
57
+
58
+
52
59
  </l-app-main>
53
60
  </template>
54
-
@@ -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.7.1",
3
+ "version": "1.8.1",
4
4
  "description": "HostLink Nuxt Light Framework",
5
5
  "repository": "@hostlink/nuxt-light",
6
6
  "license": "MIT",
@@ -40,6 +40,7 @@
40
40
  "@nuxt/module-builder": "^0.5.2",
41
41
  "@quasar/extras": "^1.16.6",
42
42
  "axios": "^1.5.0",
43
+ "diff2html": "^3.4.47",
43
44
  "formkit-quasar": "^0.0.15",
44
45
  "json-to-graphql-query": "^2.2.5",
45
46
  "quasar": "^2.12.5",