@afeefa/vue-app 0.0.65 → 0.0.66

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.
@@ -1 +1 @@
1
- 0.0.65
1
+ 0.0.66
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@afeefa/vue-app",
3
- "version": "0.0.65",
3
+ "version": "0.0.66",
4
4
  "description": "",
5
5
  "author": "Afeefa Kollektiv <kollektiv@afeefa.de>",
6
6
  "license": "MIT",
@@ -1,19 +1,38 @@
1
1
  <template>
2
- <div class="d-flex flex-wrap align-center">
3
- <div
4
- v-for="(breadcrumb, index) in breadcrumbs"
5
- :key="index"
6
- class="item mr-2 d-flex align-center"
7
- >
8
- <v-icon>$chevronRightIcon</v-icon>
9
-
10
- <router-link
11
- :to="breadcrumb.to"
12
- :exact="true"
2
+ <div class="a-breadcrumbs d-flex align-start gap-2 mr-4">
3
+ <div :class="['breadcrumbs d-flex align-center', {'flex-wrap': wrapBreadcrumbs_}]">
4
+ <div
5
+ v-for="(breadcrumb, index) in breadcrumbs"
6
+ :key="index"
7
+ class="item mr-2 d-flex align-center"
13
8
  >
14
- {{ getItemTitle(breadcrumb.title) }}
15
- </router-link>
9
+ <v-icon v-if="index > 0">
10
+ $chevronRightIcon
11
+ </v-icon>
12
+
13
+ <router-link
14
+ :to="breadcrumb.to"
15
+ :exact="true"
16
+ >
17
+ {{ breadcrumb.title }}
18
+ </router-link>
19
+ </div>
16
20
  </div>
21
+
22
+ <v-avatar
23
+ v-if="expandVisible"
24
+ class="expand"
25
+ color="#EEE"
26
+ size="1.3rem"
27
+ @click="wrapBreadcrumbs"
28
+ >
29
+ <a-icon>$caret{{ wrapBreadcrumbs_ ? 'Up' : 'Down' }}Icon</a-icon>
30
+ </v-avatar>
31
+
32
+ <div
33
+ v-else
34
+ class="expandDummy"
35
+ />
17
36
  </div>
18
37
  </template>
19
38
 
