@afeefa/vue-app 0.0.54 → 0.0.57
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/AContextMenu.vue +1 -1
- package/src/components/AContextMenuItem.vue +1 -1
- package/src/components/ADialog.vue +2 -0
- package/src/components/ARichTextArea.vue +257 -0
- package/src/components/ASearchSelect.vue +12 -12
- package/src/components/form/EditForm.vue +1 -5
- package/src/components/form/EditModal.vue +22 -17
- package/src/components/form/FormFieldMixin.js +2 -3
- package/src/components/form/fields/FormFieldRichTextArea.vue +14 -0
- package/src/components/index.js +2 -0
- package/src/components/list/ListViewMixin.js +4 -0
- package/src/components/list/filters/ListFilterSelect.vue +4 -2
- package/src/components/search-select/SearchSelectList.vue +5 -1
- package/src/index.js +2 -0
- package/src/plugins/api-resources/ApiResourcesPlugin.js +12 -0
- package/src/styles/forms.scss +8 -0
- package/src/styles/vue-app.scss +1 -0
- package/src-admin/bootstrap.js +2 -5
- package/src-admin/components/controls/SearchSelectFormField.vue +223 -0
- package/src-admin/components/detail/DetailProperty.vue +1 -3
- package/src-admin/components/list/ListColumnHeader.vue +4 -3
- package/src-admin/components/list/ListView.vue +15 -5
- package/src-admin/components/pages/CreatePage.vue +1 -2
- package/src-admin/components/pages/DetailPage.vue +3 -3
- package/src-admin/components/pages/EditPage.vue +4 -5
- package/src-admin/components/pages/ListPage.vue +2 -3
- package/src-admin/components/routes/DetailRoute.vue +3 -3
- package/src-admin/components/routes/EditRoute.vue +3 -3
- package/src-admin/components/routes/ListRoute.vue +3 -3
- package/src-admin/config/vuetify.js +3 -1
- package/src-admin/models/Model.js +13 -0
- package/src-admin/models/ModelAdminConfig.js +20 -0
- package/src-components/AMdiIcon.vue +18 -0
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.57
|
package/package.json
CHANGED
@@ -29,7 +29,7 @@ export default class AContextMenuItem extends Vue {
|
|
29
29
|
this.contextMenu.close()
|
30
30
|
if (this.to) {
|
31
31
|
this.$router.push(this.to)
|
32
|
-
.catch(() => null) // prevent duplicated navigation
|
32
|
+
.catch(() => null) // prevent duplicated navigation warning
|
33
33
|
} else {
|
34
34
|
this.$emit('click')
|
35
35
|
}
|
@@ -132,6 +132,8 @@ export default class ADialog extends Mixins(UsesPositionServiceMixin) {
|
|
132
132
|
if (!Array.isArray(anchor)) {
|
133
133
|
if (typeof anchor === 'string') {
|
134
134
|
anchor = [document.documentElement, anchor]
|
135
|
+
} else if (typeof anchor === 'object') { // dom element or vue ref
|
136
|
+
anchor = [anchor]
|
135
137
|
} else {
|
136
138
|
anchor = [document.documentElement]
|
137
139
|
}
|
@@ -0,0 +1,257 @@
|
|
1
|
+
<template>
|
2
|
+
<div :class="['a-rich-text-editor a-text-input', {'a-text-input-focused': focus}]">
|
3
|
+
<div
|
4
|
+
v-if="editor"
|
5
|
+
class="menu-bar"
|
6
|
+
>
|
7
|
+
<v-btn
|
8
|
+
small
|
9
|
+
:class="['menu-button', {'is-active': focus && editor.isActive('bold')}]"
|
10
|
+
@click="editor.chain().focus().toggleBold().run()"
|
11
|
+
>
|
12
|
+
<v-icon>{{ boldIcon }}</v-icon>
|
13
|
+
</v-btn>
|
14
|
+
|
15
|
+
<v-btn
|
16
|
+
small
|
17
|
+
:class="['menu-button', {'is-active': focus && editor.isActive('italic')}]"
|
18
|
+
@click="editor.chain().focus().toggleItalic().run()"
|
19
|
+
>
|
20
|
+
<v-icon>{{ italicIcon }}</v-icon>
|
21
|
+
</v-btn>
|
22
|
+
|
23
|
+
<v-btn
|
24
|
+
small
|
25
|
+
:class="['menu-button', 'strike', {'is-active': focus && editor.isActive('strike')}]"
|
26
|
+
@click="editor.chain().focus().toggleStrike().run()"
|
27
|
+
>
|
28
|
+
<v-icon>{{ strikeIcon }}</v-icon>
|
29
|
+
</v-btn>
|
30
|
+
|
31
|
+
<v-btn
|
32
|
+
small
|
33
|
+
:class="['menu-button', {'is-active': focus && editor.isActive('heading', {level: 1})}]"
|
34
|
+
@click="editor.chain().focus().toggleHeading({level: 1}).run()"
|
35
|
+
>
|
36
|
+
<v-icon>{{ h1Icon }}</v-icon>
|
37
|
+
</v-btn>
|
38
|
+
|
39
|
+
<v-btn
|
40
|
+
small
|
41
|
+
:class="['menu-button', {'is-active': focus && editor.isActive('heading', {level: 2})}]"
|
42
|
+
@click="editor.chain().focus().toggleHeading({level: 2}).run()"
|
43
|
+
>
|
44
|
+
<v-icon>{{ h2Icon }}</v-icon>
|
45
|
+
</v-btn>
|
46
|
+
|
47
|
+
<v-btn
|
48
|
+
small
|
49
|
+
:class="['menu-button', {'is-active': focus && editor.isActive('bulletList')}]"
|
50
|
+
@click="editor.chain().focus().toggleBulletList().run()"
|
51
|
+
>
|
52
|
+
<v-icon>{{ ulIcon }}</v-icon>
|
53
|
+
</v-btn>
|
54
|
+
|
55
|
+
<v-btn
|
56
|
+
small
|
57
|
+
:class="['menu-button', {'is-active': focus && editor.isActive('orderedList')}]"
|
58
|
+
@click="editor.chain().focus().toggleOrderedList().run()"
|
59
|
+
>
|
60
|
+
<v-icon>{{ olIcon }}</v-icon>
|
61
|
+
</v-btn>
|
62
|
+
|
63
|
+
<v-btn
|
64
|
+
small
|
65
|
+
:class="['menu-button', {'is-active': focus && editor.isActive('blockquote')}]"
|
66
|
+
@click="editor.chain().focus().toggleBlockquote().run()"
|
67
|
+
>
|
68
|
+
<v-icon>{{ commentIcon }}</v-icon>
|
69
|
+
</v-btn>
|
70
|
+
|
71
|
+
<v-btn
|
72
|
+
small
|
73
|
+
class="menu-button"
|
74
|
+
@click="editor.chain().focus().undo().run()"
|
75
|
+
>
|
76
|
+
<v-icon>{{ undoIcon }}</v-icon>
|
77
|
+
</v-btn>
|
78
|
+
|
79
|
+
<v-btn
|
80
|
+
small
|
81
|
+
class="menu-button"
|
82
|
+
@click="editor.chain().focus().redo().run()"
|
83
|
+
>
|
84
|
+
<v-icon>{{ redoIcon }}</v-icon>
|
85
|
+
</v-btn>
|
86
|
+
</div>
|
87
|
+
|
88
|
+
<editor-content
|
89
|
+
:editor="editor"
|
90
|
+
:class="['a-rich-text-editor', {focus}]"
|
91
|
+
/>
|
92
|
+
</div>
|
93
|
+
</template>
|
94
|
+
|
95
|
+
|
96
|
+
<script>
|
97
|
+
import { Component, Vue, Watch } from '@a-vue'
|
98
|
+
import { Editor, EditorContent } from '@tiptap/vue-2'
|
99
|
+
import StarterKit from '@tiptap/starter-kit'
|
100
|
+
import {
|
101
|
+
mdiFormatBold,
|
102
|
+
mdiFormatItalic,
|
103
|
+
mdiFormatStrikethroughVariant,
|
104
|
+
mdiFormatHeader1,
|
105
|
+
mdiFormatHeader2,
|
106
|
+
mdiFormatListBulleted,
|
107
|
+
mdiFormatListNumbered,
|
108
|
+
mdiFormatQuoteClose,
|
109
|
+
mdiRotateLeft,
|
110
|
+
mdiRotateRight
|
111
|
+
} from '@mdi/js'
|
112
|
+
|
113
|
+
@Component({
|
114
|
+
props: ['value', 'validator'],
|
115
|
+
components: {
|
116
|
+
EditorContent
|
117
|
+
}
|
118
|
+
})
|
119
|
+
export default class ARichTextArea extends Vue {
|
120
|
+
editor = null
|
121
|
+
internalValue = null
|
122
|
+
focus = false
|
123
|
+
|
124
|
+
boldIcon = mdiFormatBold
|
125
|
+
italicIcon = mdiFormatItalic
|
126
|
+
strikeIcon = mdiFormatStrikethroughVariant
|
127
|
+
h1Icon = mdiFormatHeader1
|
128
|
+
h2Icon = mdiFormatHeader2
|
129
|
+
ulIcon = mdiFormatListBulleted
|
130
|
+
olIcon = mdiFormatListNumbered
|
131
|
+
commentIcon = mdiFormatQuoteClose
|
132
|
+
undoIcon = mdiRotateLeft
|
133
|
+
redoIcon = mdiRotateRight
|
134
|
+
|
135
|
+
created () {
|
136
|
+
this.internalValue = this.value
|
137
|
+
}
|
138
|
+
|
139
|
+
mounted () {
|
140
|
+
if (this.validator) {
|
141
|
+
this.$refs.input.validate(true)
|
142
|
+
}
|
143
|
+
|
144
|
+
this.editor = new Editor({
|
145
|
+
content: this.internalValue,
|
146
|
+
extensions: [
|
147
|
+
StarterKit
|
148
|
+
],
|
149
|
+
onUpdate: () => {
|
150
|
+
this.$emit('input', this.editor.getHTML())
|
151
|
+
},
|
152
|
+
onFocus: ({ editor, event }) => {
|
153
|
+
this.focus = true
|
154
|
+
},
|
155
|
+
onBlur: ({ editor, event }) => {
|
156
|
+
this.focus = false
|
157
|
+
}
|
158
|
+
})
|
159
|
+
|
160
|
+
this.editor.commands.setContent(this.internalValue, false)
|
161
|
+
}
|
162
|
+
|
163
|
+
beforeDestroy () {
|
164
|
+
this.editor.destroy()
|
165
|
+
}
|
166
|
+
|
167
|
+
@Watch('value')
|
168
|
+
valueChanged () {
|
169
|
+
this.internalValue = this.value
|
170
|
+
|
171
|
+
const isSame = this.editor.getHTML() === this.internalValue
|
172
|
+
if (!isSame) {
|
173
|
+
this.editor.commands.setContent(this.internalValue, false)
|
174
|
+
}
|
175
|
+
}
|
176
|
+
|
177
|
+
get validationRules () {
|
178
|
+
const label = this.$attrs.label
|
179
|
+
return (this.validator && this.validator.getRules(label)) || []
|
180
|
+
}
|
181
|
+
|
182
|
+
get counter () {
|
183
|
+
if (!this.validator) {
|
184
|
+
return false
|
185
|
+
}
|
186
|
+
return this.validator.getParams().max || false
|
187
|
+
}
|
188
|
+
}
|
189
|
+
</script>
|
190
|
+
|
191
|
+
|
192
|
+
<style lang="scss" scoped>
|
193
|
+
.v-input:not(.v-input--is-focused) ::v-deep .v-counter {
|
194
|
+
display: none;
|
195
|
+
}
|
196
|
+
|
197
|
+
.a-rich-text-editor {
|
198
|
+
::v-deep .ProseMirror {
|
199
|
+
&-focused {
|
200
|
+
outline: none;
|
201
|
+
}
|
202
|
+
}
|
203
|
+
}
|
204
|
+
|
205
|
+
.menu-bar {
|
206
|
+
margin: -.2rem 0 .5rem -.2rem;
|
207
|
+
}
|
208
|
+
|
209
|
+
.menu-button {
|
210
|
+
padding: 0 !important;
|
211
|
+
width: 30px !important;
|
212
|
+
height: 32px !important;
|
213
|
+
min-width: unset !important;
|
214
|
+
text-align: center;
|
215
|
+
font-size: 1rem;
|
216
|
+
background: white !important;
|
217
|
+
border: none;
|
218
|
+
box-shadow: none;
|
219
|
+
border-radius: 0;
|
220
|
+
|
221
|
+
::v-deep .v-icon {
|
222
|
+
font-size: 20px;
|
223
|
+
width: 20px;
|
224
|
+
height: 20px;
|
225
|
+
}
|
226
|
+
|
227
|
+
&.strike {
|
228
|
+
::v-deep .v-icon {
|
229
|
+
width: 15px;
|
230
|
+
}
|
231
|
+
}
|
232
|
+
|
233
|
+
svg {
|
234
|
+
width: unset;
|
235
|
+
}
|
236
|
+
|
237
|
+
&.is-active {
|
238
|
+
background: #ECECEC !important;
|
239
|
+
}
|
240
|
+
}
|
241
|
+
|
242
|
+
::v-deep .ProseMirror {
|
243
|
+
min-height: 200px;
|
244
|
+
|
245
|
+
> :last-child {
|
246
|
+
margin: 0;
|
247
|
+
}
|
248
|
+
|
249
|
+
li p {
|
250
|
+
margin: 0;
|
251
|
+
}
|
252
|
+
|
253
|
+
ul {
|
254
|
+
margin: 16px 0;
|
255
|
+
}
|
256
|
+
}
|
257
|
+
</style>
|
@@ -16,6 +16,7 @@
|
|
16
16
|
<div
|
17
17
|
v-if="isOpen"
|
18
18
|
class="controls"
|
19
|
+
:style="cwm_widthStyle"
|
19
20
|
>
|
20
21
|
<div class="background elevation-6" />
|
21
22
|
|
@@ -54,6 +55,7 @@
|
|
54
55
|
:filters.sync="filters"
|
55
56
|
:count.sync="count"
|
56
57
|
:isLoading.sync="isLoading"
|
58
|
+
:style="cwm_widthStyle"
|
57
59
|
>
|
58
60
|
<template #header>
|
59
61
|
<div />
|
@@ -62,19 +64,11 @@
|
|
62
64
|
</template>
|
63
65
|
|
64
66
|
<template #row="{ model }">
|
65
|
-
<v-icon
|
66
|
-
:color="model.getIcon().color"
|
67
|
-
size="1.5rem"
|
68
|
-
v-text="model.getIcon().icon"
|
69
|
-
/>
|
70
|
-
|
71
67
|
<slot
|
72
68
|
name="row"
|
73
69
|
:model="model"
|
74
70
|
:on="{ click: selectHandler(model) }"
|
75
71
|
/>
|
76
|
-
|
77
|
-
<div class="lastColumn" />
|
78
72
|
</template>
|
79
73
|
|
80
74
|
<template #not-found="{ filters }">
|
@@ -98,6 +92,7 @@ import { FilterSourceType } from '@a-vue/components/list/FilterSourceType'
|
|
98
92
|
import SearchSelectFilters from './search-select/SearchSelectFilters'
|
99
93
|
import SearchSelectList from './search-select/SearchSelectList'
|
100
94
|
import { CancelOnEscMixin } from '@a-vue/services/escape/CancelOnEscMixin'
|
95
|
+
import { ComponentWidthMixin } from './mixins/ComponentWidthMixin'
|
101
96
|
|
102
97
|
@Component({
|
103
98
|
props: [
|
@@ -115,7 +110,7 @@ import { CancelOnEscMixin } from '@a-vue/services/escape/CancelOnEscMixin'
|
|
115
110
|
SearchSelectList
|
116
111
|
}
|
117
112
|
})
|
118
|
-
export default class ASearchSelect extends Mixins(UsesPositionServiceMixin, CancelOnEscMixin) {
|
113
|
+
export default class ASearchSelect extends Mixins(ComponentWidthMixin, UsesPositionServiceMixin, CancelOnEscMixin) {
|
119
114
|
selectId = randomCssClass(10)
|
120
115
|
isOpen = false
|
121
116
|
items_ = []
|
@@ -318,20 +313,25 @@ export default class ASearchSelect extends Mixins(UsesPositionServiceMixin, Canc
|
|
318
313
|
}
|
319
314
|
|
320
315
|
.controls {
|
321
|
-
|
316
|
+
width: 400px;
|
322
317
|
position: absolute;
|
323
318
|
z-index: 300;
|
324
319
|
display: block;
|
325
|
-
padding: 0
|
320
|
+
padding: 0 .5rem;
|
321
|
+
|
322
|
+
::v-deep .a-row {
|
323
|
+
overflow: unset;
|
324
|
+
}
|
326
325
|
}
|
327
326
|
|
328
327
|
.searchSelectList {
|
329
|
-
|
328
|
+
width: 400px;
|
330
329
|
position: absolute;
|
331
330
|
z-index: 301;
|
332
331
|
|
333
332
|
max-height: 40vh;
|
334
333
|
overflow-y: auto;
|
334
|
+
overflow-x: hidden;
|
335
335
|
overscroll-behavior: contain;
|
336
336
|
|
337
337
|
::v-deep .a-table-row {
|
@@ -8,6 +8,7 @@
|
|
8
8
|
<slot
|
9
9
|
:changed="changed"
|
10
10
|
:valid="valid"
|
11
|
+
:model="model"
|
11
12
|
/>
|
12
13
|
</v-form>
|
13
14
|
</template>
|
@@ -15,7 +16,6 @@
|
|
15
16
|
|
16
17
|
<script>
|
17
18
|
import { Component, Vue, Watch } from '@a-vue'
|
18
|
-
import { apiResources } from '@afeefa/api-resources-client'
|
19
19
|
|
20
20
|
@Component({
|
21
21
|
props: ['model']
|
@@ -52,9 +52,5 @@ export default class EditForm extends Vue {
|
|
52
52
|
changedChanged () {
|
53
53
|
this.$emit('update:changed', this.changed)
|
54
54
|
}
|
55
|
-
|
56
|
-
get type () {
|
57
|
-
return apiResources.getType(this.model.type)
|
58
|
-
}
|
59
55
|
}
|
60
56
|
</script>
|
@@ -21,7 +21,7 @@
|
|
21
21
|
|
22
22
|
<template #default="{changed, valid}">
|
23
23
|
<a-row
|
24
|
-
class="mt-8 mb-
|
24
|
+
class="mt-8 mb-1 pb-1 gap-4"
|
25
25
|
right
|
26
26
|
>
|
27
27
|
<v-btn
|
@@ -31,23 +31,25 @@
|
|
31
31
|
Schließen
|
32
32
|
</v-btn>
|
33
33
|
|
34
|
-
<
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
34
|
+
<a-row gap="2">
|
35
|
+
<v-btn
|
36
|
+
small
|
37
|
+
:disabled="!changed || !valid"
|
38
|
+
color="green white--text"
|
39
|
+
@click="save"
|
40
|
+
>
|
41
|
+
Speichern
|
42
|
+
</v-btn>
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
44
|
+
<v-icon
|
45
|
+
v-if="changed"
|
46
|
+
small
|
47
|
+
text
|
48
|
+
@click="reset"
|
49
|
+
>
|
50
|
+
{{ undoIcon }}
|
51
|
+
</v-icon>
|
52
|
+
</a-row>
|
51
53
|
</a-row>
|
52
54
|
</template>
|
53
55
|
</edit-form>
|
@@ -57,6 +59,7 @@
|
|
57
59
|
|
58
60
|
<script>
|
59
61
|
import { Component, Vue, Watch } from '@a-vue'
|
62
|
+
import { mdiRotateLeft} from '@mdi/js'
|
60
63
|
|
61
64
|
@Component({
|
62
65
|
props: ['model', 'title', 'show']
|
@@ -64,6 +67,8 @@ import { Component, Vue, Watch } from '@a-vue'
|
|
64
67
|
export default class EditModal extends Vue {
|
65
68
|
show_ = false
|
66
69
|
|
70
|
+
undoIcon = mdiRotateLeft
|
71
|
+
|
67
72
|
/**
|
68
73
|
* visiblility changes from outside
|
69
74
|
* this will trigger the show_ watcher,
|
@@ -1,6 +1,5 @@
|
|
1
|
-
import { ListAction } from '@a-vue/api-resources/ApiActions'
|
2
|
-
import { apiResources } from '@afeefa/api-resources-client'
|
3
1
|
import { Component, Vue } from '@a-vue'
|
2
|
+
import { ListAction } from '@a-vue/api-resources/ApiActions'
|
4
3
|
|
5
4
|
@Component({
|
6
5
|
props: ['name', 'label']
|
@@ -17,7 +16,7 @@ export class FormFieldMixin extends Vue {
|
|
17
16
|
}
|
18
17
|
|
19
18
|
get modelType () {
|
20
|
-
return apiResources.getType(this.model.type)
|
19
|
+
return this.$apiResources.getType(this.model.type)
|
21
20
|
}
|
22
21
|
|
23
22
|
get field () {
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<template>
|
2
|
+
<a-rich-text-area
|
3
|
+
v-model="model[name]"
|
4
|
+
/>
|
5
|
+
</template>
|
6
|
+
|
7
|
+
<script>
|
8
|
+
import { Component, Mixins } from '@a-vue'
|
9
|
+
import { FormFieldMixin } from '../FormFieldMixin'
|
10
|
+
|
11
|
+
@Component
|
12
|
+
export default class FormFieldRichTextArea extends Mixins(FormFieldMixin) {
|
13
|
+
}
|
14
|
+
</script>
|
package/src/components/index.js
CHANGED
@@ -5,6 +5,7 @@ import EditModal from './form/EditModal'
|
|
5
5
|
import FormFieldCheckbox from './form/fields/FormFieldCheckbox'
|
6
6
|
import FormFieldDate from './form/fields/FormFieldDate'
|
7
7
|
import FormFieldRadioGroup from './form/fields/FormFieldRadioGroup'
|
8
|
+
import FormFieldRichTextArea from './form/fields/FormFieldRichTextArea'
|
8
9
|
import FormFieldSearchSelect from './form/fields/FormFieldSearchSelect'
|
9
10
|
import FormFieldSelect from './form/fields/FormFieldSelect'
|
10
11
|
import FormFieldSelect2 from './form/fields/FormFieldSelect2'
|
@@ -19,6 +20,7 @@ Vue.component('EditForm', EditForm)
|
|
19
20
|
Vue.component('EditModal', EditModal)
|
20
21
|
Vue.component('FormFieldText', FormFieldText)
|
21
22
|
Vue.component('FormFieldTextArea', FormFieldTextArea)
|
23
|
+
Vue.component('FormFieldRichTextArea', FormFieldRichTextArea)
|
22
24
|
Vue.component('FormFieldRadioGroup', FormFieldRadioGroup)
|
23
25
|
Vue.component('FormFieldCheckbox', FormFieldCheckbox)
|
24
26
|
Vue.component('FormFieldDate', FormFieldDate)
|
@@ -17,7 +17,9 @@ import { Component, Mixins } from '@a-vue'
|
|
17
17
|
import { ListFilterMixin } from '../ListFilterMixin'
|
18
18
|
import { ListAction } from '@a-vue/api-resources/ApiActions'
|
19
19
|
|
20
|
-
@Component
|
20
|
+
@Component({
|
21
|
+
props: ['itemTitle']
|
22
|
+
})
|
21
23
|
export default class ListFilterSelect extends Mixins(ListFilterMixin) {
|
22
24
|
items = null
|
23
25
|
|
@@ -61,7 +63,7 @@ export default class ListFilterSelect extends Mixins(ListFilterMixin) {
|
|
61
63
|
return [
|
62
64
|
...this.createOptions(),
|
63
65
|
...models.map(model => ({
|
64
|
-
itemTitle: model.name,
|
66
|
+
itemTitle: (this.itemTitle && this.itemTitle(model)) || model.name || model.title,
|
65
67
|
itemValue: model.id
|
66
68
|
}))
|
67
69
|
]
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<template>
|
2
|
-
<div class="searchSelectList">
|
2
|
+
<div :class="['searchSelectList', {isLoading}]">
|
3
3
|
<template v-if="models_.length">
|
4
4
|
<a-table v-bind="$attrs">
|
5
5
|
<a-table-header
|
@@ -74,6 +74,10 @@ export default class SearchSelectList extends Mixins(ListViewMixin) {
|
|
74
74
|
|
75
75
|
|
76
76
|
<style scoped lang="scss">
|
77
|
+
.isLoading {
|
78
|
+
opacity: .6;
|
79
|
+
}
|
80
|
+
|
77
81
|
.notFound {
|
78
82
|
padding: 0 .5rem .3rem;
|
79
83
|
}
|
package/src/index.js
CHANGED
@@ -1,6 +1,18 @@
|
|
1
1
|
import { apiResources } from '@afeefa/api-resources-client'
|
2
2
|
|
3
3
|
class ApiResourcesPlugin {
|
4
|
+
apiResources = apiResources
|
5
|
+
|
6
|
+
register (models, apis) {
|
7
|
+
apiResources
|
8
|
+
.registerModels(models)
|
9
|
+
.registerApis(apis)
|
10
|
+
}
|
11
|
+
|
12
|
+
schemasLoaded () {
|
13
|
+
return apiResources.schemasLoaded()
|
14
|
+
}
|
15
|
+
|
4
16
|
install (Vue) {
|
5
17
|
Object.defineProperty(Vue.prototype, '$apiResources', {
|
6
18
|
get () {
|
@@ -0,0 +1 @@
|
|
1
|
+
@import "forms";
|
package/src-admin/bootstrap.js
CHANGED
@@ -4,7 +4,6 @@ import './config/components'
|
|
4
4
|
import { apiResourcesPlugin } from '@a-vue/plugins/api-resources/ApiResourcesPlugin'
|
5
5
|
import { hasOptionsPlugin } from '@a-vue/plugins/has-options/HasOptionsPlugin'
|
6
6
|
import { timeout } from '@a-vue/utils/timeout'
|
7
|
-
import { apiResources } from '@afeefa/api-resources-client'
|
8
7
|
import Vue from 'vue'
|
9
8
|
|
10
9
|
import { appConfig } from './config/AppConfig'
|
@@ -17,9 +16,7 @@ Vue.use(hasOptionsPlugin)
|
|
17
16
|
Vue.config.productionTip = false
|
18
17
|
|
19
18
|
export async function bootstrap ({ apis, models, routing, authService, app, components }) {
|
20
|
-
|
21
|
-
.registerModels(models)
|
22
|
-
.registerApis(apis)
|
19
|
+
apiResourcesPlugin.register(models, apis)
|
23
20
|
|
24
21
|
appConfig.authService = authService
|
25
22
|
appConfig.app = app
|
@@ -36,7 +33,7 @@ export async function bootstrap ({ apis, models, routing, authService, app, comp
|
|
36
33
|
|
37
34
|
routing(routeConfigPlugin)
|
38
35
|
const router = await routeConfigPlugin.getRouter()
|
39
|
-
await
|
36
|
+
await apiResourcesPlugin.schemasLoaded()
|
40
37
|
|
41
38
|
if (authService) {
|
42
39
|
authService.initApp(router)
|
@@ -0,0 +1,223 @@
|
|
1
|
+
<template>
|
2
|
+
<div>
|
3
|
+
<a-table
|
4
|
+
v-if="selectedItems.length"
|
5
|
+
:style="selectedWidthStyle"
|
6
|
+
>
|
7
|
+
<a-table-header
|
8
|
+
v-if="hasHeader"
|
9
|
+
small
|
10
|
+
>
|
11
|
+
<div
|
12
|
+
v-for="(column, index) in selectedColumns"
|
13
|
+
:key="index"
|
14
|
+
>
|
15
|
+
{{ column.header }}
|
16
|
+
</div>
|
17
|
+
</a-table-header>
|
18
|
+
|
19
|
+
<a-table-row
|
20
|
+
v-for="(item, index) in selectedItems"
|
21
|
+
:key="item.id"
|
22
|
+
:selected="isClicked(item)"
|
23
|
+
>
|
24
|
+
<template v-for="(column, index2) in selectedColumns">
|
25
|
+
<v-icon
|
26
|
+
v-if="column.icon"
|
27
|
+
:key="'icon' + index2"
|
28
|
+
:color="column.icon.color"
|
29
|
+
class="selectedIcon"
|
30
|
+
size="1.5rem"
|
31
|
+
v-text="column.icon.icon"
|
32
|
+
/>
|
33
|
+
|
34
|
+
<div
|
35
|
+
v-else
|
36
|
+
:key="'text' + index2"
|
37
|
+
class="selectedContent"
|
38
|
+
>
|
39
|
+
{{ column.text(item) }}
|
40
|
+
</div>
|
41
|
+
</template>
|
42
|
+
|
43
|
+
<div>
|
44
|
+
<a-context-menu
|
45
|
+
:ref="'editItem' + index"
|
46
|
+
@open="clickedItem = item"
|
47
|
+
@close="clickedItem = null"
|
48
|
+
>
|
49
|
+
<a-context-menu-item @click="removeItem(item, index)">
|
50
|
+
<v-icon>$trashCanIcon</v-icon>
|
51
|
+
Löschen
|
52
|
+
</a-context-menu-item>
|
53
|
+
</a-context-menu>
|
54
|
+
</div>
|
55
|
+
</a-table-row>
|
56
|
+
</a-table>
|
57
|
+
|
58
|
+
<div v-else>
|
59
|
+
{{ isEmptyText }}
|
60
|
+
</div>
|
61
|
+
|
62
|
+
<a-search-select
|
63
|
+
:listViewConfig="selectableConfig.listViewConfig"
|
64
|
+
:loadOnlyIfKeyword="false"
|
65
|
+
:selectedItems="selectableSelectedItems"
|
66
|
+
:width="selectableWidth"
|
67
|
+
@select="addItem"
|
68
|
+
>
|
69
|
+
<template #activator>
|
70
|
+
<a-icon-button
|
71
|
+
icon="$plusIcon"
|
72
|
+
:text="selectableConfig.addButtonTitle || 'Hinzufügen'"
|
73
|
+
class="mt-4"
|
74
|
+
/>
|
75
|
+
</template>
|
76
|
+
|
77
|
+
<template #filters>
|
78
|
+
<list-filter-row>
|
79
|
+
<list-filter-search
|
80
|
+
:focus="true"
|
81
|
+
maxWidth="100%"
|
82
|
+
label="Suche Berater:in"
|
83
|
+
/>
|
84
|
+
|
85
|
+
<list-filter-page
|
86
|
+
:has="{page_size: false, page_number: true}"
|
87
|
+
:totalVisible="0"
|
88
|
+
/>
|
89
|
+
</list-filter-row>
|
90
|
+
</template>
|
91
|
+
|
92
|
+
<template #row="{ model, on }">
|
93
|
+
<template
|
94
|
+
v-for="(column, index) in selectableColumns"
|
95
|
+
v-on="on"
|
96
|
+
>
|
97
|
+
<v-icon
|
98
|
+
v-if="column.icon"
|
99
|
+
:key="'icon' + index"
|
100
|
+
:color="column.icon.color"
|
101
|
+
class="selectableIcon"
|
102
|
+
size="1.5rem"
|
103
|
+
v-on="on"
|
104
|
+
v-text="column.icon.icon"
|
105
|
+
/>
|
106
|
+
|
107
|
+
<div
|
108
|
+
v-else
|
109
|
+
:key="'text' + index"
|
110
|
+
class="selectableContent"
|
111
|
+
v-on="on"
|
112
|
+
>
|
113
|
+
{{ column.text(model) }}
|
114
|
+
</div>
|
115
|
+
</template>
|
116
|
+
</template>
|
117
|
+
</a-search-select>
|
118
|
+
</div>
|
119
|
+
</template>
|
120
|
+
|
121
|
+
|
122
|
+
<script>
|
123
|
+
import { Component, Vue } from '@a-vue'
|
124
|
+
|
125
|
+
@Component({
|
126
|
+
props: [
|
127
|
+
'value',
|
128
|
+
'selectedConfig',
|
129
|
+
'selectedWidth',
|
130
|
+
'selectableConfig',
|
131
|
+
'selectableWidth'
|
132
|
+
]
|
133
|
+
})
|
134
|
+
export default class SearchSelectFormField extends Vue {
|
135
|
+
clickedItem = null
|
136
|
+
|
137
|
+
get hasHeader () {
|
138
|
+
return this.selectedColumns.some(c => !!c.header)
|
139
|
+
}
|
140
|
+
|
141
|
+
get selectedItems () {
|
142
|
+
return this.value
|
143
|
+
}
|
144
|
+
|
145
|
+
get selectableSelectedItems () {
|
146
|
+
return this.value.map(this.selectedConfig.selectedToSelectableItem)
|
147
|
+
}
|
148
|
+
|
149
|
+
get isEmptyText () {
|
150
|
+
return this.selectedConfig.isEmptyText
|
151
|
+
}
|
152
|
+
|
153
|
+
isClicked (selectedItem) {
|
154
|
+
return selectedItem === this.clickedItem
|
155
|
+
}
|
156
|
+
|
157
|
+
get selectedColumns () {
|
158
|
+
return this.selectedConfig.columns
|
159
|
+
}
|
160
|
+
|
161
|
+
get selectableColumns () {
|
162
|
+
return this.selectableConfig.columns
|
163
|
+
}
|
164
|
+
|
165
|
+
addItem (selectableItem) {
|
166
|
+
const selectedItem = this.selectedConfig.newSelectedItem(selectableItem)
|
167
|
+
const selectedItems = [...this.value, selectedItem]
|
168
|
+
if (this.$listeners.add) {
|
169
|
+
this.$emit('add', selectedItems)
|
170
|
+
} else {
|
171
|
+
this.$emit('input', selectedItems)
|
172
|
+
}
|
173
|
+
}
|
174
|
+
|
175
|
+
async removeItem (selectedItem, rowIndex) {
|
176
|
+
const removeDialog = this.selectedConfig.removeDialog(selectedItem)
|
177
|
+
const dialog = {
|
178
|
+
anchor: this.$refs['editItem' + rowIndex], // is array [component]
|
179
|
+
...removeDialog,
|
180
|
+
yesButton: 'Löschen',
|
181
|
+
yesColor: 'red white--text'
|
182
|
+
}
|
183
|
+
|
184
|
+
const selectedItems = this.value.filter(i => i !== selectedItem)
|
185
|
+
if (this.$listeners.remove) {
|
186
|
+
this.$emit('remove', selectedItems, dialog)
|
187
|
+
} else {
|
188
|
+
this.$emit('input', selectedItems)
|
189
|
+
}
|
190
|
+
}
|
191
|
+
|
192
|
+
get selectedWidthStyle () {
|
193
|
+
if (!this.selectedWidth) {
|
194
|
+
return ''
|
195
|
+
}
|
196
|
+
|
197
|
+
let width = this.selectedWidth
|
198
|
+
if (!isNaN(width)) {
|
199
|
+
width = width + 'px'
|
200
|
+
}
|
201
|
+
return `width: ${width};`
|
202
|
+
}
|
203
|
+
}
|
204
|
+
</script>
|
205
|
+
|
206
|
+
|
207
|
+
<style scoped lang="scss">
|
208
|
+
.selectedIcon::v-deep {
|
209
|
+
padding-right: .3rem !important;
|
210
|
+
}
|
211
|
+
|
212
|
+
.selectableIcon::v-deep {
|
213
|
+
padding-right: 2rem !important;
|
214
|
+
}
|
215
|
+
|
216
|
+
.selectedContent::v-deep {
|
217
|
+
width: 100%;
|
218
|
+
}
|
219
|
+
|
220
|
+
.selectableContent::v-deep {
|
221
|
+
width: 100%;
|
222
|
+
}
|
223
|
+
</style>
|
@@ -25,7 +25,6 @@
|
|
25
25
|
|
26
26
|
<script>
|
27
27
|
import { Component, Vue } from '@a-vue'
|
28
|
-
import { apiResources } from '@afeefa/api-resources-client'
|
29
28
|
|
30
29
|
@Component({
|
31
30
|
props: ['icon', 'iconModelType', 'label']
|
@@ -37,7 +36,7 @@ export default class DetailProperty extends Vue {
|
|
37
36
|
}
|
38
37
|
|
39
38
|
if (this.iconModelType) {
|
40
|
-
const ModelClass = apiResources.getModelClass(this.iconModelType)
|
39
|
+
const ModelClass = this.$apiResources.getModelClass(this.iconModelType)
|
41
40
|
return ModelClass.icon
|
42
41
|
}
|
43
42
|
}
|
@@ -77,6 +76,5 @@ export default class DetailProperty extends Vue {
|
|
77
76
|
padding-left: 55px;
|
78
77
|
}
|
79
78
|
}
|
80
|
-
|
81
79
|
}
|
82
80
|
</style>
|
@@ -9,7 +9,15 @@
|
|
9
9
|
</div>
|
10
10
|
|
11
11
|
<template v-if="models_.length">
|
12
|
-
<template v-if="
|
12
|
+
<template v-if="$scopedSlots.models">
|
13
|
+
<slot
|
14
|
+
name="models"
|
15
|
+
:models="models_"
|
16
|
+
:setFilter="setFilter"
|
17
|
+
/>
|
18
|
+
</template>
|
19
|
+
|
20
|
+
<template v-else-if="$scopedSlots['model-table']">
|
13
21
|
<a-table>
|
14
22
|
<a-table-header>
|
15
23
|
<div v-if="$has.icon" />
|
@@ -20,6 +28,7 @@
|
|
20
28
|
<a-table-row
|
21
29
|
v-for="model in models_"
|
22
30
|
:key="model.id"
|
31
|
+
:class="getModelClass(model)"
|
23
32
|
>
|
24
33
|
<v-icon
|
25
34
|
v-if="$has.icon"
|
@@ -37,10 +46,11 @@
|
|
37
46
|
</a-table>
|
38
47
|
</template>
|
39
48
|
|
40
|
-
<template v-else>
|
49
|
+
<template v-else-if="$scopedSlots.model">
|
41
50
|
<div
|
42
51
|
v-for="model in models_"
|
43
52
|
:key="model.id"
|
53
|
+
:class="getModelClass(model)"
|
44
54
|
>
|
45
55
|
<slot
|
46
56
|
name="model"
|
@@ -66,7 +76,7 @@ import { ListViewMixin } from '@a-vue/components/list/ListViewMixin'
|
|
66
76
|
import { LoadingEvent } from '@a-vue/events'
|
67
77
|
|
68
78
|
@Component({
|
69
|
-
props: ['
|
79
|
+
props: ['modelClass']
|
70
80
|
})
|
71
81
|
export default class ListView extends Mixins(ListViewMixin) {
|
72
82
|
$hasOptions = ['icon']
|
@@ -83,8 +93,8 @@ export default class ListView extends Mixins(ListViewMixin) {
|
|
83
93
|
this.$emit('update:isLoading', this.isLoading)
|
84
94
|
}
|
85
95
|
|
86
|
-
|
87
|
-
return this.
|
96
|
+
getModelClass (model) {
|
97
|
+
return this.modelClass && this.modelClass(model)
|
88
98
|
}
|
89
99
|
|
90
100
|
setFilter (name, value) {
|
@@ -49,7 +49,6 @@
|
|
49
49
|
<script>
|
50
50
|
import { Component, Mixins } from '@a-vue'
|
51
51
|
import { EditPageMixin } from './EditPageMixin'
|
52
|
-
import { apiResources } from '@afeefa/api-resources-client'
|
53
52
|
|
54
53
|
@Component({
|
55
54
|
props: ['icon', 'title', 'createModel', 'listLink']
|
@@ -86,7 +85,7 @@ export default class CreatePage extends Mixins(EditPageMixin) {
|
|
86
85
|
return this.title
|
87
86
|
}
|
88
87
|
|
89
|
-
const type = apiResources.getType(this.ModelClass.type)
|
88
|
+
const type = this.$apiResources.getType(this.ModelClass.type)
|
90
89
|
return type.t('TITLE_NEW')
|
91
90
|
}
|
92
91
|
|
@@ -64,8 +64,8 @@ export default class DetailPage extends Vue {
|
|
64
64
|
removeConfirmed = null
|
65
65
|
|
66
66
|
created () {
|
67
|
-
if (!this.$parent.constructor.
|
68
|
-
console.warn('<detail-page> owner must provide a static
|
67
|
+
if (!this.$parent.constructor.getDetailRouteConfig) {
|
68
|
+
console.warn('<detail-page> owner must provide a static getDetailRouteConfig method.')
|
69
69
|
}
|
70
70
|
this.$emit('model', this.model)
|
71
71
|
}
|
@@ -80,7 +80,7 @@ export default class DetailPage extends Vue {
|
|
80
80
|
}
|
81
81
|
|
82
82
|
get detailConfig () {
|
83
|
-
return this.$parent.constructor.
|
83
|
+
return this.$parent.constructor.getDetailRouteConfig(this.$route)
|
84
84
|
}
|
85
85
|
|
86
86
|
get document () {
|
@@ -66,7 +66,6 @@
|
|
66
66
|
|
67
67
|
<script>
|
68
68
|
import { Component, Mixins, Watch } from '@a-vue'
|
69
|
-
import { apiResources } from '@afeefa/api-resources-client'
|
70
69
|
import { EditPageMixin } from './EditPageMixin'
|
71
70
|
|
72
71
|
@Component({
|
@@ -78,8 +77,8 @@ export default class EditPage extends Mixins(EditPageMixin) {
|
|
78
77
|
model_ = null
|
79
78
|
|
80
79
|
created () {
|
81
|
-
if (!this.$parent.constructor.
|
82
|
-
console.warn('<edit-page> owner must provide a static
|
80
|
+
if (!this.$parent.constructor.getEditRouteConfig) {
|
81
|
+
console.warn('<edit-page> owner must provide a static getEditRouteConfig method.')
|
83
82
|
}
|
84
83
|
|
85
84
|
this.model_ = this.model
|
@@ -95,7 +94,7 @@ export default class EditPage extends Mixins(EditPageMixin) {
|
|
95
94
|
}
|
96
95
|
|
97
96
|
get editConfig () {
|
98
|
-
return this.$parent.constructor.
|
97
|
+
return this.$parent.constructor.getEditRouteConfig(this.$route)
|
99
98
|
}
|
100
99
|
|
101
100
|
get modelUpateAction () {
|
@@ -123,7 +122,7 @@ export default class EditPage extends Mixins(EditPageMixin) {
|
|
123
122
|
return this.title
|
124
123
|
}
|
125
124
|
|
126
|
-
const type = apiResources.getType(this.ModelClass.type)
|
125
|
+
const type = this.$apiResources.getType(this.ModelClass.type)
|
127
126
|
return type.t('TITLE_EMPTY')
|
128
127
|
}
|
129
128
|
|
@@ -21,7 +21,6 @@
|
|
21
21
|
|
22
22
|
<script>
|
23
23
|
import { Component, Vue } from '@a-vue'
|
24
|
-
import { apiResources } from '@afeefa/api-resources-client'
|
25
24
|
|
26
25
|
@Component({
|
27
26
|
props: ['icon', 'title', 'newTitle', 'newLink', 'Model']
|
@@ -38,7 +37,7 @@ export default class ListPage extends Vue {
|
|
38
37
|
return this.title
|
39
38
|
}
|
40
39
|
|
41
|
-
const type = apiResources.getType(this.Model.type)
|
40
|
+
const type = this.$apiResources.getType(this.Model.type)
|
42
41
|
return type.t('TITLE_PLURAL')
|
43
42
|
}
|
44
43
|
|
@@ -47,7 +46,7 @@ export default class ListPage extends Vue {
|
|
47
46
|
return this.newTitle
|
48
47
|
}
|
49
48
|
|
50
|
-
const type = apiResources.getType(this.Model.type)
|
49
|
+
const type = this.$apiResources.getType(this.Model.type)
|
51
50
|
return type.t('TITLE_SINGULAR')
|
52
51
|
}
|
53
52
|
|
@@ -19,11 +19,11 @@ function load (route) {
|
|
19
19
|
const routeDefinition = route.meta.routeDefinition
|
20
20
|
const Component = routeDefinition.config.detail
|
21
21
|
|
22
|
-
if (!Component.
|
23
|
-
console.warn('A detail route component must implement a static
|
22
|
+
if (!Component.getDetailRouteConfig) {
|
23
|
+
console.warn('A detail route component must implement a static getDetailRouteConfig property.')
|
24
24
|
}
|
25
25
|
|
26
|
-
const detailConfig = Component.
|
26
|
+
const detailConfig = Component.getDetailRouteConfig(route)
|
27
27
|
const action = detailConfig.action || detailConfig.ModelClass.getAction('get')
|
28
28
|
|
29
29
|
return new GetAction()
|
@@ -20,11 +20,11 @@ function load (route) {
|
|
20
20
|
const routeDefinition = route.meta.routeDefinition
|
21
21
|
const Component = routeDefinition.config.edit
|
22
22
|
|
23
|
-
if (!Component.
|
24
|
-
console.warn('An edit route component must implement a static
|
23
|
+
if (!Component.getEditRouteConfig) {
|
24
|
+
console.warn('An edit route component must implement a static getEditRouteConfig property.')
|
25
25
|
}
|
26
26
|
|
27
|
-
const editConfig = Component.
|
27
|
+
const editConfig = Component.getEditRouteConfig(route)
|
28
28
|
const action = editConfig.getAction || editConfig.ModelClass.getAction('get')
|
29
29
|
|
30
30
|
return new GetAction()
|
@@ -31,11 +31,11 @@ function load (route) {
|
|
31
31
|
const routeDefinition = route.meta.routeDefinition
|
32
32
|
const Component = routeDefinition.config.list
|
33
33
|
|
34
|
-
if (!Component.
|
35
|
-
console.warn('A list route component must implement a static
|
34
|
+
if (!Component.getListRouteConfig) {
|
35
|
+
console.warn('A list route component must implement a static getListRouteConfig property.')
|
36
36
|
}
|
37
37
|
|
38
|
-
const request = new ListViewModel(Component.
|
38
|
+
const request = new ListViewModel(Component.getListRouteConfig(route))
|
39
39
|
// read from next route query string, but do not push
|
40
40
|
// list component will be init with used_filters
|
41
41
|
.filterSource(new NextRouteFilterSource(route), false)
|
@@ -6,6 +6,7 @@ import {
|
|
6
6
|
mdiDelete,
|
7
7
|
mdiDotsHorizontal,
|
8
8
|
mdiDotsVertical,
|
9
|
+
mdiLock,
|
9
10
|
mdiLogoutVariant,
|
10
11
|
mdiMagnify,
|
11
12
|
mdiPencil,
|
@@ -32,7 +33,8 @@ export default new Vuetify({
|
|
32
33
|
pencilIcon: mdiPencil,
|
33
34
|
trashCanIcon: mdiDelete,
|
34
35
|
calendarIcon: mdiCalendar,
|
35
|
-
searchIcon: mdiMagnify
|
36
|
+
searchIcon: mdiMagnify,
|
37
|
+
lockIcon: mdiLock
|
36
38
|
}
|
37
39
|
},
|
38
40
|
breakpoint: {
|
@@ -1,11 +1,17 @@
|
|
1
1
|
import { Model as ApiResourcesModel, apiResources } from '@afeefa/api-resources-client'
|
2
2
|
import { mdiAlphaMCircle } from '@mdi/js'
|
3
3
|
|
4
|
+
import { ModelAdminConfig } from './ModelAdminConfig'
|
5
|
+
|
6
|
+
export { ModelAdminConfig }
|
7
|
+
|
4
8
|
export class Model extends ApiResourcesModel {
|
5
9
|
static resourceType = null
|
6
10
|
static routeName = null
|
7
11
|
static routeIdKey = 'id'
|
8
12
|
|
13
|
+
static config = null
|
14
|
+
|
9
15
|
static getLink (action) {
|
10
16
|
return (new this()).getLink(action)
|
11
17
|
}
|
@@ -21,6 +27,13 @@ export class Model extends ApiResourcesModel {
|
|
21
27
|
return null
|
22
28
|
}
|
23
29
|
|
30
|
+
static get adminConfig () {
|
31
|
+
return new ModelAdminConfig()
|
32
|
+
.setIcon({
|
33
|
+
icon: mdiAlphaMCircle
|
34
|
+
})
|
35
|
+
}
|
36
|
+
|
24
37
|
static icon = {
|
25
38
|
icon: mdiAlphaMCircle,
|
26
39
|
color: 'blue lighten-2'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
export class ModelAdminConfig {
|
2
|
+
icon = null
|
3
|
+
selectedListConfig = null
|
4
|
+
selectableListConfig = null
|
5
|
+
|
6
|
+
setIcon (icon) {
|
7
|
+
this.icon = icon
|
8
|
+
return this
|
9
|
+
}
|
10
|
+
|
11
|
+
setSelectedListConfig (selectedListConfig) {
|
12
|
+
this.selectedListConfig = selectedListConfig
|
13
|
+
return this
|
14
|
+
}
|
15
|
+
|
16
|
+
setSelectableListConfig (selectableListConfig) {
|
17
|
+
this.selectableListConfig = selectableListConfig
|
18
|
+
return this
|
19
|
+
}
|
20
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<template>
|
2
|
+
<div>TEST</div>
|
3
|
+
</template>
|
4
|
+
|
5
|
+
|
6
|
+
<script>
|
7
|
+
import { Component, Vue } from '@a-vue'
|
8
|
+
|
9
|
+
@Component({
|
10
|
+
props: ['name']
|
11
|
+
})
|
12
|
+
export default class Splash extends Vue {
|
13
|
+
}
|
14
|
+
</script>
|
15
|
+
|
16
|
+
|
17
|
+
<style lang="scss" scoped>
|
18
|
+
</style>
|