Skip to content

Commit 87528c3

Browse files
committed
#16 - Field desc from 3 components merged into 1
1 parent c9a7401 commit 87528c3

File tree

4 files changed

+119
-522
lines changed

4 files changed

+119
-522
lines changed

src/utils/crud/components/ChildDetails.vue

Lines changed: 63 additions & 269 deletions
Original file line numberDiff line numberDiff line change
@@ -6,131 +6,12 @@
66
<v-card-text>
77

88
<div v-for="(field, i) in fields" :key="i">
9-
10-
<!-- text field: input / number / decimal / date / time / datetime -->
11-
<v-text-field
12-
hide-details
13-
:rules="fieldRules(field)"
14-
v-if="['input', 'number', 'decimal', 'date', 'time', 'datetime'].includes(field.type)"
15-
:label="field.text"
16-
v-model="field.value"
17-
:disabled="field.disabled"
18-
:type="['number', 'decimal'].includes(field.type) ? 'number' : 'text'"
19-
:step="field.type == 'decimal' ? 0.01 : 1"
20-
min="0"
21-
:mask="['date', 'time', 'datetime'].includes(field.type) ? masks[field.type] : undefined"
22-
:return-masked-value="['date', 'time', 'datetime'].includes(field.type) ? true : false"
23-
></v-text-field>
24-
25-
<!-- text area -->
26-
<v-textarea
27-
hide-details
28-
:rules="fieldRules(field)"
29-
v-else-if="field.type == 'textarea'"
30-
:label="field.text"
31-
v-model="field.value"
32-
:disabled="field.disabled"
33-
></v-textarea>
34-
35-
<!-- file upload -->
36-
<div v-else-if="field.type == 'file'" class="file-container">
37-
<div class="field-label">{{ field.text }}</div>
38-
<v-btn dark class="jbtn-file" :loading="uploadLoaders[field.name]" :class="fileUploadBtn(uploadStatuses[field.name])">
39-
{{ $t('global.details.files.upload') }}
40-
<v-icon dark right>
41-
{{ fileUploadIcon(uploadStatuses[field.name]) }}
42-
</v-icon>
43-
<input
44-
:id="field.name"
45-
type="file"
46-
@change="fileSelected($event, field)"
47-
accept="*"
48-
:multiple="false"
49-
:disabled="field.disabled"
50-
ref="fileInput"
51-
>
52-
</v-btn>
53-
</div>
54-
55-
<!-- select -->
56-
<template v-else-if="field.type == 'select'">
57-
<v-autocomplete
58-
v-if="field.async"
59-
hide-details
60-
:rules="fieldRules(field)"
61-
:loading="searchLoading['search_' + field.name]"
62-
:items="searchData['search_' + field.name]"
63-
v-model="field.value"
64-
:search-input.sync="searchPhrases['search_' + field.name]"
65-
flat
66-
:item-text="field.list.text"
67-
:item-value="field.list.value"
68-
item-disabled="itemDisabled"
69-
:label="field.text"
70-
menu-props="bottom"
71-
:disabled="field.disabled"
72-
></v-autocomplete>
73-
<v-autocomplete
74-
v-else
75-
hide-details
76-
:rules="fieldRules(field)"
77-
:items="field.list.data"
78-
v-model="field.value"
79-
:item-text="field.list.text"
80-
:item-value="field.list.value"
81-
item-disabled="itemDisabled"
82-
:label="field.text"
83-
menu-props="bottom"
84-
:disabled="field.disabled"
85-
></v-autocomplete>
86-
</template>
87-
88-
<!-- date picker -->
89-
<v-menu
90-
v-else-if="field.type == 'datePicker'"
91-
lazy
92-
:close-on-content-click="true"
93-
v-model="field.show"
94-
transition="scale-transition"
95-
offset-y
96-
full-width
97-
:nudge-right="40"
98-
min-width="290px"
99-
:return-value.sync="field.value"
100-
:disabled="field.disabled"
101-
>
102-
<v-text-field
103-
hide-details
104-
slot="activator"
105-
:label="field.text"
106-
v-model="field.value"
107-
prepend-icon="event"
108-
:disabled="field.disabled"
109-
></v-text-field>
110-
<v-date-picker v-model="field.value" no-title scrollable></v-date-picker>
111-
</v-menu>
112-
113-
<!-- rich text editor -->
114-
<template v-else-if="field.type == 'richTextBox'">
115-
<label>{{field.text}}</label>
116-
<vue-editor
117-
id="editor"
118-
v-model="field.value"
119-
:editorOptions="{bounds: '#editor'}"
120-
:disabled="field.disabled"
121-
></vue-editor>
122-
<br>
123-
</template>
124-
125-
<!-- checkbox -->
126-
<v-checkbox v-else-if="field.type == 'checkbox'"
127-
hide-details
128-
color="primary"
129-
v-model="field.value"
130-
:label="field.text"
131-
:disabled="field.disabled"
132-
></v-checkbox>
133-
9+
<field
10+
:field="field"
11+
:fieldValue="field.value"
12+
:reload="reload"
13+
@valueChanged="valueChanged"
14+
></field>
13415
</div>
13516
</v-card-text>
13617
<v-card-actions>
@@ -144,28 +25,26 @@
14425
</v-dialog>
14526
</template>
14627
<script>
147-
import Vue from 'vue'
148-
import { VueEditor } from 'vue2-editor'
28+
import Field from './Field.vue'
14929
import { fieldModifiers } from '@/utils/crud/helpers/functions'
15030
15131
export default {
15232
components: {
153-
VueEditor
33+
Field
15434
},
15535
props: {
15636
details: Object,
15737
fieldsInfo: Array
15838
},
15939
data () {
16040
return {
161-
searchPhrases: {},
162-
searchLoading: {},
163-
searchData: {},
41+
fields: [],
16442
masks: {
16543
date: '####-##-##',
16644
time: '##:##',
16745
datetime: '####-##-## ##:##:##'
16846
},
47+
reload: false,
16948
customFilter (item, queryText, itemText) {
17049
const hasValue = val => (val != null ? val : '')
17150
const text = hasValue(item.name)
@@ -179,79 +58,10 @@ export default {
17958
}
18059
}
18160
},
182-
created () {
183-
for (const field of this.fields) {
184-
if (field.type === 'select') {
185-
const { url } = field
186-
if (field.async) {
187-
this.$set(this.searchPhrases, `search_${field.name}`, '')
188-
this.$set(this.searchLoading, `search_${field.name}`, false)
189-
this.$set(this.searchData, `search_${field.name}`, [])
190-
this.$set(field.list, 'oldSearch', '')
191-
} else {
192-
field.list.data = []
193-
let selectItems
194-
Vue.http.get(url).then((response) => {
195-
const items = response.body
196-
selectItems = items.map((item) => {
197-
const rItem = item
198-
if (typeof field.list.activeColumn !== 'undefined') {
199-
rItem.itemDisabled = parseInt(item[field.list.activeColumn]) === 0
200-
}
201-
if (typeof field.list.complexName !== 'undefined') {
202-
const textArray = field.list.complexName.map((textInfo) => {
203-
const splittedText = textInfo
204-
.split('.')
205-
.reduce((object, property) => object[property] || '', item)
206-
return splittedText
207-
})
208-
rItem.complexName = textArray.join(', ')
209-
}
210-
return rItem
211-
})
212-
if (!field.required) {
213-
const nullElement = {}
214-
nullElement[field.list.value] = ''
215-
nullElement[field.list.text] = '-'
216-
field.list.data = [nullElement, ...selectItems]
217-
} else {
218-
field.list.data = selectItems
219-
}
220-
})
221-
}
222-
}
223-
}
61+
mounted () {
62+
this.setFields()
22463
},
22564
computed: {
226-
fields () {
227-
let filteredFields
228-
filteredFields = this.fieldsInfo.filter(
229-
field => field.details !== false && field.type !== 'divider'
230-
)
231-
const result = filteredFields.map((field) => {
232-
const rField = field
233-
rField.value = this.details.item[field.column]
234-
if (field.type === 'select') {
235-
const defaultVal = field.list.default || 1
236-
rField.value = field.stringId
237-
? this.details.item[field.column]
238-
: parseInt(this.details.item[field.column]) || defaultVal
239-
}
240-
if (field.apiObject) {
241-
if (field.apiObject.useFunctionsInDetails) {
242-
const functions = field.apiObject.functions || []
243-
const availableFunctions = fieldModifiers
244-
245-
for (let i = 0; i < functions.length; i++) {
246-
const functionName = functions[i]
247-
rField.value = availableFunctions[functionName](rField.value)
248-
}
249-
}
250-
}
251-
return rField
252-
})
253-
return result
254-
},
25565
itemData () {
25666
const result = {}
25767
for (const field of this.fields) {
@@ -266,82 +76,66 @@ export default {
26676
input: [v => !!v || self.$t('global.details.rules.required')],
26777
required: v => !!v || self.$t('global.details.rules.required')
26878
}
79+
},
80+
detailsShow () {
81+
return this.details.show
26982
}
27083
},
27184
watch: {
272-
details: {
273-
handler (val) {
274-
if (val.show === true && val.action === 'edit') {
275-
for (const field of this.fields) {
276-
if (field.type === 'select') {
277-
if (field.async) {
278-
field.list.oldSearch = ''
279-
let data
280-
const url = `${field.url}/id/${field.value}`
281-
Vue.http.get(url).then((response) => {
282-
const items = response.body
283-
if (typeof field.list.complexName !== 'undefined') {
284-
data = items.map((item) => {
285-
const rItem = item
286-
const textArray = field.list.complexName.map((textInfo) => {
287-
const splittedText = textInfo
288-
.split('.')
289-
.reduce((object, property) => object[property] || '', item)
290-
return splittedText
291-
})
292-
rItem.complexName = textArray.join(', ')
293-
return rItem
294-
})
295-
} else {
296-
data = items
297-
}
298-
this.$set(this.searchData, `search_${field.name}`, data)
299-
})
300-
}
301-
}
302-
}
85+
detailsShow: function (val) {
86+
if (val) {
87+
this.setFields()
88+
this.reload = true
89+
setTimeout(() => {
90+
this.reload = false
91+
}, 100)
92+
}
93+
}
94+
},
95+
methods: {
96+
setFields () {
97+
let filteredFields
98+
filteredFields = this.fieldsInfo.filter(
99+
field => field.details !== false && field.type !== 'divider'
100+
)
101+
const result = filteredFields.map((field) => {
102+
const rField = field
103+
let show = true
104+
if (this.details.action === 'create') {
105+
show = field.create !== false
303106
}
304-
},
305-
deep: true
306-
},
307-
searchPhrases: {
308-
handler (val) {
309-
for (const field of this.fields) {
107+
rField.show = show
108+
rField.value = this.details.item[field.column]
109+
if (typeof rField.value !== 'undefined') {
310110
if (field.type === 'select') {
311-
if (field.async) {
312-
if (val[`search_${field.name}`] !== undefined) {
313-
const url = `${field.url}/phrase/${val[`search_${field.name}`]}`
314-
this.$set(this.searchLoading, `search_${field.name}`, true)
315-
Vue.http.get(url).then((response) => {
316-
this.$set(this.searchLoading, `search_${field.name}`, false)
317-
const items = response.body
318-
let data
319-
if (typeof field.list.complexName !== 'undefined') {
320-
data = items.map((item) => {
321-
const rItem = item
322-
const textArray = field.list.complexName.map((textInfo) => {
323-
const splittedText = textInfo
324-
.split('.')
325-
.reduce((object, property) => object[property] || '', item)
326-
return splittedText
327-
})
328-
rItem.complexName = textArray.join(', ')
329-
return rItem
330-
})
331-
} else {
332-
data = items
333-
}
334-
this.$set(this.searchData, `search_${field.name}`, data)
335-
})
111+
const defaultVal = field.list.default || 1
112+
rField.value = field.stringId ? this.details.item[field.column] : parseInt(this.details.item[field.column]) || defaultVal
113+
} else if (field.type === 'datePicker') {
114+
rField.value = this.details.item[field.column].substring(0, 10)
115+
} else if (field.type === 'checkbox') {
116+
rField.value = parseInt(this.details.item[field.column]) === 1
117+
}
118+
if (field.apiObject) {
119+
if (field.apiObject.useFunctionsInDetails) {
120+
const functions = field.apiObject.functions || []
121+
const availableFunctions = fieldModifiers
122+
123+
for (let i = 0; i < functions.length; i++) {
124+
const functionName = functions[i]
125+
rField.value = availableFunctions[functionName](rField.value)
336126
}
337127
}
338128
}
129+
} else if (field.type === 'checkbox') {
130+
rField.value = false
339131
}
340-
},
341-
deep: true
342-
}
343-
},
344-
methods: {
132+
return rField
133+
})
134+
this.$set(this, 'fields', result)
135+
},
136+
valueChanged (val, fieldColumn) {
137+
this.$set(this.fields[this.fields.findIndex(el => el.column === fieldColumn)], 'value', val)
138+
},
345139
fieldRules (field) {
346140
const rules = []
347141
const required = field.required !== undefined ? field.required : true

0 commit comments

Comments
 (0)