Files
livetrail/src/components/admin.vue
T
2026-05-03 18:31:53 +02:00

232 lines
6.9 KiB
Vue

<script>
import SpotIcon from '@components/spotIcon';
import SpotButton from '@components/spotButton';
import AdminInput from '@components/adminInput';
export default {
components: {
SpotIcon,
SpotButton,
AdminInput
},
inject: ['api', 'lang'],
data() {
return {
elems: {},
feedbacks: [],
saveTimer: null
};
},
beforeUnmount() {
if(this.saveTimer) clearTimeout(this.saveTimer);
},
mounted() {
this.setProjects();
},
methods: {
l(id) {
return this.lang.get(id);
},
addFeedback(sType, sMsg, asContext = {}) {
delete asContext.a;
delete asContext.t;
sMsg += ' (';
for(const [sKey, sElem] of Object.entries(asContext)) {
sMsg += sKey+'='+sElem+' / ' ;
}
sMsg = sMsg.slice(0, -3)+')';
this.feedbacks.push({type:sType, msg:sMsg});
},
async setProjects() {
let aoElemTypes = await this.api.get('admin_get');
for(const [sType, aoElems] of Object.entries(aoElemTypes)) {
this.elems[sType] = {};
for(const [iKey, oElem] of Object.entries(aoElems)) {
oElem.type = sType;
this.elems[sType][oElem.id] = oElem;
}
}
},
createElem(sType) {
this.api.get('admin_create', {type: sType})
.then((aoNewElemTypes) => {
for(const [sType, aoNewElems] of Object.entries(aoNewElemTypes)) {
for(const [iKey, oNewElem] of Object.entries(aoNewElems)) {
oNewElem.type = sType;
this.elems[sType][oNewElem.id] = oNewElem;
this.addFeedback('success', this.l('admin.create_success'), {'create':sType});
}
}
})
.catch((sMsg) => {this.addFeedback('error', sMsg, {'create':sType});});
},
deleteElem(oElem) {
const asInputs = {
type: oElem.type,
id: oElem.id
};
this.api.get('admin_delete', asInputs)
.then((asData) => {
delete this.elems[asInputs.type][asInputs.id];
this.addFeedback('success', this.l('admin.delete_success'), asInputs);
})
.catch((sError) => {
this.addFeedback('error', sError, asInputs);
});
},
updateElem(oElem, oEvent) {
if(this.saveTimer) clearTimeout(this.saveTimer);
let sOldVal = this.elems[oElem.type][oElem.id][oEvent.target.name];
let sNewVal = oEvent.target.value;
if(sOldVal != sNewVal) {
let asInputs = {
type: oElem.type,
id: oElem.id,
field: oEvent.target.name,
value: sNewVal
};
this.api.get('admin_set', asInputs)
.then((asData) => {
this.elems[oElem.type][oElem.id][oEvent.target.name] = sNewVal;
this.addFeedback('success', this.l('admin.save_success'), asInputs);
})
.catch((sError) => {
oEvent.target.value = sOldVal;
this.addFeedback('error', sError, asInputs);
});
}
},
queue(oElem, oEvent) {
if(this.saveTimer) clearTimeout(this.saveTimer);
this.saveTimer = setTimeout(() => {this.updateElem(oElem, oEvent);}, 2000);
},
updateProject() {
this.api.get('update_project')
.then((asData, sMsg) => {this.addFeedback('success', sMsg, {'update':'project'});})
.catch((sMsg) => {this.addFeedback('error', sMsg, {'update':'project'});});
}
}
}
</script>
<template>
<div id="admin">
<a name="back" class="button" href="#project"><SpotIcon :icon="'back'" :text="l('action.back')" /></a>
<h1>{{ l('project.plural') }}</h1>
<div>
<table>
<thead>
<tr>
<th>{{ l('project.id') }}</th>
<th>{{ l('project.single') }}</th>
<th>{{ l('project.mode') }}</th>
<th>{{ l('project.code_name') }}</th>
<th>{{ l('project.start') }}</th>
<th>{{ l('project.end') }}</th>
<th>{{ l('action.delete') }}</th>
</tr>
</thead>
<tbody>
<tr v-for="project in elems.project">
<td>{{ project.id }}</td>
<td><AdminInput :type="'text'" :name="'name'" :elem="project" /></td>
<td>{{ project.mode }}</td>
<td><AdminInput :type="'text'" :name="'codename'" :elem="project" /></td>
<td><AdminInput :type="'date'" :name="'active_from'" :elem="project" /></td>
<td><AdminInput :type="'date'" :name="'active_to'" :elem="project" /></td>
<td><SpotButton :icon="'close'" iconSize="lg" @click="deleteElem(project)" /></td>
</tr>
</tbody>
</table>
<SpotButton :classes="'new'" :text="l('project.new')" :icon="'new'" @click="createElem('project')" />
</div>
<h1>{{ l('feed.plural') }}</h1>
<div>
<table>
<thead>
<tr>
<th>{{ l('feed.id') }}</th>
<th>{{ l('feed.ref_id') }}</th>
<th>{{ l('spot.id') }}</th>
<th>{{ l('project.id') }}</th>
<th>{{ l('feed.name') }}</th>
<th>{{ l('feed.status') }}</th>
<th>{{ l('feed.last_update') }}</th>
<th>{{ l('action.delete') }}</th>
</tr>
</thead>
<tbody>
<tr v-for="feed in elems.feed">
<td>{{ feed.id }}</td>
<td><AdminInput :type="'text'" :name="'ref_feed_id'" :elem="feed" /></td>
<td><AdminInput :type="'number'" :name="'id_spot'" :elem="feed" /></td>
<td><AdminInput :type="'number'" :name="'id_project'" :elem="feed" /></td>
<td>{{ feed.name }}</td>
<td>{{ feed.status }}</td>
<td>{{ feed.last_update }}</td>
<td><SpotButton :icon="'close'" iconSize="lg" @click="deleteElem(feed)" /></td>
</tr>
</tbody>
</table>
<SpotButton :classes="'new'" :text="l('feed.new')" :icon="'new'" @click="createElem('feed')" />
</div>
<h1>{{ l('spot.plural') }}</h1>
<div>
<table>
<thead>
<tr>
<th>{{ l('spot.id') }}</th>
<th>{{ l('spot.ref_id') }}</th>
<th>{{ l('spot.name') }}</th>
<th>{{ l('spot.model') }}</th>
</tr>
</thead>
<tbody>
<tr v-for="spot in elems.spot">
<td>{{ spot.id }}</td>
<td>{{ spot.ref_spot_id }}</td>
<td>{{ spot.name }}</td>
<td>{{ spot.model }}</td>
</tr>
</tbody>
</table>
</div>
<h1>{{ l('user.active') }}</h1>
<div>
<table>
<thead>
<tr>
<th>{{ l('user.id') }}</th>
<th>{{ l('user.name') }}</th>
<th>{{ l('user.language') }}</th>
<th>{{ l('time.zone') }}</th>
<th>{{ l('user.clearance') }}</th>
<th>{{ l('action.delete') }}</th>
</tr>
</thead>
<tbody>
<tr v-for="user in elems.user">
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.language }}</td>
<td>{{ user.timezone }}</td>
<td><AdminInput :type="'number'" :name="'clearance'" :elem="user" /></td>
<td><SpotButton :icon="'close'" iconSize="lg" @click="deleteElem(user)" /></td>
</tr>
</tbody>
</table>
</div>
<h1>{{ l('admin.toolbox') }}</h1>
<div id="toolbox">
<SpotButton :classes="'refresh'" :text="l('project.update_messages')" :icon="'refresh'" @click="updateProject" />
</div>
<div id="feedback" class="feedback">
<p v-for="feedback in feedbacks" :class="feedback.type">{{ feedback.msg }}</p>
</div>
</div>
</template>