122 lines
6.9 KiB
JavaScript
122 lines
6.9 KiB
JavaScript
Vue.component('tt-table-crud', {
|
|
//language=Vue
|
|
template: `
|
|
<div>
|
|
<tt-table :fetch-url="window['TT_CONFIG']['TABLE_URL']" :config="tableConfig"
|
|
small ssr ref="table">
|
|
<template v-slot:top-buttons>
|
|
<button type="button" class="btn btn-primary" @click="openCrudModal" v-if="crudConfig.createText !== false">
|
|
<i class="fas fa-plus"></i>
|
|
{{crudConfig.createText || 'Erstellen'}}
|
|
</button>
|
|
|
|
<slot name="table-top-buttons"></slot>
|
|
</template>
|
|
|
|
<template v-for="column in crudConfig.columns"
|
|
:slot="column.key.toLowerCase()"
|
|
slot-scope="{row}">
|
|
<slot v-if="$scopedSlots[column.key.toLowerCase()] && column.modal?.type !== 'select'"
|
|
:name="column.key.toLowerCase()" :row="row">
|
|
|
|
</slot>
|
|
<span v-else-if="column.modal?.type === 'select' && column.modal.items.find(item => item.value + '' === row[column.key] + '')">{{column.modal.items.find(item => item.value == row[column.key]).text}}</span>
|
|
<span v-else-if="column.modal?.type === 'select'"
|
|
:data-all-items="JSON.stringify(column.modal.items)"
|
|
>Select not found for column {{column.key}} and value {{row[column.key]}}</span>
|
|
</template>
|
|
|
|
<template v-slot:actions="{ row }">
|
|
<!-- calculate min width 1 + number of actions * 19 -->
|
|
<div style="display: flex; justify-content: space-around; align-items: center;" :style="{minWidth: (1 + crudConfig?.additionalActions?.length || 0) * 19 + 'px'}">
|
|
<a style="cursor: pointer;" @click="openCrudModal(row)"><i class="far fa-edit text-primary"
|
|
title="Editieren"></i></a>
|
|
|
|
<!-- v-for action crudConfig.additionalActions -> v-if action.condition(row) || true , action.class for icon class, action.title for title, action.key for emitting event -->
|
|
<a v-for="action in crudConfig.additionalActions"
|
|
v-if="!action.condition || action.condition(row)"
|
|
style="cursor: pointer;" @click="$emit(action.key, row)">
|
|
<i :class="action.class" :title="action.title"></i>
|
|
</a>
|
|
</div>
|
|
|
|
</template>
|
|
</tt-table>
|
|
|
|
<tt-modal :show.sync="crudModal"
|
|
:title="crudConfig.createText || 'Erstellen'"
|
|
@submit="submitCrudModal"
|
|
@delete="deleteCrudModal"
|
|
@close="resetCrudModalData">
|
|
|
|
<template v-for="column in modalConfig.headers">
|
|
<!-- @formatter:off -->
|
|
<tt-input v-if="column.type === 'text'" v-model="crudModalData[column.key]" :label="column.text" sm row/>
|
|
<tt-input v-if="column.type === 'number'" v-model="crudModalData[column.key]" :label="column.text" type="number" sm row/>
|
|
<tt-textarea v-if="column.type === 'textarea'" v-model="crudModalData[column.key]" :label="column.text" sm row/>
|
|
<tt-select v-if="column.type === 'select'" v-model="crudModalData[column.key]" :label="column.text" :options="column.items" sm row/>
|
|
<tt-autocomplete v-if="column.type === 'autocomplete'" v-model="crudModalData[column.key]" :label="column.text" :items="column.items" sm row/>
|
|
<tt-date-picker v-if="column.type === 'datepicker'" v-model="crudModalData[column.key]" :label="column.text" sm row/>
|
|
<tt-icon-select v-if="column.type === 'icon-select'" v-model="crudModalData[column.key]" :label="column.text" sm row/>
|
|
<tt-checkbox v-if="column.type === 'checkbox'" v-model="crudModalData[column.key]" :label="column.text" sm row/>
|
|
<!-- @formatter:on -->
|
|
</template>
|
|
|
|
</tt-modal>
|
|
</div>
|
|
`, props: {
|
|
crudConfig: {type: Object, required: false, default: () => (window['TT_CONFIG']['CRUD_CONFIG'])}
|
|
}, data() {
|
|
return {
|
|
crudModal: false, crudModalData: {}, window: window
|
|
|
|
}
|
|
}, methods: {
|
|
openCrudModal(row = null) {
|
|
this.crudModalData = row ? JSON.parse(JSON.stringify(row)) : {};
|
|
this.crudModal = true;
|
|
}, resetCrudModalData() {
|
|
this.crudModalData = {};
|
|
this.crudModal = false;
|
|
}, async submitCrudModal() {
|
|
delete this.crudModalData.isTrusted;
|
|
const response = await axios.post(this.crudModalData.id ? window['TT_CONFIG']['UPDATE_URL'] : window['TT_CONFIG']['CREATE_URL'],
|
|
this.crudModalData);
|
|
if (response.data.success) {
|
|
this.$refs.table.refreshTable();
|
|
this.resetCrudModalData();
|
|
this.window.notify('success', response.data.message || 'Erfolgreich gespeichert');
|
|
} else {
|
|
this.window.notify('error',
|
|
response.data.errors ? Object.values(response.data.errors).join('<br>') : response.data.message ||
|
|
'Ein Fehler ist aufgetreten');
|
|
}
|
|
}, async deleteCrudModal() {
|
|
|
|
const response = await axios.post(window['TT_CONFIG']['DELETE_URL'], {id: this.crudModalData.id});
|
|
if (response.data.success) {
|
|
this.$refs.table.refreshTable();
|
|
this.resetCrudModalData();
|
|
}
|
|
this.window.notify(response.data.success ? 'success' : 'error', response.data.message);
|
|
}
|
|
}, computed: {
|
|
tableConfig() {
|
|
return {
|
|
key: this.crudConfig.key,
|
|
tableHeader: this.crudConfig.tableHeader,
|
|
headers: this.crudConfig.columns.filter(column => column.table !== false).map(column => {
|
|
return {text: column.text, key: column.key, ...column.table, filterOptions: column?.modal?.items}
|
|
})
|
|
}
|
|
}, modalConfig() {
|
|
return {
|
|
key: this.crudConfig.key,
|
|
headers: this.crudConfig.columns.filter(column => column.modal !== false).map(column => {
|
|
const type = column.modal?.type || "text"
|
|
return {text: column.text, key: column.key, type, ...column.modal}
|
|
}),
|
|
}
|
|
}
|
|
}
|
|
}) |