@@ -28,6 +47,8 @@ export default class ABreadcrumbs extends Vue {
28
47
  breadcrumbs = []
29
48
  titleCache = {}
30
49
  lastRoute = null
50
+ expandVisible = false
51
+ wrapBreadcrumbs_ = false
31
52
 
32
53
  created () {
33
54
  this.$events.on(SaveEvent.STOP_SAVING, this.afterSave)
@@ -101,21 +122,46 @@ export default class ABreadcrumbs extends Vue {
101
122
  }
102
123
 
103
124
  this.breadcrumbs = breadcrumbs
125
+ this.wrapBreadcrumbs_ = false
126
+
127
+ this.scrollBreadcrumbs()
128
+ }
129
+
130
+ scrollBreadcrumbs () {
131
+ this.$nextTick(() => {
132
+ const objDiv = this.$el.querySelector('.breadcrumbs')
133
+ if (objDiv.scrollWidth > objDiv.offsetWidth) {
134
+ objDiv.scrollLeft = objDiv.scrollWidth
135
+ this.expandVisible = true
136
+ } else {
137
+ objDiv.scrollLeft = 0
138
+ this.expandVisible = false
139
+ }
140
+ })
104
141
  }
105
142
 
106
- getItemTitle (title) {
107
- // title = title.concat(title).concat(title)
108
- if (title.length > 20) {
109
- // title = title.slice(0, 10).trim() + '...' + title.slice(-10).trim()
143
+ wrapBreadcrumbs () {
144
+ this.wrapBreadcrumbs_ = !this.wrapBreadcrumbs_
145
+ if (this.wrapBreadcrumbs_) {
146
+ const objDiv = this.$el.querySelector('.breadcrumbs')
147
+ objDiv.scrollLeft = 0
148
+ } else {
149
+ this.scrollBreadcrumbs()
110
150
  }
111
- return title
112
- // return title.toUpperCase()
113
151
  }
114
152
  }
115
153
  </script>
116
154
 
117
155
 
118
156
  <style lang="scss" scoped>
157
+ .a-breadcrumbs {
158
+ overflow: hidden;
159
+ }
160
+
161
+ .breadcrumbs {
162
+ overflow: hidden;
163
+ }
164
+
119
165
  .item {
120
166
  white-space: nowrap;
121
167
 
@@ -131,4 +177,14 @@ export default class ABreadcrumbs extends Vue {
131
177
  }
132
178
  }
133
179
  }
180
+
181
+ .expand {
182
+ cursor: pointer;
183
+ margin-top: 1px;
184
+ }
185
+
186
+ .expandDummy {
187
+ width: 1.5rem;
188
+ height: 1.5rem;
189
+ }
134
190
  </style>
@@ -13,7 +13,7 @@
13
13
  :label="label"
14
14
  :style="cwm_widthStyle"
15
15
  readonly
16
- v-bind="attrs"
16
+ v-bind="{...$attrs, ...attrs}"
17
17
  :rules="validationRules"
18
18
  v-on="on"
19
19
  @click.native="on.click"
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <v-icon
3
- :class="{isButton}"
3
+ :class="{button}"
4
4
  v-bind="$attrs"
5
5
  v-on="$listeners"
6
6
  >
@@ -13,17 +13,14 @@
13
13
  import { Component, Vue } from '@a-vue'
14
14
 
15
15
  @Component({
16
- props: ['button']
16
+ props: [{button: false}]
17
17
  })
18
18
  export default class AIcon extends Vue {
19
- get isButton () {
20
- return this.button !== undefined
21
- }
22
19
  }
23
20
  </script>
24
21
 
25
22
  <style lang="scss" scoped>
26
- .v-icon:not(.isButton)::after {
23
+ .v-icon:not(.button)::after {
27
24
  background: none;
28
25
  }
29
26
  </style>
@@ -1,12 +1,11 @@
1
1
  <template>
2
2
  <v-btn
3
- small
4
3
  v-bind="$attrs"
5
4
  v-on="$listeners"
6
5
  >
7
6
  <v-icon
8
7
  left
9
- class="mr-0"
8
+ class="mr-1"
10
9
  >
11
10
  {{ icon }}
12
11
  </v-icon>
@@ -58,13 +58,6 @@ export default class ARow extends Vue {
58
58
  <style scoped lang="scss">
59
59
  .a-row {
60
60
  display: flex;
61
- overflow: hidden;
62
- @media (max-width: 900px), (orientation : portrait) {
63
- flex-wrap: wrap;
64
- & > * {
65
- flex: 0 0 auto;
66
- }
67
- }
68
61
 
69
62
  &.full {
70
63
  width: 100%;
@@ -11,6 +11,7 @@ import { FilterSourceType } from './FilterSourceType'
11
11
  'listAction',
12
12
  'filterHistoryKey',
13
13
  'loadOnlyIfKeyword',
14
+ 'checkBeforeLoad',
14
15
  {
15
16
  filterSource: FilterSourceType.QUERY_STRING,
16
17
  events: true,
@@ -120,6 +121,16 @@ export class ListViewMixin extends Vue {
120
121
  }
121
122
 
122
123
  async load () {
124
+ if (this.checkBeforeLoad) {
125
+ const canLoad = await this.checkBeforeLoad()
126
+ if (!canLoad) {
127
+ if (this.meta_.used_filters) {
128
+ this.listViewModel.initFromUsedFilters(this.meta_.used_filters, this.meta_.count_search)
129
+ }
130
+ return
131
+ }
132
+ }
133
+
123
134
  if (this._loadOnlyIfKeyword && !this.filters.q.value) {
124
135
  this.models_ = []
125
136
  this.meta_ = {}
@@ -25,10 +25,14 @@ export class ClickOutsideMixin extends Vue {
25
25
  // popup clicked
26
26
  const thisIndex = getZIndex(this.$el)
27
27
  const targetIndex = getZIndex(e.target)
28
- if (targetIndex > thisIndex) {
28
+ if (targetIndex > 10 && targetIndex > thisIndex) { // sidebar === 6
29
29
  return
30
30
  }
31
31
 
32
+ this.com_onClickOutside()
32
33
  this.$emit('click:outside')
33
34
  }
35
+
36
+ com_onClickOutside () {
37
+ }
34
38
  }
@@ -73,78 +73,46 @@
73
73
  </v-container>
74
74
  </v-navigation-drawer>
75
75
 
76
- <v-navigation-drawer
77
- v-if="false"
78
- app
79
- clipped
80
- right
81
- >
82
- <v-list>
83
- <v-list-item
84
- v-for="n in 5"
85
- :key="n"
86
- link
87
- >
88
- <v-list-item-content>
89
- <v-list-item-title>Item {{ n }}</v-list-item-title>
90
- </v-list-item-content>
91
- </v-list-item>
92
- </v-list>
93
- </v-navigation-drawer>
94
-
95
- <v-app-bar
96
- v-if="false"
97
- app
98
- flat
99
- dense
100
- color="#FAFAFA"
101
- >
102
- <div class="d-flex align-start mt-n2">
103
- <v-app-bar-nav-icon
104
- class="sidebarToggleButton mr-2 ml-n1"
105
- @click="toggleDrawer"
106
- />
107
- <a-breadcrumbs class="mt-2" />
108
- </div>
109
-
110
- <a-loading-indicator
111
- fixed
112
- top
113
- left
114
- class="loadingIndicator"
115
- :isLoading="isLoading"
116
- :color="loaderColor"
117
- />
118
- </v-app-bar>
76
+ <a-loading-indicator
77
+ fixed
78
+ top
79
+ left
80
+ class="loadingIndicator"
81
+ :isLoading="isLoading"
82
+ :color="loaderColor"
83
+ />
119
84
 
120
85
  <v-main id="v-main">
121
- <a-row class="topbar">
86
+ <a-row
87
+ start
88
+ class="topbar"
89
+ >
122
90
  <v-app-bar-nav-icon
123
- class="sidebarToggleButton mr-2 ml-n1"
91
+ class="sidebarToggleButton mr-2 ml-4"
124
92
  @click="toggleDrawer"
125
93
  />
94
+
126
95
  <a-breadcrumbs />
127
96
  </a-row>
128
97
 
129
98
  <v-container
130
99
  fluid
131
- class="pa-4"
100
+ class="pa-8 pt-4"
132
101
  >
133
- <div class="sticky-app-bar d-flex align-center">
134
- <app-bar-title-container class="flex-grow-1" />
135
- <app-bar-buttons class="mr-2" />
136
- </div>
102
+ <sticky-header />
137
103
 
138
104
  <router-view :class="{isLoading}" />
139
105
  </v-container>
140
106
 
141
- <sticky-footer-container v-if="true" />
107
+ <sticky-footer-container />
142
108
  </v-main>
143
109
 
144
110
  <a-dialog id="app" />
145
111
 
146
112
  <a-save-indicator />
147
113
 
114
+ <sidebar />
115
+
148
116
  <flying-context-container />
149
117
  </div>
150
118
  </template>
@@ -158,6 +126,8 @@ import AppBarButtons from './app/AppBarButtons'
158
126
  import AppBarTitleContainer from './app/AppBarTitleContainer'
159
127
  import FlyingContextContainer from './FlyingContextContainer'
160
128
  import StickyFooterContainer from './StickyFooterContainer'
129
+ import Sidebar from './Sidebar'
130
+ import StickyHeader from './StickyHeader'
161
131
  import '../styles.scss'
162
132
 
163
133
  @Component({
@@ -165,12 +135,13 @@ import '../styles.scss'
165
135
  AppBarButtons,
166
136
  AppBarTitleContainer,
167
137
  FlyingContextContainer,
168
- StickyFooterContainer
138
+ StickyFooterContainer,
139
+ Sidebar,
140
+ StickyHeader
169
141
  }
170
142
  })
171
143
  export default class App extends Vue {
172
144
  drawer = true
173
- mainDrawer = false
174
145
  isLoading = false
175
146
  account = null
176
147
 
@@ -185,17 +156,6 @@ export default class App extends Vue {
185
156
  this.$emit('appLoaded')
186
157
  }
187
158
 
188
- mounted () {
189
- const el = document.querySelector('.sticky-app-bar')
190
- const observer = new IntersectionObserver(
191
- ([e]) => {
192
- e.target.classList.toggle('is-pinned', e.intersectionRatio < 1)
193
- },
194
- { threshold: [1] }
195
- )
196
- observer.observe(el)
197
- }
198
-
199
159
  get SidebarMenu () {
200
160
  return appConfig.components.SidebarMenu
201
161
  }
@@ -228,16 +188,6 @@ export default class App extends Vue {
228
188
  this.drawer = !this.drawer
229
189
  }
230
190
 
231
- @Watch('drawer')
232
- async drawerChanged () {
233
- if (this.drawer) {
234
- this.mainDrawer = false
235
- } else {
236
- await sleep(0.1)
237
- this.mainDrawer = true
238
- }
239
- }
240
-
241
191
  get hasAuthService () {
242
192
  return !!appConfig.authService
243
193
  }
@@ -281,16 +231,16 @@ export default class App extends Vue {
281
231
  top: 0;
282
232
  padding: .2rem 1rem;
283
233
  }
284
- .sticky-app-bar {
285
- position: sticky;
286
- top: -1px;
287
- margin: -1rem -1rem 0;
288
- padding: 1rem;
289
-
290
- &.is-pinned {
291
- background: white;
292
- z-index: 2;
293
- box-shadow: 0 4px 7px -4px #00000033;
294
- }
234
+
235
+ .a-breadcrumbs {
236
+ margin-top: 7px;
237
+ }
238
+
239
+ .menubar {
240
+ // background: #666666 !important;
241
+ }
242
+
243
+ #sidebar {
244
+ // background: #F4F4F4 !important;
295
245
  }
296
246
  </style>
@@ -0,0 +1,66 @@
1
+ <template>
2
+ <v-navigation-drawer
3
+ id="sidebar"
4
+ v-model="visible"
5
+ app
6
+ right
7
+ disable-resize-watcher
8
+ width="220"
9
+ >
10
+ <div id="sidebar__children">
11
+ <div class="top" />
12
+ <div class="bottom" />
13
+ </div>
14
+ </v-navigation-drawer>
15
+ </template>
16
+
17
+ <script>
18
+ import { Component, Vue } from '@a-vue'
19
+
20
+ @Component({
21
+ props: []
22
+ })
23
+ export default class Sidebar extends Vue {
24
+ visible = false
25
+
26
+ mounted () {
27
+ this.mutationWatcher = new MutationObserver(this.domChanged)
28
+ this.mutationWatcher.observe(this.$el.querySelector('#sidebar__children > .top'), { childList: true })
29
+ this.mutationWatcher.observe(this.$el.querySelector('#sidebar__children > .bottom'), { childList: true })
30
+
31
+ this.domChanged()
32
+ }
33
+
34
+ domChanged () {
35
+ this.visible = this.hasSidebarItems()
36
+ }
37
+
38
+ getChildrenContainer () {
39
+ return this.$el.querySelector('#sidebar__children')
40
+ }
41
+
42
+ hasSidebarItems () {
43
+ return !!(this.$el.querySelector('#sidebar__children .top').children.length +
44
+ this.$el.querySelector('#sidebar__children .bottom').children.length)
45
+ }
46
+ }
47
+ </script>
48
+
49
+
50
+ <style lang="scss" scoped>
51
+ #sidebar {
52
+ &__children {
53
+ width: 100%;
54
+ }
55
+ }
56
+
57
+ #sidebar__children {
58
+ height: 100%;
59
+ padding: 2rem;
60
+ // padding-left: 4rem;
61
+
62
+ display: flex;
63
+ flex-direction: column;
64
+ justify-content: space-between;
65
+ }
66
+ </style>
@@ -0,0 +1,59 @@
1
+ <template>
2
+ <div class="sidebarItem">
3
+ <div :class="contextId">
4
+ <slot />
5
+ </div>
6
+ </div>
7
+ </template>
8
+
9
+ <script>
10
+ import { Component, Vue } from '@a-vue'
11
+ import { randomCssClass } from '@a-vue/utils/random'
12
+
13
+ @Component({
14
+ props: [
15
+ {
16
+ top: true,
17
+ bottom: false
18
+ }
19
+ ]
20
+ })
21
+ export default class SidebarItem extends Vue {
22
+ contextId = randomCssClass(10)
23
+
24
+ mounted () {
25
+ const container = this.getSidebarContainer()
26
+ console.log(container)
27
+ container.appendChild(this.getContent())
28
+ }
29
+
30
+ destroyed () {
31
+ const container = this.getSidebarContainer()
32
+ const el = this.getContent()
33
+ if (container.contains(el)) {
34
+ container.removeChild(el)
35
+ }
36
+ }
37
+
38
+ getContent () {
39
+ return document.querySelector('.' + this.contextId)
40
+ }
41
+
42
+ getSidebarContainer () {
43
+ console.log('toporbottom', this.$props)
44
+ return document.querySelector('#sidebar__children > .' + this.position)
45
+ }
46
+
47
+ get position () {
48
+ if (this.bottom) {
49
+ return 'bottom'
50
+ } else {
51
+ return 'top'
52
+ }
53
+ }
54
+ }
55
+ </script>
56
+
57
+
58
+ <style lang="scss" scoped>
59
+ </style>
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <div
3
+ id="stickyHeader"
4
+ :class="['d-flex align-center gap-8', {visible}]"
5
+ >
6
+ <app-bar-title-container class="appBarTitle flex-grow-1" />
7
+ <app-bar-buttons class="appBarButtons mr-2" />
8
+ </div>
9
+ </template>
10
+
11
+ <script>
12
+ import { Component, Vue } from '@a-vue'
13
+ import AppBarButtons from './app/AppBarButtons'
14
+ import AppBarTitleContainer from './app/AppBarTitleContainer'
15
+
16
+ @Component({
17
+ components: {
18
+ AppBarButtons,
19
+ AppBarTitleContainer
20
+ }
21
+ })
22
+ export default class StickyHeader extends Vue {
23
+ visible = false
24
+
25
+ mounted () {
26
+ // watch mutation
27
+ this.mutationWatcher = new MutationObserver(this.domChanged)
28
+ this.mutationWatcher.observe(this.$el.querySelector('.appBarTitle'), { childList: true })
29
+ this.mutationWatcher.observe(this.$el.querySelector('.appBarButtons'), { childList: true })
30
+
31
+ // watch intersection
32
+ const el = document.querySelector('#stickyHeader')
33
+ const observer = new IntersectionObserver(
34
+ ([e]) => {
35
+ e.target.classList.toggle('is-pinned', e.intersectionRatio < 1)
36
+ },
37
+ { threshold: [1] }
38
+ )
39
+ observer.observe(el)
40
+
41
+ this.domChanged()
42
+ }
43
+
44
+ domChanged () {
45
+ this.visible = this.hasItems()
46
+ }
47
+
48
+ hasItems () {
49
+ return !!(this.$el.querySelector('.appBarTitle').children.length +
50
+ this.$el.querySelector('.appBarButtons').children.length)
51
+ }
52
+ }
53
+ </script>
54
+
55
+
56
+ <style lang="scss" scoped>
57
+ #stickyHeader {
58
+ position: sticky;
59
+ top: -1px;
60
+ margin: -1rem -2rem 2rem;
61
+ padding: 1rem 2rem;
62
+
63
+ &:not(.visible) {
64
+ display: none !important;
65
+ }
66
+
67
+ &.is-pinned {
68
+ background: white;
69
+ z-index: 2;
70
+ box-shadow: 0 4px 7px -4px #00000033;
71
+ }
72
+ }
73
+ </style>
@@ -12,10 +12,3 @@ import { Component, Vue } from '@a-vue'
12
12
  export default class AppBarButtons extends Vue {
13
13
  }
14
14
  </script>
15
-
16
-
17
- <style lang="scss" scoped>
18
- #appBarButtons:empty {
19
- display: none !important;
20
- }
21
- </style>
@@ -1,13 +1,36 @@
1
1
  <template>
2
- <div class="d-flex align-center">
3
- <v-icon
4
- class="mr-2"
5
- :color="icon.color"
6
- size="1.8rem"
7
- v-text="icon.icon"
8
- />
9
-
10
- <h2>{{ title }}</h2>
2
+ <div class="d-flex align-center gap-4">
3
+ <v-btn
4
+ v-if="back"
5
+ fab
6
+ x-small
7
+ color="#F4F4F4"
8
+ title="Zurück"
9
+ class="mr-n2"
10
+ @click="$router.push(back)"
11
+ >
12
+ <v-icon>
13
+ $arrowLeftIcon
14
+ </v-icon>
15
+ </v-btn>
16
+
17
+ <v-avatar
18
+ color="#F4F4F4"
19
+ size="3rem"
20
+ >
21
+ <v-icon
22
+ :color="icon.color"
23
+ size="2.2rem"
24
+ v-text="icon.icon"
25
+ />
26
+ </v-avatar>
27
+
28
+ <div class="titleContainer">
29
+ <h3 v-if="subtitle">
30
+ {{ subtitle }}
31
+ </h3>
32
+ <h2>{{ title }}</h2>
33
+ </div>
11
34
  </div>
12
35
  </template>
13
36
 
@@ -15,7 +38,7 @@
15
38
  import { Component, Vue } from '@a-vue'
16
39
 
17
40
  @Component({
18
- props: ['icon', 'title']
41
+ props: ['back', 'icon', 'title', 'subtitle']
19
42
  })
20
43
  export default class appBarTitle extends Vue {
21
44
  mounted () {
@@ -41,8 +64,29 @@ export default class appBarTitle extends Vue {
41
64
 
42
65
 
43
66
  <style lang="scss" scoped>
67
+ .titleContainer {
68
+ overflow: hidden;
69
+ margin-top: -.2rem;
70
+ }
71
+
72
+ h3 {
73
+ font-size: .9rem;
74
+ font-weight: normal;
75
+ margin-bottom: .1rem;
76
+ line-height: 1rem;
77
+ color: #999999;
78
+
79
+ white-space: nowrap;
80
+ overflow: hidden;
81
+ text-overflow: ellipsis;
82
+ }
83
+
44
84
  h2 {
45
- // white-space: nowrap;
85
+ font-size: 1.5rem;
46
86
  line-height: 1.5rem;
87
+
88
+ white-space: nowrap;
89
+ overflow: hidden;
90
+ text-overflow: ellipsis;
47
91
  }
48
92
  </style>
@@ -11,9 +11,8 @@ export default class AppBarTitleContainer extends Vue {
11
11
  }
12
12
  </script>
13
13
 
14
-
15
14
  <style lang="scss" scoped>
16
- #appBarTitleContainer:empty {
17
- display: none;
15
+ #appBarTitleContainer {
16
+ min-width: 0; // https://stackoverflow.com/questions/38657688/text-overflow-ellipsis-not-working-in-a-nested-flex-container
18
17
  }
19
18
  </style>
@@ -68,6 +68,7 @@
68
68
  >
69
69
  <template #activator>
70
70
  <a-icon-button
71
+ small
71
72
  icon="$plusIcon"
72
73
  :text="selectableConfig.addButtonTitle || 'Hinzufügen'"
73
74
  class="mt-4"
@@ -1,17 +1,23 @@
1
1
  <template>
2
2
  <div class="detailProperty">
3
3
  <div class="header">
4
- <v-icon
4
+ <v-avatar
5
5
  v-if="_icon"
6
- :color="_icon.color"
7
- size="2rem"
6
+ color="#EEEEEE"
7
+ size="2.5rem"
8
8
  >
9
- {{ _icon.icon }}
10
- </v-icon>
11
- <label :class="['label', {'label--withIcon': _icon != null}]">{{ label }}</label>
9
+ <v-icon
10
+ :color="_icon.color"
11
+ size="1.5rem"
12
+ >
13
+ {{ _icon.icon }}
14
+ </v-icon>
15
+ </v-avatar>
16
+
17
+ <label :class="['label', {'label--withIcon': !!_icon}]">{{ label }}</label>
12
18
  </div>
13
19
 
14
- <div :class="['content', {'content--withIcon': _icon != null}]">
20
+ <div :class="['content', {'content--withIcon': !!_icon}]">
15
21
  <a-row
16
22
  vertical
17
23
  gap="6"
@@ -52,29 +58,27 @@ export default class DetailProperty extends Vue {
52
58
  flex-wrap: nowrap;
53
59
  align-items: center;
54
60
  height: 40px;
55
- .v-icon {
61
+
62
+ .v-avatar {
56
63
  flex: 0 0 40px;
57
64
  margin-right: 15px;
58
65
  }
66
+
59
67
  .label {
60
68
  display: block;
61
69
  text-transform: uppercase;
62
70
  letter-spacing: 2px;
63
- @media (max-width: 900px), (orientation : portrait) {
64
- padding-left: 55px;
65
- &--withIcon {
66
- padding-left: 0;
67
- }
71
+ padding-left: 55px;
72
+ &--withIcon {
73
+ padding-left: 0;
68
74
  }
69
75
  }
70
76
  }
71
77
  .content {
78
+ padding-left: 55px;
72
79
  &--withIcon {
73
80
  padding-left: 55px;
74
81
  }
75
- @media (max-width: 900px), (orientation : portrait) {
76
- padding-left: 55px;
77
- }
78
82
  }
79
83
  }
80
84
  </style>
@@ -1,20 +1,27 @@
1
1
  <template>
2
2
  <a-row
3
- gap="2"
3
+ gap="1"
4
4
  v-bind="$attrs"
5
5
  >
6
6
  <v-btn
7
- :small="small"
7
+ fab
8
+ small
8
9
  :disabled="($has.reset && !changed) || !valid"
9
10
  color="green white--text"
11
+ title="Speichern"
10
12
  @click="$emit('save')"
11
13
  >
12
- Speichern
14
+ <v-icon>
15
+ $checkIcon
16
+ </v-icon>
13
17
  </v-btn>
14
18
 
15
19
  <v-icon
16
20
  v-if="$has.reset && changed"
17
21
  :small="small"
22
+ :class="{disabled: !changed}"
23
+ :disabled="!changed"
24
+ color="#999999"
18
25
  text
19
26
  title="Formular zurücksetzen"
20
27
  @click="$emit('reset')"
@@ -32,7 +39,7 @@ import { mdiRotateLeft} from '@mdi/js'
32
39
  props: [
33
40
  'changed',
34
41
  'valid',
35
- 'small'
42
+ {small: false}
36
43
  ]
37
44
  })
38
45
  export default class EditFormButtons extends Vue {
@@ -41,3 +48,10 @@ export default class EditFormButtons extends Vue {
41
48
  undoIcon = mdiRotateLeft
42
49
  }
43
50
  </script>
51
+
52
+
53
+ <style lang="scss" scoped>
54
+ .v-icon--disabled {
55
+ opacity: .3;
56
+ }
57
+ </style>
@@ -1,13 +1,22 @@
1
1
  <template>
2
2
  <div>
3
- <a-icon-button
4
- small
5
- color="red white--text"
6
- :class="'removeButton-' + dialogId"
7
- icon="$trashCanIcon"
8
- text="Löschen"
9
- @click="remove"
10
- />
3
+ <v-hover v-slot="{ hover }">
4
+ <v-btn
5
+ :class="'removeButton-' + dialogId"
6
+ fab
7
+ small
8
+ :color="(hover ? 'red' : 'grey lighten-3')"
9
+ title="Löschen"
10
+ @click="remove"
11
+ >
12
+ <v-icon
13
+ :color="hover ? 'white' : '#999999'"
14
+ size="1.4rem"
15
+ >
16
+ $trashCanIcon
17
+ </v-icon>
18
+ </v-btn>
19
+ </v-hover>
11
20
 
12
21
  <a-dialog
13
22
  :id="dialogId"
@@ -19,6 +19,7 @@ import ListView from './list/ListView'
19
19
  import ModelCount from './model/ModelCount'
20
20
  import ModelIcon from './model/ModelIcon'
21
21
  import EditPage from './pages/EditPage'
22
+ import SidebarItem from './SidebarItem.vue'
22
23
  import Start from './Start.vue'
23
24
  import StickyFooter from './StickyFooter.vue'
24
25
 
@@ -48,3 +49,4 @@ Vue.component('AppBarTitle', AppBarTitle)
48
49
  Vue.component('Start', Start)
49
50
  Vue.component('FlyingContext', FlyingContext)
50
51
  Vue.component('StickyFooter', StickyFooter)
52
+ Vue.component('SidebarItem', SidebarItem)
@@ -12,7 +12,7 @@
12
12
  :valid="valid"
13
13
  />
14
14
 
15
- <sticky-footer>
15
+ <app-bar-button>
16
16
  <edit-form-buttons
17
17
  :changed="changed"
18
18
  :valid="valid"
@@ -20,7 +20,7 @@
20
20
  @save="$emit('save', modelToEdit, ignoreChangesOnRouteChange)"
21
21
  @reset="$refs.form.reset()"
22
22
  />
23
- </sticky-footer>
23
+ </app-bar-button>
24
24
  </template>
25
25
  </edit-form>
26
26
  </template>
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  mdiAlarmLightOutline,
3
+ mdiArrowLeft,
3
4
  mdiCalendar,
4
5
  mdiCheck,
5
6
  mdiCheckBold,
@@ -12,9 +13,15 @@ import {
12
13
  mdiLock,
13
14
  mdiLogoutVariant,
14
15
  mdiMagnify,
16
+ mdiMenuDown,
17
+ mdiMenuUp,
15
18
  mdiPencil,
16
19
  mdiPlus,
17
- mdiThumbUpOutline
20
+ mdiThumbUpOutline,
21
+ mdiAccountGroup,
22
+ mdiShopping,
23
+ mdiMessage,
24
+ mdiPencilBoxMultiple
18
25
  } from '@mdi/js'
19
26
  import Vue from 'vue'
20
27
  import Vuetify from 'vuetify/lib'
@@ -40,7 +47,14 @@ export default new Vuetify({
40
47
  searchIcon: mdiMagnify,
41
48
  lockIcon: mdiLock,
42
49
  checkIcon: mdiCheck,
43
- checkBoldIcon: mdiCheckBold
50
+ checkBoldIcon: mdiCheckBold,
51
+ arrowLeftIcon: mdiArrowLeft,
52
+ caretDownIcon: mdiMenuDown,
53
+ caretUpIcon: mdiMenuUp,
54
+ householdMembers: mdiAccountGroup,
55
+ shop: mdiShopping,
56
+ annotation: mdiMessage,
57
+ duplicates: mdiPencilBoxMultiple
44
58
  }
45
59
  },
46
60
  breakpoint: {
@@ -32,6 +32,26 @@
32
32
  background-color: #E9E9E9;
33
33
  }
34
34
 
35
+ .theme--light.v-btn.v-btn--disabled,
36
+ .theme--light.v-btn.v-btn--disabled .v-icon,
37
+ .theme--light.v-btn.v-btn--disabled .v-btn__loading {
38
+ color: white !important;
39
+ }
40
+
41
+ .theme--light.v-btn.v-btn--disabled.v-btn--has-bg {
42
+ background-color: #EEEEEE !important;
43
+ }
44
+
45
+ .v-btn {
46
+ box-shadow: none !important;
47
+ }
48
+
49
+ // @for $i from 1 through 10 {
50
+ // .gap-{$i} {
51
+ // gap: 0.25rem * $i;
52
+ // }
53
+ // }
54
+
35
55
  .gap-0 {
36
56
  gap: 0;
37
57
  }