@hostlink/nuxt-light 0.0.28 → 0.0.30

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.28"
4
+ "version": "0.0.30"
5
5
  }
package/dist/module.mjs CHANGED
@@ -10,7 +10,6 @@ const module = defineNuxtModule({
10
10
  defaults: {},
11
11
  setup(options, nuxt) {
12
12
  const resolver = createResolver(import.meta.url);
13
- nuxt.options.css.push("element-plus/dist/index.css");
14
13
  nuxt.options.css.push("quasar/dist/quasar.prod.css");
15
14
  nuxt.options.css.push("@quasar/extras/material-icons/material-icons.css");
16
15
  nuxt.options.css.push("@quasar/extras/material-icons-outlined/material-icons-outlined.css");
@@ -1,9 +1,12 @@
1
1
  <script setup>
2
+ import { useQuasar } from 'quasar';
2
3
  import { useI18n } from 'vue-i18n';
3
- import { useLight, q, getCurrentUser, m } from '../';
4
+ import { useLight, q, getCurrentUser, m, f } from '../';
4
5
  import { ref, computed, reactive, provide, watch } from 'vue';
5
6
  //import packageJson from '../../package.json'
6
7
 
8
+ const quasar = useQuasar();
9
+ quasar.dark.set(false);
7
10
  const light = useLight();
8
11
  const props = defineProps({
9
12
  company: {
@@ -12,7 +15,14 @@ const props = defineProps({
12
15
  });
13
16
 
14
17
  let app = await q("app", ["menus", "viewAsMode", "languages"]);
15
- let my = await q("my", ["styles", "language"]);
18
+ let my = await q("my", ["styles", "language", f('granted_storage:granted', { right: "system.storage" }, [])]);
19
+ let system = null
20
+ if (my.granted_storage) {
21
+ system = await q("system", ["diskFreeSpace", "diskTotalSpace", "diskFreeSpacePercent"]);
22
+ }
23
+
24
+ light.setStyles(my.styles);
25
+
16
26
  const menus = ref(app.menus)
17
27
 
18
28
  const i18n = useI18n();
@@ -50,9 +60,9 @@ const layoutView = computed(() => {
50
60
 
51
61
  const style = reactive({
52
62
  color: my.styles?.color || 'bg-primary',
53
- theme: 'semi-dark',
54
- miniState: false,
55
- dense: my.styles?.dense
63
+ theme: my.styles?.theme || 'semi-dark',
64
+ miniState: my.styles?.miniState || false,
65
+ dense: my.styles?.dense || false
56
66
  });
57
67
 
58
68
 
@@ -100,6 +110,7 @@ const reloadMenu = async () => {
100
110
 
101
111
  provide('reloadMenu', reloadMenu)
102
112
 
113
+
103
114
  watch(() => style.dense, async (value) => {
104
115
  await m("updateMyStyle", {
105
116
  name: "dense",
@@ -111,14 +122,31 @@ watch(() => style.color, async (value) => {
111
122
  await m("updateMyStyle", {
112
123
  name: "color",
113
124
  value: value
114
- });
125
+ })
115
126
  })
116
127
 
128
+ watch(() => style.theme, async (value) => {
129
+ await m("updateMyStyle", {
130
+ name: "theme",
131
+ value: value
132
+ })
133
+ })
134
+
135
+ watch(() => style.miniState, async (value) => {
136
+ await m("updateMyStyle", {
137
+ name: "miniState",
138
+ value: value
139
+ })
140
+ });
141
+
117
142
  const exitViewAs = async () => {
118
143
  await m("cancelViewAs");
119
144
  window.location.reload();
120
145
  }
121
146
 
147
+
148
+
149
+
122
150
  </script>
123
151
 
124
152
 
@@ -134,7 +162,7 @@ const exitViewAs = async () => {
134
162
 
135
163
  <q-space />
136
164
 
137
- <q-btn v-if="languages.length > 1" rounded flat icon="language" :label="my.language">
165
+ <q-btn v-if="languages.length > 1" rounded flat icon="language" :label="my.language" class="q-mr-sm">
138
166
  <q-menu>
139
167
  <q-list>
140
168
  <q-item v-for="language in languages" :key="language.value" v-close-popup clickable
@@ -147,7 +175,26 @@ const exitViewAs = async () => {
147
175
  </q-menu>
148
176
  </q-btn>
149
177
 
150
- <div class="q-mx-sm">
178
+ <q-btn icon="sym_o_storage" flat round dense class="q-mr-sm" v-if="my.granted_storage">
179
+ <q-menu>
180
+ <q-card style="width:200px">
181
+ <q-card-section>
182
+ Storage
183
+ <q-linear-progress rounded size="20px" :value="system.diskFreeSpacePercent" color="primary"
184
+ class="q-mt-sm" />
185
+
186
+ {{ system.diskFreeSpace }} / {{ system.diskTotalSpace }}
187
+
188
+
189
+ </q-card-section>
190
+
191
+ </q-card>
192
+ </q-menu>
193
+
194
+
195
+ </q-btn>
196
+
197
+ <div class="q-mx-sm" v-if="$q.platform.is.desktop">
151
198
  <div class="text-bold text-right">
152
199
  {{ user.first_name }} {{ user.last_name }}
153
200
  </div>
@@ -158,6 +205,8 @@ const exitViewAs = async () => {
158
205
  </div>
159
206
 
160
207
 
208
+
209
+
161
210
  <q-btn flat round dense icon="sym_o_person" class="q-mr-sm">
162
211
  <q-menu max-width="250px">
163
212
  <q-list>
@@ -232,7 +281,6 @@ const exitViewAs = async () => {
232
281
  </q-card-section>
233
282
  </q-card>
234
283
 
235
-
236
284
  <router-view v-slot="{ Component }">
237
285
  <template v-if="Component">
238
286
  <suspense>
@@ -70,7 +70,7 @@ const props = defineProps({
70
70
  <q-separator />
71
71
  <q-item>
72
72
  <q-item-section>
73
- <q-item-label>Mini mode</q-item-label>
73
+ <q-item-label>{{ $t('Mini mode') }}</q-item-label>
74
74
  </q-item-section>
75
75
  <q-item-section side>
76
76
  <q-toggle :model-value="miniState" @update:model-value="$emit('update:miniState', $event)" />
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { computed } from "vue";
2
+ import { computed, ref } from "vue";
3
3
  import { useI18n } from 'vue-i18n';
4
4
  const i18n = useI18n();
5
5
 
@@ -22,6 +22,10 @@ const props = defineProps({
22
22
  type: String,
23
23
  default: "text"
24
24
  },
25
+ showPassword: {
26
+ type: Boolean,
27
+ default: false
28
+ }
25
29
  });
26
30
  const emit = defineEmits(["update:modelValue"]);
27
31
 
@@ -54,10 +58,45 @@ const localLabel = computed(() => {
54
58
 
55
59
  });
56
60
 
61
+ const isShowPassword = ref(false);
62
+
63
+ const localType = computed(() => {
64
+ if (props.type == "password" && isShowPassword.value) {
65
+ return "text";
66
+ }
67
+ return props.type;
68
+ });
69
+
70
+
71
+
72
+ const localShowPassword = computed(() => {
73
+ if (props.type != "password") {
74
+ return false;
75
+ }
76
+
77
+ if (!props.showPassword) {
78
+ return false;
79
+ }
80
+
81
+ if (!localValue.value) {
82
+ return false;
83
+ }
84
+
85
+ return true;
86
+
87
+ });
88
+
57
89
 
58
90
 
59
91
 
60
92
  </script>
61
93
  <template>
62
- <q-input :label="localLabel" v-model="localValue" hide-bottom-space :rules="new_rules" :type="type"></q-input>
94
+ <q-input :label="localLabel" v-model="localValue" hide-bottom-space :rules="new_rules" :type="localType">
95
+ <template v-if="localShowPassword" v-slot:append>
96
+ <q-icon name="sym_o_visibility" class="cursor-pointer" :color="showPassword ? 'primary' : 'grey-5'"
97
+ @click="isShowPassword = false" v-if="isShowPassword" />
98
+ <q-icon name="sym_o_visibility_off" class="cursor-pointer" :color="showPassword ? 'grey-5' : 'primary'"
99
+ @click="isShowPassword = true" v-else />
100
+ </template>
101
+ </q-input>
63
102
  </template>
@@ -112,8 +112,8 @@ const forgetPassword = async () => {
112
112
  {{ company }}
113
113
  </div>
114
114
  <q-form ref="form1">
115
- <q-input v-model.trim="data.username" label="Username" :rules="[v => !!v || 'Username is required']" clearable />
116
- <q-input v-model="data.password" label="Password" type="password" clearable
115
+ <l-input v-model.trim="data.username" label="Username" :rules="[v => !!v || 'Username is required']" clearable />
116
+ <l-input v-model="data.password" label="Password" type="password" clearable show-password
117
117
  :rules="[v => !!v || 'Password is required']" @keydown.enter.prevent="submit" />
118
118
  <q-input v-if="twoFactorAuthentication" v-model="data.code" label="2FA code" required type="text" clearable>
119
119
  </q-input>
@@ -1,3 +1,3 @@
1
1
  <template>
2
- <q-btn color="primary" flat rounded icon="sym_o_save" label="Save" />
2
+ <q-btn color="primary" outline rounded icon="sym_o_save" :label="$t('Save')" />
3
3
  </template>
@@ -2,12 +2,16 @@
2
2
  import { useQuasar, QTable } from 'quasar';
3
3
  import { useRoute } from 'vue-router';
4
4
  import { ref, computed, onMounted, useSlots, reactive } from "vue";
5
- import { t, deleteObject, q, f } from '../';
5
+ import { t, deleteObject, q, f, useLight } from '../';
6
6
 
7
7
  const route = useRoute();
8
8
  const module = route.path.split("/")[1];
9
9
  const errors = ref<InstanceType<any>>([]);
10
10
 
11
+ const light = useLight();
12
+
13
+ const tableDense = light.getStyle("tableDense") ?? false;
14
+
11
15
  const props = defineProps({
12
16
  columns: {
13
17
  type: Array<{
@@ -33,6 +37,10 @@ const props = defineProps({
33
37
  type: String,
34
38
  default: null
35
39
  },
40
+ rowsPerPageLabel: {
41
+ type: String,
42
+ default: "Records per page:"
43
+ },
36
44
  })
37
45
 
38
46
 
@@ -328,6 +336,8 @@ const onDelete = async (id: any) => {
328
336
  }
329
337
 
330
338
 
339
+
340
+
331
341
  </script>
332
342
  <template>
333
343
  <template v-if="errors.length > 0">
@@ -337,9 +347,9 @@ const onDelete = async (id: any) => {
337
347
  </ul>
338
348
  </div>
339
349
  </template>
340
-
341
- <q-table flat bordered :columns="renderColumns" v-model:pagination="pagination" ref="table" :loading="loading"
342
- @request="onRequest" :selection="selection" :rows="rows">
350
+ <q-table flat bordered :dense="tableDense" :columns="renderColumns" v-model:pagination="pagination" ref="table"
351
+ :loading="loading" @request="onRequest" :selection="selection" :rows="rows"
352
+ :rows-per-page-label="t(props.rowsPerPageLabel)">
343
353
 
344
354
  <template v-for="s in ss" v-slot:[s]="props">
345
355
  <slot :name="s" v-bind="props"></slot>
@@ -2,6 +2,8 @@ interface Light {
2
2
  addError: (error: String) => void;
3
3
  getErrors: () => String[];
4
4
  removeError: (error: String) => void;
5
+ getStyle: (name: String) => any;
6
+ setStyles: (styles: Object) => void;
5
7
  }
6
8
  export declare function useLight(): Light;
7
9
  export { notify, addObject, f, getApiUrl, getCurrentUser, getObject, id, list, listData, login, m, mutation, q, removeObject, t, updateObject, getID, deleteObject, listObject } from "./lib";
@@ -1,4 +1,5 @@
1
1
  const errors = [];
2
+ let styles = {};
2
3
  export function useLight() {
3
4
  return {
4
5
  addError: (error) => {
@@ -12,6 +13,12 @@ export function useLight() {
12
13
  if (index > -1) {
13
14
  errors.splice(index, 1);
14
15
  }
16
+ },
17
+ getStyle(name) {
18
+ return styles[name];
19
+ },
20
+ setStyles(s) {
21
+ styles = s;
15
22
  }
16
23
  };
17
24
  }
@@ -145,5 +145,7 @@
145
145
  "Menu": "選單",
146
146
  "New": "新增",
147
147
  "Server": "伺服器",
148
- "Remove": "移除"
148
+ "Remove": "移除",
149
+ "Records per page:": "每頁顯示:"
150
+
149
151
  }
@@ -9,8 +9,6 @@ const loadData = async () => {
9
9
  return await q("listRole", ["name", "canDelete", { parents: ["name"] }]);
10
10
 
11
11
  }
12
-
13
-
14
12
  const roles = ref(await loadData());
15
13
 
16
14
  const onDelete = async (role) => {
@@ -29,12 +27,45 @@ const onDelete = async (role) => {
29
27
 
30
28
  }
31
29
 
30
+ const columns = [
31
+ {
32
+ name: "_can_delete"
33
+ },
34
+ {
35
+ name: "name",
36
+ field: "name",
37
+ label: "Name",
38
+ align: "left",
39
+ sortable: true,
40
+ }, {
41
+ name: "parents",
42
+ label: "Parent",
43
+ align: "left",
44
+ }
45
+ ]
46
+
32
47
  </script>
33
48
 
34
49
  <template>
35
50
  <l-page>
51
+ <q-table :rows="roles" flat bordered :columns="columns">
52
+ <template #body-cell-_can_delete="props">
53
+ <q-td auto-width>
54
+ <q-btn v-if="props.row.canDelete" flat round dense icon="sym_o_delete"
55
+ @click="onDelete(props.row.name)" />
56
+ </q-td>
57
+ </template>
58
+
59
+ <template #body-cell-parents="props">
60
+ <q-td>
61
+ <q-table :rows="props.row.parents" flat bordered :rows-per-page-options="[0]" hide-bottom></q-table>
62
+ </q-td>
63
+ </template>
64
+
65
+
66
+ </q-table>
36
67
 
37
- <el-table :data="roles">
68
+ <!-- q-table :data="roles">
38
69
 
39
70
  <el-table-column width="60px" #default="{ row }">
40
71
  <q-btn v-if="row.canDelete" flat round dense icon="sym_o_delete" @click="onDelete(row.name)" />
@@ -49,6 +80,6 @@ const onDelete = async (role) => {
49
80
  </el-table>
50
81
  </template>
51
82
  </el-table-column>
52
- </el-table>
83
+ </q-table -->
53
84
  </l-page>
54
85
  </template>
@@ -34,6 +34,12 @@ const columns = [
34
34
  name: "phone",
35
35
  sortable: true,
36
36
  searchable: true,
37
+ }, {
38
+ label: "Join date",
39
+ name: "join_date",
40
+ sortable: true,
41
+ searchable: true,
42
+ searchType: "date"
37
43
  }
38
44
  ]
39
45
 
@@ -1,3 +1,21 @@
1
+ <script setup>
2
+ import { q, m } from '../../../'
3
+ import { reactive } from 'vue'
4
+ let my = await q("my", ["styles"]);
5
+
6
+ const styles = reactive({
7
+ tableDense: my.styles.tableDense,
8
+ })
9
+
10
+ const onSave = async () => {
11
+ await m("updateMyStyle", {
12
+ name: "tableDense",
13
+ value: styles.tableDense
14
+ });
15
+ }
16
+ </script>
1
17
  <template>
2
- <div>Style</div>
18
+ <l-form @save="onSave" :bordered="false">
19
+ <q-checkbox v-model="styles.tableDense" label="Dense table" />
20
+ </l-form>
3
21
  </template>
@@ -1,4 +1,3 @@
1
1
  import "./assets/main.css";
2
- import './assets/element.css';
3
2
  declare const _default: any;
4
3
  export default _default;
@@ -1,12 +1,8 @@
1
1
  import { Quasar, Dialog, Notify, Loading } from "quasar";
2
- import ElementPlus from "element-plus";
3
2
  import { createI18n } from "vue-i18n";
4
3
  import { defineNuxtPlugin } from "#app";
5
4
  import { useRouter } from "vue-router";
6
5
  import "./assets/main.css";
7
- import "./assets/element.css";
8
- import zhTW from "element-plus/es/locale/lang/zh-tw";
9
- import en from "element-plus/es/locale/lang/en";
10
6
  import message_en from "./locales/en.json";
11
7
  import message_zh from "./locales/zh-hk.json";
12
8
  import routes from "./routes.mjs";
@@ -22,15 +18,14 @@ export default defineNuxtPlugin((nuxtApp) => {
22
18
  legacy: false,
23
19
  locale: localStorage.getItem("locale") || "en",
24
20
  messages: {
25
- en: Object.assign(en, message_en),
26
- "zh-hk": Object.assign(zhTW, message_zh),
27
- "zh-tw": Object.assign(zhTW, message_zh)
21
+ en: message_en,
22
+ "zh-hk": message_zh,
23
+ "zh-tw": message_zh
28
24
  },
29
25
  fallbackWarn: false,
30
26
  missingWarn: false
31
27
  });
32
28
  nuxtApp.vueApp.use(i18n);
33
- nuxtApp.vueApp.use(ElementPlus);
34
29
  nuxtApp.vueApp.use(Quasar, {
35
30
  config: {
36
31
  brand: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hostlink/nuxt-light",
3
- "version": "0.0.28",
3
+ "version": "0.0.30",
4
4
  "description": "HostLink Nuxt Light Framework",
5
5
  "repository": "@hostlink/nuxt-light",
6
6
  "license": "MIT",
@@ -34,7 +34,6 @@
34
34
  "@nuxt/kit": "^3.7.0",
35
35
  "@quasar/extras": "^1.16.6",
36
36
  "axios": "^1.5.0",
37
- "element-plus": "^2.3.12",
38
37
  "gql-query-builder": "^3.8.0",
39
38
  "json-to-graphql-query": "^2.2.5",
40
39
  "quasar": "^2.12.5",