@hostlink/nuxt-light 1.2.1 → 1.3.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.2.1"
4
+ "version": "1.3.1"
5
5
  }
@@ -3,7 +3,7 @@ import { useRoute } 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 } 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()
@@ -23,7 +23,7 @@ const tt = await q({
23
23
  "copyrightName",
24
24
  "hasFavorite",
25
25
  { i18nMessages: ["name", "value"] }],
26
- my: ['username', 'first_name', 'last_name', 'roles', "styles", "language", "permissions", { myFavorites: ["label", "path"] }],
26
+ my: ['username', 'first_name', 'last_name', 'roles', "styles", "language", "permissions", { myFavorites: ["my_favorite_id", "label", "path", "icon"] }],
27
27
  })
28
28
 
29
29
  let app = tt.app
@@ -34,6 +34,16 @@ light.init(my.styles);
34
34
  //set permission
35
35
  light.setPermissions(my.permissions);
36
36
 
37
+ light.setMyFavorites(toRaw(my.myFavorites))
38
+
39
+ const myFavorites = computed(() => {
40
+ return light.getMyFavorites();
41
+ });
42
+
43
+ const myFavoritesCount = computed(() => {
44
+ return light.getMyFavorites().length;
45
+ });
46
+
37
47
  quasar.dark.set(light.isDarkMode());
38
48
 
39
49
  const i18n = useI18n();
@@ -196,17 +206,6 @@ const containerStyle = computed(() => {
196
206
 
197
207
  const route = useRoute()
198
208
 
199
- const reloadMyFavorites = async () => {
200
- const data = await q({
201
- my: {
202
- myFavorites: {
203
- label: true,
204
- path: true,
205
- }
206
- }
207
- });
208
- my.myFavorites = data.my.myFavorites;
209
- }
210
209
 
211
210
  const onToggleFav = async () => {
212
211
 
@@ -216,7 +215,8 @@ const onToggleFav = async () => {
216
215
  })
217
216
 
218
217
  //reload my.myFavorites
219
- reloadMyFavorites();
218
+ light.reloadMyFavorites();
219
+
220
220
 
221
221
  return;
222
222
  }
@@ -236,7 +236,7 @@ const onToggleFav = async () => {
236
236
  path: route.fullPath,
237
237
  label: data,
238
238
  })) {
239
- reloadMyFavorites();
239
+ light.reloadMyFavorites();
240
240
 
241
241
  }
242
242
  })
