@afeefa/vue-app 0.0.173 → 0.0.174
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/.afeefa/package/release/version.txt +1 -1
- package/package.json +1 -1
- package/src/components/AInfo.vue +11 -1
- package/src/components/ALoadingIndicator.vue +4 -0
- package/src/components/ATable.vue +6 -0
- package/src/components/ATableRow.vue +5 -0
- package/src/plugins/route-config/RouteConfigPlugin.js +17 -0
- package/src/utils/format-time.js +17 -0
- package/src-admin/components/App.vue +48 -186
- package/src-admin/components/CollapsibleSection.vue +64 -0
- package/src-admin/components/FlyingContextContainer.vue +1 -1
- package/src-admin/components/HSeparator.vue +90 -0
- package/src-admin/components/InformationBar.vue +176 -0
- package/src-admin/components/NavigationBar.vue +187 -0
- package/src-admin/components/StickyHeader.vue +39 -8
- package/src-admin/components/app/AppBarTitle.vue +6 -11
- package/src-admin/components/detail/DetailProperty.vue +11 -16
- package/src-admin/components/index.js +9 -2
- package/src-admin/components/sidebar/InformationBarItem.vue +178 -0
- package/src-admin/components/sidebar/SidebarEvent.js +5 -0
- package/src-admin/components/sidebar/SidebarService.js +107 -0
- package/src-admin/components/transitions/CollapseTransition.vue +61 -0
- package/src-admin/config/vuetify.js +7 -1
- package/src-admin/events.js +1 -0
- package/src-admin/styles.scss +10 -2
- package/src-admin/components/Sidebar.vue +0 -66
- package/src-admin/components/SidebarItem.vue +0 -59
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.174
|
package/package.json
CHANGED
package/src/components/AInfo.vue
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
<v-alert
|
3
3
|
v-bind="$attrs"
|
4
4
|
:style="{display: inline ? 'inline-block' : 'block'}"
|
5
|
+
:class="['a-info', {xSmall}]"
|
5
6
|
dense
|
6
7
|
border="left"
|
7
8
|
colored-border
|
@@ -16,11 +17,20 @@
|
|
16
17
|
import { Component, Vue } from '@a-vue'
|
17
18
|
|
18
19
|
@Component({
|
19
|
-
props: [{inline: true}]
|
20
|
+
props: [{inline: true, xSmall: false}]
|
20
21
|
})
|
21
22
|
export default class AInfo extends Vue {
|
22
23
|
}
|
23
24
|
</script>
|
24
25
|
|
25
26
|
<style lang="scss" scoped>
|
27
|
+
.xSmall {
|
28
|
+
padding: .3rem .6rem;
|
29
|
+
font-size: .9rem;
|
30
|
+
|
31
|
+
:deep(.v-icon) {
|
32
|
+
margin-left: .2rem;
|
33
|
+
margin-right: .4rem;
|
34
|
+
}
|
35
|
+
}
|
26
36
|
</style>
|
@@ -53,6 +53,12 @@ export default class ATable extends Vue {
|
|
53
53
|
|
54
54
|
white-space: nowrap;
|
55
55
|
vertical-align: middle;
|
56
|
+
max-width: 300px;
|
57
|
+
|
58
|
+
.a-table-cell-truncate {
|
59
|
+
overflow: hidden;
|
60
|
+
text-overflow: ellipsis;
|
61
|
+
}
|
56
62
|
|
57
63
|
&.text--info {
|
58
64
|
color: #888888 !important;
|
@@ -37,6 +37,7 @@ class RouteConfigPlugin {
|
|
37
37
|
|
38
38
|
_routeDefinitions = []
|
39
39
|
_config = {}
|
40
|
+
_scrollContainer = null
|
40
41
|
|
41
42
|
_breadcrumbDefinitions = []
|
42
43
|
_breadcrumbDefinitionMap = {}
|
@@ -117,6 +118,11 @@ class RouteConfigPlugin {
|
|
117
118
|
return this
|
118
119
|
}
|
119
120
|
|
121
|
+
scrollContainer (scrollContainer) {
|
122
|
+
this._scrollContainer = scrollContainer
|
123
|
+
return this
|
124
|
+
}
|
125
|
+
|
120
126
|
routes (callback) {
|
121
127
|
this._promise = this._promise.then(() => {
|
122
128
|
callback = callback({
|
@@ -161,6 +167,17 @@ class RouteConfigPlugin {
|
|
161
167
|
for (const route of this._routes) {
|
162
168
|
this._router.addRoute(route)
|
163
169
|
}
|
170
|
+
|
171
|
+
if (this._scrollContainer) { // scroll to 0 if not window object is used as scoll parent
|
172
|
+
this._router.afterEach((to, from) => {
|
173
|
+
if (to.path !== from.path) {
|
174
|
+
const el = document.querySelector(this._scrollContainer)
|
175
|
+
if (el) {
|
176
|
+
el.scrollTop = 0
|
177
|
+
}
|
178
|
+
}
|
179
|
+
})
|
180
|
+
}
|
164
181
|
})
|
165
182
|
})
|
166
183
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
export function formatTime (date) {
|
2
|
+
if (!date) {
|
3
|
+
return ''
|
4
|
+
}
|
5
|
+
|
6
|
+
const hour = addZero(date.getHours())
|
7
|
+
const minutes = addZero(date.getMinutes())
|
8
|
+
|
9
|
+
return `${hour}:${minutes}`
|
10
|
+
}
|
11
|
+
|
12
|
+
function addZero (i) {
|
13
|
+
if (i < 10) {
|
14
|
+
i = '0' + i
|
15
|
+
}
|
16
|
+
return i
|
17
|
+
}
|
@@ -1,136 +1,41 @@
|
|
1
1
|
<template>
|
2
|
-
<div>
|
3
|
-
<v-
|
4
|
-
v-model="drawer"
|
5
|
-
app
|
6
|
-
left
|
7
|
-
width="280"
|
8
|
-
class="menubar"
|
9
|
-
>
|
10
|
-
<v-container
|
11
|
-
flex-column
|
12
|
-
align-center
|
13
|
-
fill-height
|
14
|
-
>
|
15
|
-
<a-row
|
16
|
-
justify-end
|
17
|
-
width="100%"
|
18
|
-
>
|
19
|
-
<v-app-bar-nav-icon
|
20
|
-
class="sidebarToggleButton mt-1 mr-2 ml-3"
|
21
|
-
title="Menu schließen"
|
22
|
-
@click="toggleDrawer"
|
23
|
-
>
|
24
|
-
<v-icon>{{ closeMenuIcon }}</v-icon>
|
25
|
-
</v-app-bar-nav-icon>
|
26
|
-
</a-row>
|
27
|
-
|
28
|
-
<router-link
|
29
|
-
:to="{name: rootRouteName}"
|
30
|
-
class="logoContainer d-flex flex-column align-center pa-6"
|
31
|
-
>
|
32
|
-
<img
|
33
|
-
v-if="logoUrl"
|
34
|
-
class="logo"
|
35
|
-
:src="logoUrl"
|
36
|
-
>
|
37
|
-
<div class="text-button">
|
38
|
-
{{ title }}
|
39
|
-
</div>
|
40
|
-
</router-link>
|
41
|
-
|
42
|
-
<component
|
43
|
-
:is="SidebarMenu"
|
44
|
-
class="px-0 mt-0 flex-grow-1"
|
45
|
-
/>
|
46
|
-
|
47
|
-
<v-container
|
48
|
-
v-if="hasAuthService"
|
49
|
-
d-flex
|
50
|
-
align-center
|
51
|
-
gap-4
|
52
|
-
pa-6
|
53
|
-
pb-8
|
54
|
-
>
|
55
|
-
<div class="d-flex align-center gap-3">
|
56
|
-
<v-avatar
|
57
|
-
color="primary white--text"
|
58
|
-
size="40"
|
59
|
-
>
|
60
|
-
{{ account.first_name.charAt(0).toUpperCase() }}{{ account.last_name.charAt(0).toUpperCase() }}
|
61
|
-
</v-avatar>
|
62
|
-
|
63
|
-
<div>
|
64
|
-
<div class="accountName">
|
65
|
-
{{ account.first_name }}
|
66
|
-
<template v-if="$auth.roles[0]">
|
67
|
-
({{ $auth.roles[0].title }})
|
68
|
-
</template>
|
69
|
-
</div>
|
70
|
-
|
71
|
-
<div class="body-2 d-flex align-center">
|
72
|
-
<v-icon class="ml-n1 mr-1">
|
73
|
-
$logoutIcon
|
74
|
-
</v-icon>
|
75
|
-
<a @click="logout()">Logout</a>
|
76
|
-
</div>
|
77
|
-
</div>
|
78
|
-
|
79
|
-
<a-context-menu v-if="$has.settings">
|
80
|
-
<a-context-menu-item
|
81
|
-
:to="{name: 'settings', params: {accountId: account.id}}"
|
82
|
-
>
|
83
|
-
<v-icon>$pencilIcon</v-icon>
|
84
|
-
Einstellungen
|
85
|
-
</a-context-menu-item>
|
86
|
-
</a-context-menu>
|
87
|
-
</div>
|
88
|
-
</v-container>
|
89
|
-
</v-container>
|
90
|
-
</v-navigation-drawer>
|
91
|
-
|
92
|
-
<a-loading-indicator
|
2
|
+
<div class="admin">
|
3
|
+
<v-overlay
|
93
4
|
fixed
|
94
|
-
|
95
|
-
|
96
|
-
class="loadingIndicator"
|
97
|
-
:isLoading="!!numLoadingRequests"
|
98
|
-
:color="loaderColor"
|
5
|
+
:value="sidebarsFloating"
|
6
|
+
@click="closeFloatingSidebars"
|
99
7
|
/>
|
100
8
|
|
101
|
-
<
|
102
|
-
<
|
103
|
-
|
104
|
-
|
9
|
+
<div class="main-layout">
|
10
|
+
<navigation-bar :has="$has" />
|
11
|
+
|
12
|
+
<div
|
13
|
+
id="v-main"
|
14
|
+
:class="{marginRight: hasFloatingInformationBar}"
|
105
15
|
>
|
106
|
-
<
|
107
|
-
|
108
|
-
class="
|
109
|
-
|
110
|
-
|
16
|
+
<a-loading-indicator
|
17
|
+
top
|
18
|
+
class="loadingIndicator"
|
19
|
+
:isLoading="!!numLoadingRequests"
|
20
|
+
:color="loaderColor"
|
111
21
|
/>
|
112
22
|
|
113
|
-
<a-breadcrumbs />
|
114
|
-
</a-row>
|
115
|
-
|
116
|
-
<v-container
|
117
|
-
fluid
|
118
|
-
class="pa-8 pt-0"
|
119
|
-
>
|
120
23
|
<sticky-header />
|
121
24
|
|
122
|
-
<
|
123
|
-
|
25
|
+
<div class="pa-8 pt-4">
|
26
|
+
<router-view :class="{isLoading: !!numLoadingRequests}" />
|
27
|
+
</div>
|
28
|
+
|
29
|
+
<sticky-footer-container />
|
30
|
+
</div>
|
124
31
|
|
125
|
-
<
|
126
|
-
</
|
32
|
+
<information-bar />
|
33
|
+
</div>
|
127
34
|
|
128
35
|
<a-dialog id="app" />
|
129
36
|
|
130
37
|
<a-save-indicator />
|
131
38
|
|
132
|
-
<sidebar />
|
133
|
-
|
134
39
|
<flying-context-container />
|
135
40
|
</div>
|
136
41
|
</template>
|
@@ -144,18 +49,22 @@ import AppBarButtons from './app/AppBarButtons'
|
|
144
49
|
import AppBarTitleContainer from './app/AppBarTitleContainer'
|
145
50
|
import FlyingContextContainer from './FlyingContextContainer'
|
146
51
|
import StickyFooterContainer from './StickyFooterContainer'
|
147
|
-
import
|
52
|
+
import NavigationBar from './NavigationBar'
|
53
|
+
import InformationBar from './InformationBar'
|
148
54
|
import StickyHeader from './StickyHeader'
|
149
55
|
import '../styles.scss'
|
150
56
|
import { mdiBackburger } from '@mdi/js'
|
57
|
+
import { SidebarEvent } from '@a-admin/events'
|
58
|
+
import { sidebarService } from './sidebar/SidebarService'
|
151
59
|
|
152
60
|
@Component({
|
153
61
|
components: {
|
154
62
|
AppBarButtons,
|
155
63
|
AppBarTitleContainer,
|
64
|
+
NavigationBar,
|
65
|
+
InformationBar,
|
156
66
|
FlyingContextContainer,
|
157
67
|
StickyFooterContainer,
|
158
|
-
Sidebar,
|
159
68
|
StickyHeader
|
160
69
|
}
|
161
70
|
})
|
@@ -166,39 +75,32 @@ export default class App extends Vue {
|
|
166
75
|
closeMenuIcon = mdiBackburger
|
167
76
|
numLoadingRequests = 0
|
168
77
|
|
78
|
+
sidebarsFloating = false
|
79
|
+
hasFloatingInformationBar = false
|
80
|
+
|
169
81
|
created () {
|
170
82
|
this.$events.on(LoadingEvent.START_LOADING, this.startLoading)
|
171
83
|
this.$events.on(LoadingEvent.STOP_LOADING, this.stopLoading)
|
172
|
-
this.$emit('appLoaded')
|
173
|
-
}
|
174
84
|
|
175
|
-
|
176
|
-
|
177
|
-
|
85
|
+
this.$events.on(SidebarEvent.STATUS, ({payload: {hasFloatingOverlay, mobile, information}}) => {
|
86
|
+
this.sidebarsFloating = hasFloatingOverlay
|
87
|
+
this.hasFloatingInformationBar = mobile && information
|
88
|
+
})
|
178
89
|
|
179
|
-
|
180
|
-
|
181
|
-
}
|
90
|
+
this.sidebarsFloating = sidebarService.hasFloatingOverlay
|
91
|
+
this.hasFloatingInformationBar = sidebarService.mobile && sidebarService.information
|
182
92
|
|
183
|
-
|
184
|
-
if (this.hasAuthService) {
|
185
|
-
return this.$auth.account
|
186
|
-
}
|
187
|
-
return null
|
93
|
+
this.$emit('appLoaded')
|
188
94
|
}
|
189
95
|
|
190
|
-
|
191
|
-
|
96
|
+
closeFloatingSidebars () {
|
97
|
+
sidebarService.closeAllFloating()
|
192
98
|
}
|
193
99
|
|
194
100
|
get loaderColor () {
|
195
101
|
return adminConfig.app.loaderColor
|
196
102
|
}
|
197
103
|
|
198
|
-
get rootRouteName () {
|
199
|
-
return adminConfig.app.rootRouteName || 'root'
|
200
|
-
}
|
201
|
-
|
202
104
|
startLoading () {
|
203
105
|
this.numLoadingRequests++
|
204
106
|
}
|
@@ -206,66 +108,26 @@ export default class App extends Vue {
|
|
206
108
|
stopLoading () {
|
207
109
|
this.numLoadingRequests--
|
208
110
|
}
|
209
|
-
|
210
|
-
toggleDrawer () {
|
211
|
-
this.drawer = !this.drawer
|
212
|
-
}
|
213
|
-
|
214
|
-
get hasAuthService () {
|
215
|
-
return !!this.$auth
|
216
|
-
}
|
217
|
-
|
218
|
-
logout () {
|
219
|
-
this.$auth.logout()
|
220
|
-
}
|
221
111
|
}
|
222
112
|
</script>
|
223
113
|
|
224
114
|
|
225
115
|
<style lang="scss" scoped>
|
226
|
-
.accountName {
|
227
|
-
line-height: 1.2;
|
228
|
-
word-break: break-all;
|
229
|
-
}
|
230
|
-
|
231
|
-
.logoContainer {
|
232
|
-
text-decoration: none;
|
233
|
-
}
|
234
|
-
|
235
|
-
.logo {
|
236
|
-
max-height: 80px;
|
237
|
-
max-width: 90%;
|
238
|
-
}
|
239
|
-
|
240
116
|
.isLoading {
|
241
117
|
opacity: .6;
|
242
118
|
}
|
243
119
|
|
244
|
-
.
|
245
|
-
|
246
|
-
height: 36px !important;
|
247
|
-
margin-top: 1px;
|
120
|
+
.main-layout {
|
121
|
+
display: flex;
|
248
122
|
}
|
249
123
|
|
250
|
-
.
|
251
|
-
|
252
|
-
|
253
|
-
left: 0;
|
124
|
+
.loadingIndicator {
|
125
|
+
z-index: 3;
|
126
|
+
position: sticky;
|
254
127
|
top: 0;
|
255
|
-
height:40px;
|
256
|
-
padding: .2rem 1.1rem;
|
257
|
-
background-color: white;
|
258
|
-
}
|
259
|
-
|
260
|
-
.a-breadcrumbs {
|
261
|
-
margin-top: 7px;
|
262
|
-
}
|
263
|
-
|
264
|
-
.menubar {
|
265
|
-
// background: #666666 !important;
|
266
128
|
}
|
267
129
|
|
268
|
-
#
|
269
|
-
|
130
|
+
#v-main.marginRight {
|
131
|
+
margin-right: 60px;
|
270
132
|
}
|
271
133
|
</style>
|
@@ -0,0 +1,64 @@
|
|
1
|
+
<template>
|
2
|
+
<div :class="['collapsible-section', {collapsed}]">
|
3
|
+
<h-separator
|
4
|
+
v-bind="{...$attrs, collapsible: true}"
|
5
|
+
:collapsed.sync="collapsed"
|
6
|
+
/>
|
7
|
+
|
8
|
+
<a-info
|
9
|
+
v-if="showHint && hint"
|
10
|
+
type="info"
|
11
|
+
x-small
|
12
|
+
>
|
13
|
+
Inhalt eingeklappt. <a @click="collapsed = !collapsed">ausklappen</a>
|
14
|
+
</a-info>
|
15
|
+
|
16
|
+
<div style="height: 1px;" />
|
17
|
+
|
18
|
+
<collapse-transition>
|
19
|
+
<div
|
20
|
+
v-show="!collapsed"
|
21
|
+
class="content"
|
22
|
+
>
|
23
|
+
<slot />
|
24
|
+
</div>
|
25
|
+
</collapse-transition>
|
26
|
+
</div>
|
27
|
+
</template>
|
28
|
+
|
29
|
+
|
30
|
+
<script>
|
31
|
+
import { Component, Vue, Watch } from '@a-vue'
|
32
|
+
|
33
|
+
@Component({
|
34
|
+
props: [{showHint: true}]
|
35
|
+
})
|
36
|
+
export default class CollapsibleSection extends Vue {
|
37
|
+
collapsed = false
|
38
|
+
hint = false
|
39
|
+
|
40
|
+
@Watch('collapsed')
|
41
|
+
collapsedChanged () {
|
42
|
+
if (this.collapsed) {
|
43
|
+
setTimeout(() => {
|
44
|
+
this.hint = this.collapsed
|
45
|
+
}, 150)
|
46
|
+
} else {
|
47
|
+
this.hint = false
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
</script>
|
52
|
+
|
53
|
+
|
54
|
+
<style lang="scss" scoped>
|
55
|
+
.collapsible-section {
|
56
|
+
position: relative;
|
57
|
+
}
|
58
|
+
|
59
|
+
.a-info {
|
60
|
+
position: absolute;
|
61
|
+
margin-top: -1rem;
|
62
|
+
color: #666666;
|
63
|
+
}
|
64
|
+
</style>
|
@@ -0,0 +1,90 @@
|
|
1
|
+
<template>
|
2
|
+
<div :class="['h-separator', {first}]">
|
3
|
+
<hr>
|
4
|
+
|
5
|
+
<div
|
6
|
+
:class="['label', {collapsible}]"
|
7
|
+
@click="collapseClick"
|
8
|
+
>
|
9
|
+
{{ label }}
|
10
|
+
|
11
|
+
<template v-if="collapsible">
|
12
|
+
<v-icon class="contextButton mt-n1 ml-n2">
|
13
|
+
{{ collapsed_ ? '$caretRightIcon' : '$caretDownIcon' }}
|
14
|
+
</v-icon>
|
15
|
+
</template>
|
16
|
+
</div>
|
17
|
+
</div>
|
18
|
+
</template>
|
19
|
+
|
20
|
+
|
21
|
+
<script>
|
22
|
+
import { Component, Vue, Watch } from '@a-vue'
|
23
|
+
|
24
|
+
@Component({
|
25
|
+
props: ['label', {first: false, collapsible: false, collapsed: false}]
|
26
|
+
})
|
27
|
+
export default class HSeparator extends Vue {
|
28
|
+
collapsed_ = false
|
29
|
+
|
30
|
+
created () {
|
31
|
+
this.collapsed_ = this.collapsed
|
32
|
+
}
|
33
|
+
|
34
|
+
@Watch('collapsed')
|
35
|
+
collapsedChangedFromOutside () {
|
36
|
+
this.collapsed_ = this.collapsed
|
37
|
+
}
|
38
|
+
|
39
|
+
collapseClick () {
|
40
|
+
this.collapsed_ = !this.collapsed_
|
41
|
+
this.$emit('update:collapsed', this.collapsed_)
|
42
|
+
}
|
43
|
+
}
|
44
|
+
</script>
|
45
|
+
|
46
|
+
|
47
|
+
<style lang="scss" scoped>
|
48
|
+
.h-separator {
|
49
|
+
position: relative;
|
50
|
+
display: flex;
|
51
|
+
flex-direction: column;
|
52
|
+
justify-content: center;
|
53
|
+
margin: 5rem 0 3rem;
|
54
|
+
|
55
|
+
&.first{
|
56
|
+
margin-top: 0;
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
hr {
|
61
|
+
border: none;
|
62
|
+
border-top: 2px solid #EEEEEE;
|
63
|
+
}
|
64
|
+
|
65
|
+
.label {
|
66
|
+
position: absolute;
|
67
|
+
background: white;
|
68
|
+
padding: 0 1rem;
|
69
|
+
text-transform: uppercase;
|
70
|
+
letter-spacing: 5px;
|
71
|
+
color: #CCCCCC;
|
72
|
+
font-size: .8rem;
|
73
|
+
white-space: nowrap;
|
74
|
+
|
75
|
+
left: 45%;
|
76
|
+
transform: translateX(-50%);
|
77
|
+
|
78
|
+
&.collapsible {
|
79
|
+
cursor: pointer;
|
80
|
+
|
81
|
+
&:hover {
|
82
|
+
color: #333333;
|
83
|
+
|
84
|
+
.v-icon {
|
85
|
+
color: #333333 !important;
|
86
|
+
}
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
</style>
|