@bildvitta/quasar-ui-asteroid 3.5.0-beta.2 → 3.5.0-beta.4
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/package.json +1 -1
- package/src/components/app-bar/QasAppBar.vue +31 -115
- package/src/components/app-bar/QasAppBar.yml +11 -9
- package/src/components/app-menu/QasAppMenu.vue +136 -61
- package/src/components/app-menu/QasAppMenu.yml +35 -0
- package/src/components/app-user/QasAppUser.vue +141 -0
- package/src/components/app-user/QasAppUser.yml +29 -0
- package/src/components/layout/QasLayout.vue +25 -24
- package/src/components/layout/QasLayout.yml +3 -0
- package/src/components/select/QasSelect.vue +8 -0
- package/src/index.scss +1 -1
- package/src/vue-plugin.js +3 -0
package/package.json
CHANGED
|
@@ -1,72 +1,32 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<q-header class="
|
|
3
|
-
<q-toolbar class="
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
<q-badge v-if="hasDevelopmentBadge" align="middle" class="q-ml-sm" color="negative" :label="developmentBadgeLabel" />
|
|
13
|
-
</div>
|
|
2
|
+
<q-header class="qas-app-bar shadow-2" height-hint="56">
|
|
3
|
+
<q-toolbar class="bg-white qas-app-bar__toolbar text-grey-9">
|
|
4
|
+
<qas-btn color="grey-7" dense flat icon="o_menu" round @click="toggleMenuDrawer" />
|
|
5
|
+
|
|
6
|
+
<q-toolbar-title>
|
|
7
|
+
<router-link class="flex items-center no-wrap text-no-decoration" :to="rootRoute">
|
|
8
|
+
<img v-if="brand" :alt="title" class="qas-app-bar__brand" :src="brand">
|
|
9
|
+
<span v-else class="ellipsis text-bold text-primary">{{ title }}</span>
|
|
10
|
+
<q-badge v-if="hasDevelopmentBadge" class="q-ml-sm" color="red" :label="developmentBadgeLabel" />
|
|
11
|
+
</router-link>
|
|
14
12
|
</q-toolbar-title>
|
|
15
13
|
|
|
16
|
-
<
|
|
17
|
-
<qas-
|
|
18
|
-
|
|
19
|
-
</qas-btn>
|
|
20
|
-
</div>
|
|
21
|
-
|
|
22
|
-
<div class="items-center no-wrap q-gutter-md row">
|
|
23
|
-
<slot name="tools" />
|
|
24
|
-
|
|
25
|
-
<div v-if="hasUser" class="cursor-pointer items-center no-wrap qas-app-bar__user-content rounded-borders row text-grey-9" :title="userName">
|
|
26
|
-
<qas-avatar color="white" dark :image="user.photo" rounded size="42px" text-color="primary" :title="userName" />
|
|
27
|
-
|
|
28
|
-
<div class="q-ml-md q-pr-sm qas-app-bar__user-data qs-lh-lg">
|
|
29
|
-
<div class="ellipsis q-mb-xs qas-app-bar__user-name">{{ userName }}</div>
|
|
30
|
-
<div class="ellipsis qas-app-bar__user-email">{{ user.email }}</div>
|
|
31
|
-
</div>
|
|
32
|
-
|
|
33
|
-
<q-menu anchor="bottom end" class="shadow-2 text-grey-9" max-height="400px" :offset="[0, 5]" self="top end">
|
|
34
|
-
<div class="qas-app-bar__user-menu">
|
|
35
|
-
<div class="q-pa-lg text-center">
|
|
36
|
-
<button class="unset" @click="goToProfile">
|
|
37
|
-
<qas-avatar :image="user.photo" size="145px" :title="userName" />
|
|
38
|
-
</button>
|
|
39
|
-
|
|
40
|
-
<div class="ellipsis q-mt-lg qas-app-bar__user-name qs-lh-sm">{{ userName }}</div>
|
|
41
|
-
<div class="ellipsis q-mt-xs">{{ user.email }}</div>
|
|
42
|
-
|
|
43
|
-
<div class="q-mt-sm">
|
|
44
|
-
<qas-btn flat icon="o_edit" label="Editar" :to="user.to" />
|
|
45
|
-
</div>
|
|
46
|
-
|
|
47
|
-
<div class="q-mt-sm">
|
|
48
|
-
<qas-btn v-close-popup class="q-px-lg q-py-xs" dense icon="o_exit_to_app" label="Sair" outline @click="signOut" />
|
|
49
|
-
</div>
|
|
50
|
-
|
|
51
|
-
<slot name="user" :user="user" />
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
</q-menu>
|
|
55
|
-
</div>
|
|
56
|
-
</div>
|
|
14
|
+
<slot v-if="hasUser" name="user" :user="user">
|
|
15
|
+
<qas-app-user :menu-props="appUserMenuProps" :user="user" @sign-out="signOut" />
|
|
16
|
+
</slot>
|
|
57
17
|
</q-toolbar>
|
|
58
18
|
</q-header>
|
|
59
19
|
</template>
|
|
60
20
|
|
|
61
21
|
<script>
|
|
62
|
-
import
|
|
22
|
+
import QasAppUser from '../app-user/QasAppUser.vue'
|
|
63
23
|
import QasBtn from '../btn/QasBtn.vue'
|
|
64
24
|
|
|
65
25
|
export default {
|
|
66
26
|
name: 'QasAppBar',
|
|
67
27
|
|
|
68
28
|
components: {
|
|
69
|
-
|
|
29
|
+
QasAppUser,
|
|
70
30
|
QasBtn
|
|
71
31
|
},
|
|
72
32
|
|
|
@@ -76,16 +36,16 @@ export default {
|
|
|
76
36
|
type: String
|
|
77
37
|
},
|
|
78
38
|
|
|
79
|
-
title: {
|
|
80
|
-
type: String,
|
|
81
|
-
default: ''
|
|
82
|
-
},
|
|
83
|
-
|
|
84
39
|
notifications: {
|
|
85
40
|
default: () => ({}),
|
|
86
41
|
type: Object
|
|
87
42
|
},
|
|
88
43
|
|
|
44
|
+
title: {
|
|
45
|
+
required: true,
|
|
46
|
+
type: String
|
|
47
|
+
},
|
|
48
|
+
|
|
89
49
|
user: {
|
|
90
50
|
default: () => ({}),
|
|
91
51
|
require: true,
|
|
@@ -102,6 +62,14 @@ export default {
|
|
|
102
62
|
},
|
|
103
63
|
|
|
104
64
|
computed: {
|
|
65
|
+
appUserMenuProps () {
|
|
66
|
+
return {
|
|
67
|
+
anchor: 'bottom end',
|
|
68
|
+
offset: [0, 5],
|
|
69
|
+
self: 'top end'
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
|
|
105
73
|
developmentBadgeLabel () {
|
|
106
74
|
const hosts = {
|
|
107
75
|
localhost: 'Local',
|
|
@@ -123,40 +91,16 @@ export default {
|
|
|
123
91
|
return !!this.developmentBadgeLabel
|
|
124
92
|
},
|
|
125
93
|
|
|
126
|
-
hasNotifications () {
|
|
127
|
-
return !!Object.keys(this.notifications).length
|
|
128
|
-
},
|
|
129
|
-
|
|
130
|
-
showTitle () {
|
|
131
|
-
return this.title && !this.brand
|
|
132
|
-
},
|
|
133
|
-
|
|
134
94
|
hasUser () {
|
|
135
95
|
return !!Object.keys(this.user).length
|
|
136
96
|
},
|
|
137
97
|
|
|
138
|
-
|
|
139
|
-
return this.
|
|
140
|
-
},
|
|
141
|
-
|
|
142
|
-
toolbarTitleClass () {
|
|
143
|
-
return !this.$qas.screen.untilLarge && 'q-pl-none'
|
|
98
|
+
rootRoute () {
|
|
99
|
+
return this.$router.hasRoute('Root') ? { name: 'Root' } : { path: '/' }
|
|
144
100
|
}
|
|
145
101
|
},
|
|
146
102
|
|
|
147
103
|
methods: {
|
|
148
|
-
goToProfile () {
|
|
149
|
-
return this.$router.push(this.user.to)
|
|
150
|
-
},
|
|
151
|
-
|
|
152
|
-
goToRoot () {
|
|
153
|
-
const hasRoot = this.$router.hasRoute('Root')
|
|
154
|
-
|
|
155
|
-
this.$router.push({
|
|
156
|
-
...(hasRoot ? { name: 'Root' } : { path: '/' })
|
|
157
|
-
})
|
|
158
|
-
},
|
|
159
|
-
|
|
160
104
|
signOut () {
|
|
161
105
|
this.$emit('sign-out')
|
|
162
106
|
},
|
|
@@ -171,39 +115,11 @@ export default {
|
|
|
171
115
|
<style lang="scss">
|
|
172
116
|
.qas-app-bar {
|
|
173
117
|
&__toolbar {
|
|
174
|
-
height:
|
|
118
|
+
height: 56px;
|
|
175
119
|
}
|
|
176
120
|
|
|
177
121
|
&__brand {
|
|
178
122
|
height: 24px;
|
|
179
|
-
position: relative;
|
|
180
|
-
top: 4px;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
&__user-content {
|
|
184
|
-
width: 230px;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
&__user-data {
|
|
188
|
-
max-width: 180px;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
&__user-name {
|
|
192
|
-
font-weight: 600;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
&__user-menu {
|
|
196
|
-
width: 260px;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
@media (max-width: $breakpoint-xs) {
|
|
200
|
-
&__user-content {
|
|
201
|
-
width: auto;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
&__user-data {
|
|
205
|
-
display: none;
|
|
206
|
-
}
|
|
207
123
|
}
|
|
208
124
|
}
|
|
209
125
|
</style>
|
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
type: component
|
|
2
2
|
|
|
3
3
|
meta:
|
|
4
|
-
desc:
|
|
4
|
+
desc: Gerencia a barra superior da aplicação
|
|
5
5
|
|
|
6
6
|
props:
|
|
7
|
+
brand:
|
|
8
|
+
desc: Path do logotipo.
|
|
9
|
+
type: String
|
|
10
|
+
|
|
7
11
|
notifications:
|
|
8
|
-
desc:
|
|
12
|
+
desc: Lista com as notificações do usuário.
|
|
9
13
|
type: Object
|
|
10
14
|
default: {}
|
|
11
15
|
|
|
12
16
|
title:
|
|
13
|
-
desc: Título
|
|
17
|
+
desc: Título da aplicação.
|
|
18
|
+
required: true
|
|
14
19
|
type: String
|
|
15
20
|
|
|
16
21
|
user:
|
|
17
|
-
desc: Informações
|
|
22
|
+
desc: Informações do usuário.
|
|
18
23
|
type: Object
|
|
19
24
|
default: {}
|
|
20
25
|
examples: [
|
|
@@ -29,16 +34,13 @@ props:
|
|
|
29
34
|
|
|
30
35
|
slots:
|
|
31
36
|
user:
|
|
32
|
-
desc: Slot para acessar o menu de usuário
|
|
37
|
+
desc: Slot para acessar o menu de usuário.
|
|
33
38
|
scope:
|
|
34
39
|
user:
|
|
35
|
-
desc: Informações
|
|
40
|
+
desc: Informações do usuário, recebe o objeto "user".
|
|
36
41
|
type: Object
|
|
37
42
|
default: {}
|
|
38
43
|
|
|
39
|
-
tools:
|
|
40
|
-
desc: Slot para acessar o header após o elemento de notificações.
|
|
41
|
-
|
|
42
44
|
events:
|
|
43
45
|
'@sign-out -> function()':
|
|
44
46
|
desc: Dispara quando o botão de "sair" é clicado.
|
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<q-drawer v-model="model" :behavior="behavior"
|
|
3
|
-
<div class="column
|
|
4
|
-
<div class="
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
<q-drawer v-model="model" :behavior="behavior" class="qas-app-menu" :width="280">
|
|
3
|
+
<div class="column full-height justify-between">
|
|
4
|
+
<div class="full-width">
|
|
5
|
+
<!-- Brand -->
|
|
6
|
+
<div v-if="!$qas.screen.untilLarge" class="q-pt-xl q-px-lg">
|
|
7
|
+
<router-link class="block q-toolbar__title relative-position text-no-decoration" :to="rootRoute">
|
|
8
|
+
<img v-if="brand" :alt="title" class="full-width" :src="brand">
|
|
9
|
+
<span v-else class="ellipsis text-bold text-primary">{{ title }}</span>
|
|
10
|
+
<q-badge color="red" floating :label="developmentBadgeLabel" />
|
|
11
|
+
</router-link>
|
|
11
12
|
</div>
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
<!-- Module -->
|
|
15
|
+
<div v-if="displayModuleSection" class="q-mt-xl q-px-lg qas-app-menu__module">
|
|
16
|
+
<qas-select v-model="module" borderless class="q-py-xs rounded-borders shadow-2" dense input-class="q-px-md" :options="defaultModules" :outlined="false" :use-search="false" @update:model-value="redirectHandler(currentModelOption)" />
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<!-- Menu -->
|
|
20
|
+
<q-list v-if="items.length" class="q-mt-xl qas-app-menu__menu text-grey-9">
|
|
14
21
|
<template v-for="(menuItem, index) in items">
|
|
15
|
-
<div v-if="hasChildren(menuItem)" :key="`children-${index}`"
|
|
16
|
-
<q-item class="items-center">
|
|
22
|
+
<div v-if="hasChildren(menuItem)" :key="`children-${index}`">
|
|
23
|
+
<q-item class="items-center q-pb-none q-pt-md text-weight-bold">
|
|
17
24
|
{{ menuItem.label }}
|
|
18
25
|
</q-item>
|
|
19
26
|
|
|
20
|
-
<q-item v-for="(menuChildItem, childIndex) in menuItem.children" :key="childIndex" :active="isActive(menuChildItem)"
|
|
27
|
+
<q-item v-for="(menuChildItem, childIndex) in menuItem.children" :key="childIndex" :active="isActive(menuChildItem)" :to="getRouterRedirect(menuChildItem)">
|
|
21
28
|
<q-item-section v-if="menuChildItem.icon" avatar>
|
|
22
29
|
<q-icon :name="menuChildItem.icon" />
|
|
23
30
|
</q-item-section>
|
|
@@ -28,7 +35,7 @@
|
|
|
28
35
|
</q-item>
|
|
29
36
|
</div>
|
|
30
37
|
|
|
31
|
-
<q-item v-else :key="index" :active="isActive(menuItem)" active-class="q-router-link--active"
|
|
38
|
+
<q-item v-else :key="index" :active="isActive(menuItem)" active-class="q-router-link--active" :to="getRouterRedirect(menuItem)">
|
|
32
39
|
<q-item-section v-if="menuItem.icon" avatar>
|
|
33
40
|
<q-icon :name="menuItem.icon" />
|
|
34
41
|
</q-item-section>
|
|
@@ -40,17 +47,32 @@
|
|
|
40
47
|
</template>
|
|
41
48
|
</q-list>
|
|
42
49
|
</div>
|
|
50
|
+
|
|
51
|
+
<!-- User -->
|
|
52
|
+
<div v-if="showUser" class="full-width q-pb-lg q-px-lg">
|
|
53
|
+
<qas-app-user avatar-size="48px" :user="user" @sign-out="signOut" />
|
|
54
|
+
</div>
|
|
43
55
|
</div>
|
|
44
56
|
</q-drawer>
|
|
45
57
|
</template>
|
|
46
58
|
|
|
47
59
|
<script>
|
|
60
|
+
import QasAppUser from '../app-user/QasAppUser.vue'
|
|
48
61
|
import { isLocalDevelopment } from '../../helpers'
|
|
49
62
|
|
|
50
63
|
export default {
|
|
51
64
|
name: 'QasAppMenu',
|
|
52
65
|
|
|
66
|
+
components: {
|
|
67
|
+
QasAppUser
|
|
68
|
+
},
|
|
69
|
+
|
|
53
70
|
props: {
|
|
71
|
+
brand: {
|
|
72
|
+
default: '',
|
|
73
|
+
type: String
|
|
74
|
+
},
|
|
75
|
+
|
|
54
76
|
items: {
|
|
55
77
|
default: () => [],
|
|
56
78
|
type: Array
|
|
@@ -61,18 +83,30 @@ export default {
|
|
|
61
83
|
type: Boolean
|
|
62
84
|
},
|
|
63
85
|
|
|
86
|
+
modules: {
|
|
87
|
+
default: () => [],
|
|
88
|
+
type: Array
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
notifications: {
|
|
92
|
+
default: () => ({}),
|
|
93
|
+
type: Object
|
|
94
|
+
},
|
|
95
|
+
|
|
64
96
|
title: {
|
|
65
97
|
default: '',
|
|
98
|
+
required: true,
|
|
66
99
|
type: String
|
|
67
100
|
},
|
|
68
101
|
|
|
69
|
-
|
|
70
|
-
default: () =>
|
|
71
|
-
|
|
102
|
+
user: {
|
|
103
|
+
default: () => ({}),
|
|
104
|
+
require: true,
|
|
105
|
+
type: Object
|
|
72
106
|
}
|
|
73
107
|
},
|
|
74
108
|
|
|
75
|
-
emits: ['update:modelValue'],
|
|
109
|
+
emits: ['sign-out', 'update:modelValue'],
|
|
76
110
|
|
|
77
111
|
data () {
|
|
78
112
|
return {
|
|
@@ -81,6 +115,19 @@ export default {
|
|
|
81
115
|
},
|
|
82
116
|
|
|
83
117
|
computed: {
|
|
118
|
+
behavior () {
|
|
119
|
+
return this.$qas.screen.untilLarge ? 'mobile' : 'desktop'
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
currentModelOption () {
|
|
123
|
+
return this.defaultModules.find(module => module?.value === this.module)
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
currentModule () {
|
|
127
|
+
const hostname = window.location.hostname
|
|
128
|
+
return this.defaultModules.find(module => module?.value.includes(hostname))?.value
|
|
129
|
+
},
|
|
130
|
+
|
|
84
131
|
defaultModules () {
|
|
85
132
|
if (!isLocalDevelopment()) return this.modules
|
|
86
133
|
|
|
@@ -88,7 +135,7 @@ export default {
|
|
|
88
135
|
const { host, protocol } = window.location
|
|
89
136
|
const value = `${protocol}//${host}`
|
|
90
137
|
|
|
91
|
-
//
|
|
138
|
+
// Add a default module called "Localhost" when app is running in local development.
|
|
92
139
|
defaultModules.unshift({
|
|
93
140
|
label: `Localhost ${this.title ? `(${this.title})` : ''}`,
|
|
94
141
|
value
|
|
@@ -97,32 +144,47 @@ export default {
|
|
|
97
144
|
return defaultModules
|
|
98
145
|
},
|
|
99
146
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
147
|
+
developmentBadgeLabel () {
|
|
148
|
+
const hosts = {
|
|
149
|
+
localhost: 'Local',
|
|
150
|
+
'.dev.': 'Develop'
|
|
151
|
+
}
|
|
104
152
|
|
|
105
|
-
|
|
106
|
-
return
|
|
153
|
+
if (process.env.DEV) {
|
|
154
|
+
return hosts.localhost
|
|
107
155
|
}
|
|
108
|
-
},
|
|
109
156
|
|
|
110
|
-
|
|
111
|
-
|
|
157
|
+
const current = Object.keys(hosts).find(
|
|
158
|
+
host => location.hostname.includes(host)
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
return current ? hosts[current] : ''
|
|
112
162
|
},
|
|
113
163
|
|
|
114
164
|
displayModuleSection () {
|
|
115
165
|
return this.defaultModules.length
|
|
116
166
|
},
|
|
117
167
|
|
|
118
|
-
|
|
119
|
-
|
|
168
|
+
hasDevelopmentBadge () {
|
|
169
|
+
return !!this.developmentBadgeLabel
|
|
170
|
+
},
|
|
120
171
|
|
|
121
|
-
|
|
172
|
+
model: {
|
|
173
|
+
get () {
|
|
174
|
+
return this.modelValue
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
set (value) {
|
|
178
|
+
return this.$emit('update:modelValue', value)
|
|
179
|
+
}
|
|
122
180
|
},
|
|
123
181
|
|
|
124
|
-
|
|
125
|
-
return this.$
|
|
182
|
+
rootRoute () {
|
|
183
|
+
return this.$router.hasRoute('Root') ? { name: 'Root' } : { path: '/' }
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
showUser () {
|
|
187
|
+
return this.hasUser && !this.$qas.screen.untilLarge
|
|
126
188
|
}
|
|
127
189
|
},
|
|
128
190
|
|
|
@@ -131,42 +193,50 @@ export default {
|
|
|
131
193
|
handler (value) {
|
|
132
194
|
this.module = value
|
|
133
195
|
},
|
|
196
|
+
|
|
134
197
|
immediate: true
|
|
135
198
|
}
|
|
136
199
|
},
|
|
137
200
|
|
|
138
201
|
methods: {
|
|
139
|
-
|
|
140
|
-
return
|
|
141
|
-
},
|
|
142
|
-
|
|
143
|
-
redirectHandler ({ value }) {
|
|
144
|
-
if (!value.includes(window.location.host)) {
|
|
145
|
-
window.location.href = value
|
|
146
|
-
}
|
|
202
|
+
getNormalizedPath (path) {
|
|
203
|
+
return path.split('/').filter(Boolean)?.[0]
|
|
147
204
|
},
|
|
148
205
|
|
|
149
206
|
getPathFromObject ({ path, name }) {
|
|
150
207
|
if (path) return this.getNormalizedPath(path)
|
|
151
208
|
|
|
152
209
|
const resolvedRoute = this.$router.resolve({ name })
|
|
153
|
-
|
|
154
210
|
return this.getNormalizedPath(resolvedRoute.path)
|
|
155
211
|
},
|
|
156
212
|
|
|
157
|
-
getNormalizedPath (path) {
|
|
158
|
-
return path.split('/').filter(Boolean)?.[0]
|
|
159
|
-
},
|
|
160
|
-
|
|
161
213
|
getRouterRedirect ({ to }) {
|
|
162
214
|
return to || ''
|
|
163
215
|
},
|
|
164
216
|
|
|
217
|
+
hasChildren ({ children }) {
|
|
218
|
+
return !!(children || []).length
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
hasUser () {
|
|
222
|
+
return !!Object.keys(this.user).length
|
|
223
|
+
},
|
|
224
|
+
|
|
165
225
|
isActive ({ to }) {
|
|
166
226
|
const currentPath = this.getNormalizedPath(this.$route.path)
|
|
167
227
|
const itemPath = typeof to === 'string' ? this.getNormalizedPath(to) : this.getPathFromObject(to)
|
|
168
228
|
|
|
169
229
|
return currentPath === itemPath
|
|
230
|
+
},
|
|
231
|
+
|
|
232
|
+
redirectHandler ({ value }) {
|
|
233
|
+
if (!value.includes(window.location.host)) {
|
|
234
|
+
window.location.href = value
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
signOut () {
|
|
239
|
+
this.$emit('sign-out')
|
|
170
240
|
}
|
|
171
241
|
}
|
|
172
242
|
}
|
|
@@ -174,28 +244,33 @@ export default {
|
|
|
174
244
|
|
|
175
245
|
<style lang="scss">
|
|
176
246
|
.qas-app-menu {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
padding-left: var(--qas-spacing-xl);
|
|
183
|
-
}
|
|
247
|
+
// Workaround para alterar o padding interno do QSelect sem influenciar na caixa de opções.
|
|
248
|
+
&__module {
|
|
249
|
+
.q-field__native {
|
|
250
|
+
padding-left: var(--qas-spacing-md);
|
|
251
|
+
}
|
|
184
252
|
|
|
185
|
-
|
|
186
|
-
|
|
253
|
+
.q-field__append {
|
|
254
|
+
margin-right: var(--qas-spacing-sm);
|
|
255
|
+
}
|
|
187
256
|
}
|
|
188
257
|
|
|
189
|
-
&
|
|
190
|
-
|
|
258
|
+
&__menu .q-item {
|
|
259
|
+
padding-left: var(--qas-spacing-lg);
|
|
191
260
|
}
|
|
192
261
|
|
|
193
|
-
|
|
194
|
-
|
|
262
|
+
// User
|
|
263
|
+
.qas-app-user__data {
|
|
264
|
+
line-height: 1.25;
|
|
195
265
|
}
|
|
196
266
|
|
|
197
|
-
|
|
198
|
-
|
|
267
|
+
// Media: untilLarge
|
|
268
|
+
@media (min-width: $breakpoint-sm-max) {
|
|
269
|
+
// Menu
|
|
270
|
+
&__menu {
|
|
271
|
+
max-height: calc(100vh - 310px);
|
|
272
|
+
overflow-x: auto;
|
|
273
|
+
}
|
|
199
274
|
}
|
|
200
275
|
}
|
|
201
276
|
</style>
|
|
@@ -4,6 +4,9 @@ meta:
|
|
|
4
4
|
desc: Menu lateral.
|
|
5
5
|
|
|
6
6
|
props:
|
|
7
|
+
brand:
|
|
8
|
+
desc: Path do logotipo.
|
|
9
|
+
type: String
|
|
7
10
|
items:
|
|
8
11
|
desc: Itens do menu.
|
|
9
12
|
type: Array
|
|
@@ -19,11 +22,43 @@ props:
|
|
|
19
22
|
type: Array
|
|
20
23
|
default: []
|
|
21
24
|
|
|
25
|
+
notifications:
|
|
26
|
+
desc: Lista com as notificações do usuário.
|
|
27
|
+
type: Object
|
|
28
|
+
default: {}
|
|
29
|
+
|
|
22
30
|
title:
|
|
23
31
|
desc: Título que vai ficar no label do select de módulos.
|
|
32
|
+
required: true
|
|
24
33
|
type: String
|
|
25
34
|
|
|
35
|
+
user:
|
|
36
|
+
desc: Informações do usuário.
|
|
37
|
+
type: Object
|
|
38
|
+
default: {}
|
|
39
|
+
examples: [
|
|
40
|
+
"
|
|
41
|
+
{
|
|
42
|
+
photo: 'minha-img',
|
|
43
|
+
name: 'Eduardo Lima',
|
|
44
|
+
email: 'eduardolima@gmail.com'
|
|
45
|
+
}
|
|
46
|
+
"
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
slots:
|
|
50
|
+
user:
|
|
51
|
+
desc: Slot para acessar o menu de usuário.
|
|
52
|
+
scope:
|
|
53
|
+
user:
|
|
54
|
+
desc: Informações do usuário, recebe o objeto "user".
|
|
55
|
+
type: Object
|
|
56
|
+
default: {}
|
|
57
|
+
|
|
26
58
|
events:
|
|
59
|
+
'@sign-out -> function()':
|
|
60
|
+
desc: Dispara quando o botão de "sair" é clicado.
|
|
61
|
+
|
|
27
62
|
'@update:model-value -> function(value)':
|
|
28
63
|
desc: Dispara quando o model-value altera, também usado para v-model.
|
|
29
64
|
params:
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="cursor-pointer items-center no-wrap q-gutter-sm qas-app-user row">
|
|
3
|
+
<div class="relative-position">
|
|
4
|
+
<qas-avatar color="white" dark :image="user.photo" rounded :size="avatarSize" text-color="primary" :title="userName" />
|
|
5
|
+
<q-badge v-if="hasNotifications" color="red" floating>{{ notifications.count }}</q-badge>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<div class="ellipsis qas-app-user__data">
|
|
9
|
+
<div class="ellipsis qas-app-user__name text-grey-9">{{ userName }}</div>
|
|
10
|
+
<div class="ellipsis qas-app-user__email text-grey-8">{{ user.email }}</div>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<q-menu class="shadow-2 text-grey-9" max-height="400px" v-bind="menuProps">
|
|
14
|
+
<div class="q-pb-sm q-pt-md q-px-md qas-app-user__menu">
|
|
15
|
+
<qas-avatar class="q-mb-md" :image="user.photo" size="96px" :title="userName" />
|
|
16
|
+
|
|
17
|
+
<div class="ellipsis qas-app-user__menu-name">{{ userName }}</div>
|
|
18
|
+
<div class="ellipsis">{{ user.email }}</div>
|
|
19
|
+
|
|
20
|
+
<q-list class="q-mt-sm">
|
|
21
|
+
<q-item v-close-popup :active="false" class="qas-app-user__menu-item" clickable :to="user.to">
|
|
22
|
+
<q-item-section avatar>
|
|
23
|
+
<q-icon name="o_person" size="20px" />
|
|
24
|
+
</q-item-section>
|
|
25
|
+
|
|
26
|
+
<q-item-section>Editar</q-item-section>
|
|
27
|
+
</q-item>
|
|
28
|
+
|
|
29
|
+
<q-item v-if="hasNotifications" v-close-popup class="qas-app-user__menu-item" clickable>
|
|
30
|
+
<q-item-section avatar>
|
|
31
|
+
<q-icon name="o_notifications" size="20px" />
|
|
32
|
+
</q-item-section>
|
|
33
|
+
|
|
34
|
+
<q-item-section>Notificações</q-item-section>
|
|
35
|
+
|
|
36
|
+
<q-item-section side>
|
|
37
|
+
<q-badge color="red">{{ notifications.count }}</q-badge>
|
|
38
|
+
</q-item-section>
|
|
39
|
+
</q-item>
|
|
40
|
+
|
|
41
|
+
<q-item v-close-popup class="qas-app-user__menu-item" clickable @click="signOut">
|
|
42
|
+
<q-item-section avatar>
|
|
43
|
+
<q-icon name="o_logout" size="20px" />
|
|
44
|
+
</q-item-section>
|
|
45
|
+
|
|
46
|
+
<q-item-section>Sair</q-item-section>
|
|
47
|
+
</q-item>
|
|
48
|
+
</q-list>
|
|
49
|
+
</div>
|
|
50
|
+
</q-menu>
|
|
51
|
+
</div>
|
|
52
|
+
</template>
|
|
53
|
+
|
|
54
|
+
<script>
|
|
55
|
+
import QasAvatar from '../avatar/QasAvatar.vue'
|
|
56
|
+
|
|
57
|
+
export default {
|
|
58
|
+
name: 'QasAppUser',
|
|
59
|
+
|
|
60
|
+
components: {
|
|
61
|
+
QasAvatar
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
props: {
|
|
65
|
+
avatarSize: {
|
|
66
|
+
default: '36px',
|
|
67
|
+
type: String
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
menuProps: {
|
|
71
|
+
default: () => ({}),
|
|
72
|
+
type: Object
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
notifications: {
|
|
76
|
+
default: () => ({}),
|
|
77
|
+
type: Object
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
user: {
|
|
81
|
+
default: () => ({}),
|
|
82
|
+
required: true,
|
|
83
|
+
type: Object
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
emits: ['sign-out'],
|
|
88
|
+
|
|
89
|
+
computed: {
|
|
90
|
+
hasNotifications () {
|
|
91
|
+
return !!Object.keys(this.notifications).length
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
userName () {
|
|
95
|
+
return this.user.name || this.user.givenName
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
methods: {
|
|
100
|
+
signOut () {
|
|
101
|
+
this.$emit('sign-out')
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
</script>
|
|
106
|
+
|
|
107
|
+
<style lang="scss">
|
|
108
|
+
.qas-app-user {
|
|
109
|
+
&__data {
|
|
110
|
+
line-height: 1.1;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
&__name,
|
|
114
|
+
&__menu-name {
|
|
115
|
+
font-weight: 600;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
&__email {
|
|
119
|
+
font-size: 0.75rem;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
&__menu {
|
|
123
|
+
width: 248px;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
&__menu-name {
|
|
127
|
+
font-size: 1.125rem;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
&__menu-item {
|
|
131
|
+
min-height: 36px;
|
|
132
|
+
padding: 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
@media (max-width: $breakpoint-xs) {
|
|
136
|
+
&__data {
|
|
137
|
+
display: none;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
</style>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
type: component
|
|
2
|
+
|
|
3
|
+
meta:
|
|
4
|
+
desc: Exibe o avatar e o nome do usuário, ao clicar abre um menu com as opções.
|
|
5
|
+
|
|
6
|
+
props:
|
|
7
|
+
notifications:
|
|
8
|
+
desc: Lista com as notificações do usuário.
|
|
9
|
+
type: Object
|
|
10
|
+
default: {}
|
|
11
|
+
|
|
12
|
+
user:
|
|
13
|
+
desc: Informações do usuário.
|
|
14
|
+
required: true
|
|
15
|
+
type: Object
|
|
16
|
+
default: {}
|
|
17
|
+
examples: [
|
|
18
|
+
"
|
|
19
|
+
{
|
|
20
|
+
photo: 'minha-img',
|
|
21
|
+
name: 'Eduardo Lima',
|
|
22
|
+
email: 'eduardolima@gmail.com'
|
|
23
|
+
}
|
|
24
|
+
"
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
events:
|
|
28
|
+
'@sign-out -> function()':
|
|
29
|
+
desc: Dispara quando o botão de "sair" é clicado.
|
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<q-layout view="hHh Lpr lFf">
|
|
3
|
-
<slot name="app-bar">
|
|
4
|
-
<qas-app-bar v-bind="appBarProps" @toggle-menu="toggleMenuDrawer" />
|
|
3
|
+
<slot v-if="$qas.screen.untilLarge" name="app-bar">
|
|
4
|
+
<qas-app-bar v-bind="appBarProps" @sign-out="signOut" @toggle-menu="toggleMenuDrawer" />
|
|
5
5
|
</slot>
|
|
6
6
|
|
|
7
7
|
<slot name="app-menu">
|
|
8
|
-
<qas-app-menu
|
|
8
|
+
<qas-app-menu :model-value="showMenuDrawer" v-bind="defaultAppMenuProps" @sign-out="signOut" @update:model-value="updateMenuDrawer" />
|
|
9
9
|
</slot>
|
|
10
10
|
|
|
11
11
|
<slot>
|
|
12
12
|
<q-page-container>
|
|
13
|
-
<
|
|
13
|
+
<q-page padding>
|
|
14
|
+
<router-view />
|
|
15
|
+
</q-page>
|
|
14
16
|
</q-page-container>
|
|
15
17
|
</slot>
|
|
18
|
+
|
|
19
|
+
<q-ajax-bar color="primary" position="bottom" size="2px" />
|
|
16
20
|
</q-layout>
|
|
17
21
|
</template>
|
|
18
22
|
|
|
@@ -45,42 +49,39 @@ export default {
|
|
|
45
49
|
}
|
|
46
50
|
},
|
|
47
51
|
|
|
48
|
-
emits: ['update:modelValue'],
|
|
52
|
+
emits: ['sign-out', 'update:modelValue'],
|
|
49
53
|
|
|
50
54
|
data () {
|
|
51
55
|
return {
|
|
52
|
-
menuDrawer:
|
|
56
|
+
menuDrawer: false
|
|
53
57
|
}
|
|
54
58
|
},
|
|
55
59
|
|
|
56
60
|
computed: {
|
|
57
61
|
defaultAppMenuProps () {
|
|
58
62
|
return {
|
|
59
|
-
...this.
|
|
60
|
-
|
|
63
|
+
...this.appBarProps,
|
|
64
|
+
...this.appMenuProps
|
|
61
65
|
}
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
watch: {
|
|
66
|
-
modelValue: {
|
|
67
|
-
handler (value) {
|
|
68
|
-
if (!this.$qas.screen.untilLarge) return
|
|
66
|
+
},
|
|
69
67
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
immediate: true
|
|
68
|
+
showMenuDrawer () {
|
|
69
|
+
return !this.$qas.screen.untilLarge || this.menuDrawer
|
|
73
70
|
}
|
|
74
71
|
},
|
|
75
72
|
|
|
76
|
-
mounted () {
|
|
77
|
-
this.menuDrawer = !this.$qas.screen.untilLarge
|
|
78
|
-
},
|
|
79
|
-
|
|
80
73
|
methods: {
|
|
74
|
+
signOut () {
|
|
75
|
+
this.$emit('sign-out')
|
|
76
|
+
},
|
|
77
|
+
|
|
81
78
|
toggleMenuDrawer () {
|
|
82
|
-
this.
|
|
83
|
-
|
|
79
|
+
this.updateMenuDrawer(!this.menuDrawer)
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
updateMenuDrawer (value) {
|
|
83
|
+
this.menuDrawer = value
|
|
84
|
+
this.$emit('update:modelValue', value)
|
|
84
85
|
}
|
|
85
86
|
}
|
|
86
87
|
}
|
|
@@ -30,6 +30,9 @@ slots:
|
|
|
30
30
|
desc: Slot para substituir o "QPageContainer".
|
|
31
31
|
|
|
32
32
|
events:
|
|
33
|
+
'@sign-out -> function()':
|
|
34
|
+
desc: Dispara quando o botão de "sair" é clicado.
|
|
35
|
+
|
|
33
36
|
'@update:model-value -> function(value)':
|
|
34
37
|
desc: Dispara quando o model-value altera, também usado para v-model.
|
|
35
38
|
params:
|
|
@@ -66,6 +66,11 @@ export default {
|
|
|
66
66
|
valueKey: {
|
|
67
67
|
default: '',
|
|
68
68
|
type: String
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
useSearch: {
|
|
72
|
+
type: Boolean,
|
|
73
|
+
default: undefined
|
|
69
74
|
}
|
|
70
75
|
},
|
|
71
76
|
|
|
@@ -122,6 +127,9 @@ export default {
|
|
|
122
127
|
},
|
|
123
128
|
|
|
124
129
|
hasFuse () {
|
|
130
|
+
// se for "undefined" (default) cai na logica por quantidade da option
|
|
131
|
+
if (this.useSearch === false) return false
|
|
132
|
+
|
|
125
133
|
/*
|
|
126
134
|
* quantidade de option que precisa ter para o fuse funcionar automaticamente
|
|
127
135
|
* sem necessidade de passar prop manualmente
|
package/src/index.scss
CHANGED
package/src/vue-plugin.js
CHANGED
|
@@ -3,6 +3,7 @@ import QasActionsMenu from './components/actions-menu/QasActionsMenu.vue'
|
|
|
3
3
|
import QasAlert from './components/alert/QasAlert.vue'
|
|
4
4
|
import QasAppBar from './components/app-bar/QasAppBar.vue'
|
|
5
5
|
import QasAppMenu from './components/app-menu/QasAppMenu.vue'
|
|
6
|
+
import QasAppUser from './components/app-user/QasAppUser.vue'
|
|
6
7
|
import QasAvatar from './components/avatar/QasAvatar.vue'
|
|
7
8
|
import QasBox from './components/box/QasBox.vue'
|
|
8
9
|
import QasBreakline from './components/breakline/QasBreakline.vue'
|
|
@@ -75,6 +76,7 @@ function install (app) {
|
|
|
75
76
|
app.component('QasAlert', QasAlert)
|
|
76
77
|
app.component('QasAppBar', QasAppBar)
|
|
77
78
|
app.component('QasAppMenu', QasAppMenu)
|
|
79
|
+
app.component('QasAppUser', QasAppUser)
|
|
78
80
|
app.component('QasAvatar', QasAvatar)
|
|
79
81
|
app.component('QasBox', QasBox)
|
|
80
82
|
app.component('QasBreakline', QasBreakline)
|
|
@@ -148,6 +150,7 @@ export {
|
|
|
148
150
|
QasAlert,
|
|
149
151
|
QasAppBar,
|
|
150
152
|
QasAppMenu,
|
|
153
|
+
QasAppUser,
|
|
151
154
|
QasAvatar,
|
|
152
155
|
QasBox,
|
|
153
156
|
QasBreakline,
|