@@ -252,6 +252,12 @@ const isFav = computed(() => {
252
252
 
253
253
  Loading.hide()
254
254
 
255
+ const menuWidth = ref(my.styles.menuWidth || 280);
256
+
257
+ watch(menuWidth, () => {
258
+ light.setStyle("menuWidth", menuWidth.value)
259
+ })
260
+
255
261
  </script>
256
262
 
257
263
  <template>
@@ -368,13 +374,14 @@ Loading.hide()
368
374
  </q-toolbar>
369
375
  </q-header>
370
376
 
371
- <q-drawer v-model="leftDrawerOpen" bordered show-if-above side="left" :dark="menuDark" :width="280"
377
+ <q-drawer v-model="leftDrawerOpen" bordered show-if-above side="left" :dark="menuDark" :width="menuWidth"
372
378
  :mini-to-overlay="style.miniState" :mini="isMini" @mouseout="isMouseOnDrawer = false"
373
379
  @mouseover="isMouseOnDrawer = true">
374
380
  <!-- drawer content -->
375
381
  <q-scroll-area class="fit">
382
+
376
383
  <div class="q-mx-sm">
377
- <l-fav-menu :value="my.myFavorites" :dense="style.dense" v-if="my.myFavorites.length > 0" />
384
+ <l-fav-menu :value="myFavorites" :dense="style.dense" v-if="myFavoritesCount > 0" />
378
385
  <l-menu v-for=" menu in menus " :value="menu" :dense="style.dense" />
379
386
 
380
387
  </div>
@@ -387,7 +394,7 @@ Loading.hide()
387
394
  <q-scroll-area class="fit">
388
395
  <l-customizer v-model:color="light.color" v-model:theme="light.theme" v-model:miniState="style.miniState"
389
396
  v-model:dense="style.dense" v-model:menuOverlayHeader="style.menuOverlayHeader"
390
- v-model:footer="style.footer" />
397
+ v-model:footer="style.footer" v-model:menuWidth="menuWidth" />
391
398
  </q-scroll-area>
392
399
  </q-drawer>
393
400
 
@@ -2,17 +2,19 @@
2
2
  import { type QBtnProps } from "quasar";
3
3
  import { computed } from "vue";
4
4
  import { useLight } from '#imports';
5
+ import { useI18n } from "vue-i18n";
5
6
 
6
7
  export interface LBtnProps extends QBtnProps {
7
8
  permission?: string;
8
9
  }
9
10
 
11
+ const { t } = useI18n();
10
12
  const props = defineProps<LBtnProps>();
11
13
 
12
14
  const light = useLight();
13
15
 
14
16
  const attrs = computed(() => {
15
- return {
17
+ const a = {
16
18
  ...{
17
19
  rounded: light.getStyle("buttonRounded"),
18
20
  outline: light.getStyle("buttonOutline"),
@@ -21,6 +23,13 @@ const attrs = computed(() => {
21
23
  },
22
24
  ...props,
23
25
  }
26
+
27
+ if (a.label !== undefined) {
28
+ a.label = t(a.label)
29
+ }
30
+
31
+ return a;
32
+
24
33
  });
25
34
 
26
35
 
@@ -89,26 +89,18 @@ if (props.permission && light.isAdmin) {
89
89
  }));
90
90
  }
91
91
 
92
- const onTogglePermission = async (role: any) => {
93
-
92
+ const onUpdatePermission = async (role: any) => {
94
93
  if (role.granted) {
95
-
94
+ await m("addPermission", {
95
+ role: role.name,
96
+ value: props.permission,
97
+ });
98
+ } else {
96
99
  //remove permission
97
- if (await m("removePermission", {
100
+ await m("removePermission", {
98
101
  role: role.name,
99
102
  value: props.permission,
100
- })) {
101
- role.granted = false;
102
- }
103
-
104
- return;
105
- }
106
-
107
- if (await m("addPermission", {
108
- role: role.name,
109
- value: props.permission,
110
- })) {
111
- role.granted = true;
103
+ })
112
104
  }
113
105
  }
114
106
 
@@ -125,13 +117,12 @@ const onTogglePermission = async (role: any) => {
125
117
  <q-btn dense flat icon="sym_o_lock" persistent v-if="showSecurity">
126
118
  <q-menu>
127
119
  <q-list>
128
- <q-item clickable v-for="role in roles" @click="onTogglePermission(role)">
129
- <q-item-section>{{ role.name }}</q-item-section>
130
- <q-item-section side>
131
- <q-icon name="sym_o_done" v-if="role.granted" />
120
+ <q-item clickable v-for="role in roles">
121
+ <q-item-section>
122
+ <q-checkbox :label="role.name" v-model="role.granted"
123
+ @update:model-value="onUpdatePermission(role)"></q-checkbox>
132
124
  </q-item-section>
133
125
  </q-item>
134
-
135
126
  </q-list>
136
127
  </q-menu>
137
128
  </q-btn>
@@ -1,4 +1,9 @@
1
1
  <script setup>
2
+ const menuWidth = defineModel('menuWidth', {
3
+ type: Number,
4
+ default: 280
5
+ });
6
+
2
7
  const COLORS = [
3
8
  'primary',
4
9
  'secondary',
@@ -28,6 +33,8 @@ const COLORS = [
28
33
  'blue-grey'
29
34
  ]
30
35
 
36
+
37
+
31
38
  defineEmits(['update:theme', 'update:menuOverlayHeader', 'update:dense', 'update:color', 'update:miniState', 'update:footer'])
32
39
 
33
40
  const props = defineProps({
@@ -54,7 +61,8 @@ const props = defineProps({
54
61
  footer: {
55
62
  type: Boolean,
56
63
  default: false
57
- }
64
+ },
65
+
58
66
  })
59
67
 
60
68
  </script>
@@ -132,6 +140,15 @@ const props = defineProps({
132
140
  <q-toggle :model-value="footer" @update:model-value="$emit('update:footer', $event)" />
133
141
  </q-item-section>
134
142
  </q-item>
143
+ <q-separator />
144
+ <q-item-label header>{{ $t('Menu width') }}</q-item-label>
145
+ <q-item>
146
+ <q-item-section>
147
+ <q-slider v-model="menuWidth" :min="200" :max="360" label :color="$light.color" />
148
+ </q-item-section>
149
+
150
+ </q-item>
151
+ <q-separator />
135
152
 
136
153
  </q-list>
137
154
  </template>
@@ -1,21 +1,16 @@
1
1
  <script setup>
2
2
  const props = defineProps(["value", "dense"])
3
-
4
- const onClickRemove = () => {
5
- console.log("onClickRemove")
6
- }
7
-
8
3
  </script>
9
4
 
10
5
  <style scoped>
11
6
  .menu-list .q-item{border-radius:12px 12px 12px 12px}.menu-list .q-router-link--exact-active{background:linear-gradient(118deg,var(--q-primary),rgba(115,103,240,.7));color:#fff}
12
7
  </style>
13
8
  <template>
14
- <q-expansion-item :label="$t('My Favorite')" :dense="dense" ref="expansion" icon="sym_o_favorite">
9
+ <q-expansion-item :label="$t('My favorite')" :dense="dense" ref="expansion" icon="sym_o_favorite">
15
10
  <q-list class="q-pl-md menu-list">
16
11
  <q-item v-ripple :to="item.path" v-for="item in value">
17
12
  <q-item-section avatar>
18
- <q-icon name="sym_o_link" />
13
+ <q-icon :name="item.icon ?? 'sym_o_link'" />
19
14
  </q-item-section>
20
15
  <q-item-section>
21
16
  <q-item-label v-text="$t(item.label)"></q-item-label>
@@ -1,13 +1,13 @@
1
1
  <script setup>
2
2
  import { ref, computed, watch } from "vue";
3
+ import { useQuasar } from 'quasar';
3
4
  import { q, m } from '../';
4
5
  const emit = defineEmits(["selected"]);
5
6
  const data = await q("fsListFolders", { path: "/" }, ["name", "path"]);
6
7
  const folders = ref(data);
7
8
  const mode = ref("move");
8
9
  const folder = ref("/");
9
- const parent = ref(null);
10
- const selected = ref("/");
10
+ const parent = ref("/");
11
11
 
12
12
  const qua = useQuasar();
13
13
 
@@ -30,7 +30,7 @@ const title = computed(() => {
30
30
  const newFolder = ref(null);
31
31
 
32
32
  const onClickCreate = async () => {
33
- let f = selected.value + "/" + newFolder.value;
33
+ let f = folder.value + "/" + newFolder.value;
34
34
  await m("fsCreateFolder", { path: f });
35
35
 
36
36
  folder.value = f;
@@ -42,15 +42,15 @@ const menu = ref(null);
42
42
  const onClickMove = async () => {
43
43
  qua.dialog({
44
44
  title: "Move",
45
- message: "Are you sure you want to move?",
45
+ message: "Are you sure you want to move to \"" + folder.value + "\" ?",
46
46
  cancel: true,
47
47
  persistent: true,
48
48
  }).onOk(async () => {
49
49
 
50
50
 
51
51
  menu.value.hide();
52
- emit("selected", selected.value);
53
- selected.value = "/";
52
+ emit("selected", folder.value);
53
+ folder.value = "/";
54
54
  parent.value = null;
55
55
  folder.value = "/";
56
56
 
@@ -63,22 +63,22 @@ const onClickMove = async () => {
63
63
  <q-menu transition-show="jump-down" transition-hide="jump-up" ref="menu" @before-show="show">
64
64
  <q-card>
65
65
  <q-toolbar>
66
- <q-btn flat dense round @click="clickBack()" v-if="parent">
67
- <q-icon name="sym_o_arrow_back" />
68
- </q-btn>
69
- <q-toolbar-title>
70
- <template v-if="mode == 'create'">
71
- <q-input outlined dense v-model="newFolder">
72
- <template v-slot:append>
73
- <q-btn round dense flat icon="sym_o_add" @click="onClickCreate" />
74
- </template>
75
- </q-input>
76
- </template>
77
-
78
- <template v-else>
66
+ <template v-if="mode == 'create'">
67
+ <q-btn flat dense round @click="mode = 'move'" icon="sym_o_arrow_back" class="q-mr-sm">
68
+ <q-tooltip>Cancel</q-tooltip>
69
+ </q-btn>
70
+
71
+ </template>
72
+ <template v-else>
73
+ <q-btn flat dense round @click="clickBack()" v-if="folder !== '/'" icon="sym_o_arrow_back">
74
+ <q-tooltip>Back</q-tooltip>
75
+ </q-btn>
76
+ <q-toolbar-title>
79
77
  {{ title }}
80
- </template>
81
- </q-toolbar-title>
78
+ </q-toolbar-title>
79
+
80
+ </template>
81
+
82
82
  </q-toolbar>
83
83
 
84
84
  <template v-if="mode == 'empty folder'">
@@ -86,35 +86,39 @@ const onClickMove = async () => {
86
86
  </template>
87
87
 
88
88
  <template v-if="mode == 'create'">
89
- <q-card-section> Create folder at "{{ selected }}" </q-card-section>
89
+ <q-card-section>
90
+ <q-input outlined dense v-model="newFolder" :hint="`Create folder at ${folder}`" label="Foler name"
91
+ stack-label="">
92
+ <template v-slot:append v-if="newFolder">
93
+ <q-btn round dense flat icon="sym_o_add" @click="onClickCreate">
94
+ <q-tooltip>Create</q-tooltip>
95
+ </q-btn>
96
+ </template>
97
+ </q-input>
98
+ </q-card-section>
90
99
  </template>
91
100
 
92
101
  <template v-if="mode == 'move'">
93
102
  <q-list>
94
- <q-item v-for="(b, index) in folders" :key="index" clickable @click="selected = b.path"
95
- :active="selected === b.path">
96
- <q-item-section>
103
+ <q-item v-for="(b, index) in folders" :key="index" clickable @click="parent = folder; folder = b.path;">
104
+
105
+ <q-item-section avatar>
97
106
  <q-icon name="sym_o_folder"></q-icon>
98
107
  </q-item-section>
99
108
  <q-item-section>
100
109
  <q-item-label>{{ b.name }}</q-item-label>
101
110
  </q-item-section>
102
111
 
103
- <q-item-section side>
104
- <q-btn flat dense outlined @click="
105
- parent = folder;
106
- folder = b.path;
107
- ">
108
- <q-icon name="sym_o_navigate_next"></q-icon>
109
- </q-btn>
112
+ <q-item-section side avatar>
113
+ <q-icon name="sym_o_navigate_next"></q-icon>
110
114
  </q-item-section>
111
115
  </q-item>
112
116
  </q-list>
113
117
  </template>
114
118
 
115
119
  <q-card-actions>
116
- <q-btn flat dense @click="mode = 'create'" :disable="mode == 'create'">
117
- <q-icon name="sym_o_create_new_folder"></q-icon>
120
+ <q-btn flat dense @click="mode = 'create'" :disable="mode == 'create'" round icon="sym_o_create_new_folder">
121
+ <q-tooltip> Create new folder</q-tooltip>
118
122
  </q-btn>
119
123
  <q-space></q-space>
120
124
  <q-btn dense label="Move to here" color="primary" v-if="mode == 'empty folder'">
@@ -123,65 +127,4 @@ const onClickMove = async () => {
123
127
  </q-card-actions>
124
128
  </q-card>
125
129
  </q-menu>
126
- </template>
127
- <!--
128
- <script>
129
- import { listFolders, createFolder } from "./../lib/filemanager";
130
-
131
-
132
- export default {
133
- data() {
134
- return {
135
- selected: "/",
136
- folder: null,
137
- folders: [],
138
- parent: null,
139
- mode: "move",
140
- newFolder: null,
141
- };
142
- },
143
- watch: {
144
- async folder() {
145
- this.folders = await listFolders(this.folder);
146
-
147
- if (this.folders.length == 0) {
148
- this.mode = "empty folder";
149
- }
150
- },
151
- },
152
- computed: {
153
- title() {
154
- if (this.folder) {
155
- return this.folder.split("/").pop();
156
- }
157
- return "";
158
- },
159
- },
160
-
161
- methods: {
162
- show() {
163
- this.folder = "/";
164
- this.mode = "move";
165
- },
166
- async onClickCreate() {
167
- let folder = this.selected + "/" + this.newFolder;
168
- await createFolder(folder);
169
- this.folder = folder;
170
- },
171
- clickBack() {
172
- if (this.mode == "create") {
173
- this.mode = "move";
174
- return;
175
- }
176
-
177
- this.folder = this.parent;
178
-
179
-
180
- if (this.mode == "empty folder") {
181
- this.mode = "move";
182
- return;
183
- }
184
- },
185
- },
186
- };
187
- </script> -->
130
+ </template>
@@ -587,10 +587,21 @@ const isDark = computed(() => light.isDarkMode());
587
587
 
588
588
  <q-btn flat round icon="sym_o_drive_file_move" v-if="selected.length > 0">
589
589
  <l-file-manager-move @selected="moveToFolder($event)" />
590
+ <q-tooltip>
591
+ {{ $t('Move to') }}
592
+ </q-tooltip>
590
593
  </q-btn>
591
594
 
592
- <q-btn flat round icon="o_delete" @click="onDeleteSelected" v-if="selected.length > 0"></q-btn>
593
- <q-btn flat round :icon="grid ? 'list_view' : 'grid_view'" @click="grid = !grid"></q-btn>
595
+ <q-btn flat round icon="o_delete" @click="onDeleteSelected" v-if="selected.length > 0">
596
+ <q-tooltip>
597
+ {{ $t('Delete') }}
598
+ </q-tooltip>
599
+ </q-btn>
600
+ <q-btn flat round :icon="grid ? 'list_view' : 'grid_view'" @click="grid = !grid">
601
+ <q-tooltip>
602
+ {{ grid ? $t('List view') : $t('Grid view') }}
603
+ </q-tooltip>
604
+ </q-btn>
594
605
  </q-toolbar>
595
606
 
596
607
  <template v-if="grid">
@@ -167,7 +167,7 @@ const onUploadFile = async () => {
167
167
  </q-card-section>
168
168
 
169
169
  <q-card-actions align="right">
170
- <q-btn flat :label="$t('Cancel')" color="primary" v-close-popup></q-btn>
170
+ <q-btn flat :label="$t('Cancel')" color="primary" @click="uploadFile = null" v-close-popup></q-btn>
171
171
  <q-btn flat :label="$t('Upload')" color="primary" @click="onUploadFile"></q-btn>
172
172
  </q-card-actions>
173
173
  </l-card>
@@ -175,5 +175,9 @@ const onUploadFile = async () => {
175
175
  <template v-slot:prepend>
176
176
  <q-btn dense flat round icon="sym_o_file_upload" @click="show = true"></q-btn>
177
177
  </template>
178
+
179
+ <template v-for="(s, name) in $slots" v-slot:[name]="props" :key="name">
180
+ <slot :name="name" v-bind="props ?? {}"></slot>
181
+ </template>
178
182
  </q-input>
179
183
  </template>