Merge branch 'warehouse-order-improvements' into 'master'
Updated WarehouseOrder and WarehouseOrderRequest See merge request fronk/thetool!1075
This commit is contained in:
@@ -79,6 +79,7 @@ Vue.component('tt-autocomplete', {
|
||||
sm: {type: Boolean, default: true},
|
||||
row: {type: Boolean, default: false},
|
||||
returnText: {type: Boolean, default: false},
|
||||
emitDisplayValue: {type: Boolean, default: false},
|
||||
}, data() {
|
||||
return {
|
||||
window,
|
||||
@@ -97,6 +98,7 @@ Vue.component('tt-autocomplete', {
|
||||
},
|
||||
methods: {
|
||||
setOldDisplayValue(newValue, oldValue) {
|
||||
if (this.emitDisplayValue && newValue) this.$emit('displayValue', newValue);
|
||||
this.oldDisplayValue = oldValue;
|
||||
},
|
||||
async updateDisplayValue(newValue, oldValue) {
|
||||
|
||||
@@ -25,225 +25,209 @@ Vue.component('tt-resolver', {
|
||||
}
|
||||
})
|
||||
|
||||
Vue.component('tt-positions-manager', {
|
||||
props: {
|
||||
value: {type: Array, required: false},
|
||||
config: {type: Object, required: true},
|
||||
groupMode: {type: Boolean, default: false},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
window: window,
|
||||
positions: this.value,
|
||||
formData: {},
|
||||
groupName: '',
|
||||
selectedIndex: null,
|
||||
resolvingFields: {},
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="positions-manager">
|
||||
<div class="form-container">
|
||||
<template v-for="(field, key) in config.fields">
|
||||
<slot :name="key" v-bind:field="field" v-bind:value="formData[key]">
|
||||
<tt-input
|
||||
v-if="field.type === 'input'"
|
||||
:label="field.label"
|
||||
v-model="formData[key]"
|
||||
@input="$emit('updateField-' + key, $event)"
|
||||
sm
|
||||
:type="field.inputType || 'text'"
|
||||
/>
|
||||
<tt-autocomplete
|
||||
v-else-if="field.type === 'autocomplete'"
|
||||
:label="field.label"
|
||||
v-model="formData[key]"
|
||||
@input="$emit('updateField-' + key, $event); window.console.log($event)"
|
||||
:api-url="window.TT_CONFIG['BASE_PATH'] + field.apiUrl"
|
||||
sm
|
||||
/>
|
||||
<tt-textarea
|
||||
v-else-if="field.type === 'textarea'"
|
||||
:label="field.label"
|
||||
v-model="formData[key]"
|
||||
@input="$emit('updateField-' + key, $event)"
|
||||
sm
|
||||
/>
|
||||
<tt-checkbox
|
||||
v-else-if="field.type === 'checkbox'"
|
||||
:label="field.label"
|
||||
@input="$emit('updateField-' + key, $event)"
|
||||
sm
|
||||
v-model="formData[key]"
|
||||
/>
|
||||
<tt-select
|
||||
v-else-if="field.type === 'select'"
|
||||
:label="field.label"
|
||||
@input="$emit('updateField-' + key, $event); window.console.log('updatefield-' + key, $event)"
|
||||
sm
|
||||
v-model="formData[key]"
|
||||
:options="field.options"
|
||||
/>
|
||||
</slot>
|
||||
</template>
|
||||
<div class="button-wrapper">
|
||||
<tt-button @click="saveEntry" sm :additional-class="selectedIndex === null ? 'btn-primary' : 'btn-success'"
|
||||
:text="selectedIndex === null ? 'Hinzufügen' : 'Aktualisieren'"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-container" v-if="groupMode">
|
||||
<tt-input label="Gruppenname" v-model="groupName" sm/>
|
||||
<tt-button @click="addGroup" sm text="Gruppe hinzufügen" additional-class="btn-primary"/>
|
||||
</div>
|
||||
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th v-for="field in config.fields">{{ field.label }}</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template v-if="groupMode">
|
||||
<template v-for="(groupPositions, groupName) in groupedPositions">
|
||||
<tr>
|
||||
<td colspan="100%">
|
||||
<h4 style="text-align: center;">{{ groupName }}</h4>
|
||||
</td>
|
||||
<tr v-for="(position, index) in groupPositions" :key="groupName + index">
|
||||
<td v-for="(field, key) in config.fields">
|
||||
<tt-resolver v-if="field.customFieldReference" :reference="field.customFieldReference" :value="position[key]"/>
|
||||
<span v-else>{{ formatFieldValue(position[key], field) }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<select v-model="position._group" @change="$set(position, '_group', $event.target.value)">
|
||||
<option v-for="group in allGroups" :value="group">{{ group }}</option>
|
||||
</select>
|
||||
<button @click="editEntry(index)" class="btn btn-sm btn-primary">Editieren</button>
|
||||
<button @click="deleteEntry(index)" class="btn btn-sm btn-danger">Löschen</button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<tr v-for="(position, index) in positions" :key="index">
|
||||
<td v-for="(field, key) in config.fields">
|
||||
<template v-if="resolvingFields[index + key] === true">
|
||||
<div class="d-flex justify-content-center align-items-center">
|
||||
<div class="spinner-border spinner-border-sm text-primary" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<span v-else-if="resolvingFields[index + key]">{{ resolvingFields[index + key] }}</span>
|
||||
<span v-else>{{ formatFieldValue(position[key], field) }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<select v-model="position._group" @change="position._group = $event">
|
||||
<option v-for="group in allGroups" :value="group">{{ group }}</option>
|
||||
</select>
|
||||
<button @click="editEntry(index)" class="btn btn-sm btn-primary">Editieren</button>
|
||||
<button @click="deleteEntry(index)" class="btn btn-sm btn-danger">Löschen</button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
`,
|
||||
methods: {
|
||||
updateField(key, value) {
|
||||
this.$set(this.formData, key, value);
|
||||
Vue.component('tt-positions-manager',
|
||||
{
|
||||
props: {
|
||||
value: {type: [Array, String], required: false},
|
||||
config: {type: Object, required: true},
|
||||
groupMode: {type: Boolean, default: false},
|
||||
},
|
||||
async saveEntry() {
|
||||
if (this.config.validateForm && !await this.config.validateForm(this.formData)) return;
|
||||
|
||||
if (this.selectedIndex === null) this.positions.push(this.formData);
|
||||
else this.$set(this.positions, this.selectedIndex, this.formData);
|
||||
|
||||
if (this.config.customOrdering) {
|
||||
this.positions.sort((a, b) => a[this.config.customOrdering] - b[this.config.customOrdering]);
|
||||
data() {
|
||||
return {
|
||||
window: window,
|
||||
positions: this.value,
|
||||
formData: {},
|
||||
groupName: '',
|
||||
selectedIndex: null,
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="positions-manager">
|
||||
<template v-if="config['header']">
|
||||
<h4 class="text-center">{{ config["header"] }}</h4>
|
||||
</template>
|
||||
<div class="form-container">
|
||||
<template v-for="(field, key) in config.fields">
|
||||
<slot :name="key" v-bind:field="field" v-bind:value="formData[key]">
|
||||
<tt-input
|
||||
v-if="field.type === 'input'"
|
||||
:label="field.label"
|
||||
v-model="formData[key]"
|
||||
@input="$emit('updateField-' + key, $event)"
|
||||
sm
|
||||
:type="field.inputType || 'text'"
|
||||
/>
|
||||
<tt-autocomplete
|
||||
v-else-if="field.type === 'autocomplete'"
|
||||
:label="field.label"
|
||||
:emit-display-value="field.emitDisplayValue || false"
|
||||
v-model="formData[key]"
|
||||
@input="delete formData[key + '_text']; $emit('updateField-' + key, $event)"
|
||||
@displayValue="delete formData[key];formData[key + '_text'] = $event"
|
||||
:api-url="window.TT_CONFIG['BASE_PATH'] + field.apiUrl"
|
||||
sm
|
||||
/>
|
||||
<tt-textarea
|
||||
v-else-if="field.type === 'textarea'"
|
||||
:label="field.label"
|
||||
v-model="formData[key]"
|
||||
@input="$emit('updateField-' + key, $event)"
|
||||
sm
|
||||
/>
|
||||
<tt-checkbox
|
||||
v-else-if="field.type === 'checkbox'"
|
||||
:label="field.label"
|
||||
@input="$emit('updateField-' + key, $event)"
|
||||
sm
|
||||
v-model="formData[key]"
|
||||
/>
|
||||
<tt-select
|
||||
v-else-if="field.type === 'select'"
|
||||
:label="field.label"
|
||||
@input="$emit('updateField-' + key, $event)"
|
||||
sm
|
||||
v-model="formData[key]"
|
||||
:options="field.options"
|
||||
/>
|
||||
</slot>
|
||||
</template>
|
||||
<div class="button-wrapper">
|
||||
<tt-button @click="saveEntry" sm :additional-class="selectedIndex === null ? 'btn-primary' : 'btn-success'"
|
||||
:text="selectedIndex === null ? 'Hinzufügen' : 'Aktualisieren'"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
this.$emit('input', this.positions);
|
||||
this.resetForm();
|
||||
},
|
||||
addGroup() {
|
||||
this.positions.push({_group: this.groupName});
|
||||
this.groupName = '';
|
||||
},
|
||||
editEntry(index) {
|
||||
this.selectedIndex = index;
|
||||
this.formData = {...this.positions[index]};
|
||||
},
|
||||
deleteEntry(index) {
|
||||
this.positions.splice(index, 1);
|
||||
this.$emit('input', this.positions);
|
||||
},
|
||||
resetForm() {
|
||||
this.formData = {};
|
||||
this.selectedIndex = null;
|
||||
},
|
||||
formatFieldValue(value, field) {
|
||||
if (field.formatter) return field.formatter(value);
|
||||
return value;
|
||||
},
|
||||
async resolveFields() {
|
||||
for (let i = 0; i < this.positions.length; i++) {
|
||||
for (let key in this.config.fields) {
|
||||
if (this.config.fields[key].customFieldResolver) {
|
||||
this.$set(this.resolvingFields, i + key, true);
|
||||
const textValue = await this.config.fields[key].customFieldResolver(this.positions[i][key]);
|
||||
this.$set(this.resolvingFields, i + key, textValue);
|
||||
} else if (this.config.fields[key].customFieldReference && this.positions[i][key]) {
|
||||
this.$set(this.resolvingFields, i + key, true);
|
||||
if (this.config.fields[key].customFieldReference) {
|
||||
const entry = await axios.get(window.TT_CONFIG['BASE_PATH'] +
|
||||
'/' +
|
||||
this.config.fields[key].customFieldReference +
|
||||
'/getById?id=' +
|
||||
this.positions[i][key]);
|
||||
const textValue = entry.data.name ?? entry.data.title ?? entry.data.text ?? '[E] Key not found';
|
||||
console.log(textValue);
|
||||
this.$set(this.resolvingFields, i + key, textValue);
|
||||
} else this.$set(this.resolvingFields, i + key, '');
|
||||
|
||||
<div class="form-container" v-if="groupMode">
|
||||
<tt-input label="Gruppenname" v-model="groupName" sm/>
|
||||
<tt-button @click="addGroup" sm text="Gruppe hinzufügen" additional-class="btn-primary"/>
|
||||
</div>
|
||||
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th v-for="field in config['fields']">{{ field.label }}</th>
|
||||
<th style="text-align: right;padding-right: 24px">Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<template v-for="(group, groupName) in positionsToRender">
|
||||
<tr v-if="groupMode">
|
||||
<td colspan="100%">
|
||||
<h4 style="text-align: center;">{{ groupName }}</h4>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-for="(position, index) in group" :key="groupMode ? groupName + index : index">
|
||||
<td v-for="(field, key) in config.fields">
|
||||
<tt-resolver
|
||||
v-if="field.customFieldReference && position[key]"
|
||||
:reference="field.customFieldReference"
|
||||
:value="position[key]"
|
||||
/>
|
||||
<span v-else>{{ formatFieldValue(position[key] ?? position[key + '_text'], field) }}</span>
|
||||
</td>
|
||||
<td class="d-flex justify-content-end">
|
||||
<select v-if="groupMode" v-model="position._group" @change="$set(position, '_group', $event.target.value)">
|
||||
<option v-for="group in allGroups" :value="group">{{ group }}</option>
|
||||
</select>
|
||||
<tt-button @click="editEntry(index)" sm additional-class="btn-primary" icon="fa fa-edit"/>
|
||||
<tt-button @click="deleteEntry(index)" sm additional-class="btn-danger" icon="fa fa-trash"/>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
`,
|
||||
methods: {
|
||||
updateField(key, value) {
|
||||
this.$set(this.formData, key, value);
|
||||
},
|
||||
defaultValidateForm(formData) {
|
||||
console.log(this.config["validateFormOptions"], formData);
|
||||
for (const field of this.config["validateFormOptions"]) {
|
||||
if (!(formData[field.key] || formData[field.key + '_text'])) {
|
||||
window.notify('error', field.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
async saveEntry() {
|
||||
if (this.config.hasOwnProperty('validateFormOptions') && !this.defaultValidateForm(this.formData)) return;
|
||||
else if (this.config.validateForm && !await this.config.validateForm(this.formData)) return;
|
||||
|
||||
if (this.selectedIndex === null) this.positions.push(this.formData);
|
||||
else this.$set(this.positions, this.selectedIndex, this.formData);
|
||||
|
||||
if (this.config.customOrdering) {
|
||||
this.positions.sort((a, b) => a[this.config.customOrdering] - b[this.config.customOrdering]);
|
||||
}
|
||||
|
||||
this.$emit('input', this.positions);
|
||||
this.resetForm();
|
||||
},
|
||||
addGroup() {
|
||||
this.positions.push({_group: this.groupName});
|
||||
this.groupName = '';
|
||||
},
|
||||
editEntry(index) {
|
||||
this.selectedIndex = index;
|
||||
this.formData = {...this.positions[index]};
|
||||
},
|
||||
deleteEntry(index) {
|
||||
this.positions.splice(index, 1);
|
||||
this.$emit('input', this.positions);
|
||||
},
|
||||
resetForm() {
|
||||
this.formData = {};
|
||||
this.selectedIndex = null;
|
||||
},
|
||||
formatFieldValue(value, field) {
|
||||
if (field.formatter) return field.formatter(value);
|
||||
return value;
|
||||
},
|
||||
},
|
||||
//TODO: cleanup
|
||||
created() {
|
||||
if (this.config["customMethods"]) Object.assign(this, this.config.customMethods);
|
||||
if (!this.positions) this.positions = [];
|
||||
if (typeof this.positions === 'string') {
|
||||
try {
|
||||
this.positions = JSON.parse(this.positions);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
this.positions = [];
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
groupedPositions() {
|
||||
const groups = {};
|
||||
for (const position of this.positions) {
|
||||
const group = position._group ?? 'Keine Gruppe';
|
||||
if (!groups[group]) groups[group] = [];
|
||||
if (Object.keys(position).length !== 1) groups[group].push(position);
|
||||
}
|
||||
return groups;
|
||||
},
|
||||
positionsToRender() {
|
||||
return this.groupMode ? this.groupedPositions : { '': this.positions };
|
||||
},
|
||||
allGroups() {
|
||||
return Object.keys(this.groupedPositions);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler() {
|
||||
this.positions = this.value;
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.config.customMethods) Object.assign(this, this.config.customMethods);
|
||||
},
|
||||
computed: {
|
||||
groupedPositions() {
|
||||
const groups = {};
|
||||
for (const position of this.positions) {
|
||||
const group = position._group ?? 'Keine Gruppe';
|
||||
if (!groups[group]) groups[group] = [];
|
||||
if (Object.keys(position).length !== 1) groups[group].push(position);
|
||||
}
|
||||
return groups;
|
||||
},
|
||||
allGroups() {
|
||||
return Object.keys(this.groupedPositions);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
positions: {
|
||||
handler() {
|
||||
this.resolveFields().then();
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
value: {
|
||||
handler() {
|
||||
this.positions = this.value;
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user