Workorder mph/improve
This commit is contained in:
@@ -71,6 +71,10 @@ const RadiusRouterManager = {
|
||||
<i class="fa-duotone fa-sitemap"></i>
|
||||
<span>Netzwerkstruktur</span>
|
||||
</button>
|
||||
<button class="ghost-btn action-btn" @click="openEventLog" :disabled="routerLoading || routerActionLoading || speedtestLoading">
|
||||
<i class="fa-duotone fa-list-timeline"></i>
|
||||
<span>Ereignisprotokoll</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -157,6 +161,12 @@ const RadiusRouterManager = {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 pt-3" style="border-top: 1px solid var(--border);">
|
||||
<button class="ghost-btn" @click="runRemoteAccess(true)" :disabled="remoteAccessLoading">
|
||||
<i class="fa-duotone fa-rotate"></i>
|
||||
<span>Zugangsdaten neu erstellen</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="table-placeholder" style="height: 200px;">Ein Fehler ist aufgetreten.</div>
|
||||
</tt-dialog>
|
||||
@@ -173,6 +183,34 @@ const RadiusRouterManager = {
|
||||
<div v-else class="table-placeholder" style="min-height: 300px;">Keine Daten verfügbar.</div>
|
||||
</tt-dialog>
|
||||
|
||||
<!-- Event Log Modal -->
|
||||
<tt-dialog :show="showEventLogModal" title="Ereignisprotokoll" @close="showEventLogModal = false" size="wide">
|
||||
<tt-loading-indicator v-if="eventLogLoading" text="Lade Ereignisprotokoll..." style="min-height: 300px;" />
|
||||
<div v-else-if="eventLogData && eventLogData.length > 0">
|
||||
<div class="table-wrap" style="max-height: 500px; overflow-y: auto;">
|
||||
<table class="tt-table compact">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 100px;">Datum</th>
|
||||
<th style="width: 80px;">Uhrzeit</th>
|
||||
<th style="width: 120px;">Gruppe</th>
|
||||
<th>Nachricht</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(event, idx) in eventLogData" :key="idx">
|
||||
<td class="mono small">{{ event.date }}</td>
|
||||
<td class="mono small">{{ event.time }}</td>
|
||||
<td class="small">{{ event.group }}</td>
|
||||
<td class="small">{{ event.msg }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="table-placeholder" style="min-height: 300px;">Keine Ereignisse verfügbar.</div>
|
||||
</tt-dialog>
|
||||
|
||||
</div>
|
||||
`,
|
||||
data: () => ({
|
||||
@@ -197,7 +235,11 @@ const RadiusRouterManager = {
|
||||
|
||||
showNetworkStructureModal: false,
|
||||
networkStructureLoading: false,
|
||||
rootDevice: null
|
||||
rootDevice: null,
|
||||
|
||||
showEventLogModal: false,
|
||||
eventLogLoading: false,
|
||||
eventLogData: null
|
||||
}),
|
||||
watch: {
|
||||
show: {
|
||||
@@ -353,20 +395,24 @@ const RadiusRouterManager = {
|
||||
};
|
||||
poll();
|
||||
},
|
||||
async runRemoteAccess() {
|
||||
async runRemoteAccess(forceRecreate = false) {
|
||||
if (!this.routerDevice || !this.routerDevice.deviceId) return;
|
||||
this.showRemoteAccessModal = true;
|
||||
this.remoteAccessLoading = true;
|
||||
this.remoteAccessStep = 'Konfiguriere Zugriff...';
|
||||
this.remoteAccessStep = forceRecreate ? 'Erstelle neue Zugangsdaten...' : 'Konfiguriere Zugriff...';
|
||||
this.remoteAccessResult = null;
|
||||
|
||||
try {
|
||||
const { data } = await axios.post(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsRemoteAccess`, {
|
||||
deviceId: this.routerDevice.deviceId
|
||||
deviceId: this.routerDevice.deviceId,
|
||||
forceRecreate: forceRecreate
|
||||
});
|
||||
|
||||
if (data.success) {
|
||||
this.remoteAccessResult = data;
|
||||
if (forceRecreate) {
|
||||
window.notify('success', 'Neue Zugangsdaten erstellt');
|
||||
}
|
||||
} else {
|
||||
throw new Error(data.message || "Unbekannter Fehler");
|
||||
}
|
||||
@@ -396,6 +442,29 @@ const RadiusRouterManager = {
|
||||
} finally {
|
||||
this.networkStructureLoading = false;
|
||||
}
|
||||
},
|
||||
async openEventLog() {
|
||||
if (!this.routerDevice || !this.routerDevice.deviceId) return;
|
||||
this.showEventLogModal = true;
|
||||
this.eventLogLoading = true;
|
||||
this.eventLogData = null;
|
||||
|
||||
try {
|
||||
const { data } = await axios.post(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsEventLog`, {
|
||||
deviceId: this.routerDevice.deviceId
|
||||
});
|
||||
|
||||
if (data.success && data.events) {
|
||||
this.eventLogData = data.events;
|
||||
} else {
|
||||
throw new Error(data.message || "Keine Ereignisse gefunden");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
window.notify('error', error.response?.data?.message || 'Fehler beim Laden des Ereignisprotokolls');
|
||||
} finally {
|
||||
this.eventLogLoading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -150,7 +150,7 @@ const RadiusUsers = {
|
||||
data-tooltip-align="left">
|
||||
<i class="fa-duotone fa-chart-line"></i>
|
||||
</button>
|
||||
<button v-if="window.TT_CONFIG.ACS_ENABLED" class="ghost-btn" @click="openRouterManager(item)"
|
||||
<button class="ghost-btn" @click="openRouterManager(item)"
|
||||
data-tooltip="Router Management" data-tooltip-align="left">
|
||||
<i class="fa-duotone fa-router"></i>
|
||||
</button>
|
||||
|
||||
@@ -4,10 +4,7 @@ Vue.component('workorder-mph-admin', {
|
||||
<tt-card>
|
||||
<tt-table-crud ref="table" :crud-config="crudConfig">
|
||||
<template v-slot:hausnummerinfo="{ row }">
|
||||
<div class="small">
|
||||
<div><strong>Adresse:</strong> {{ row.street }} {{ row.hausnummer }}<template v-if="row.stiege">/{{ row.stiege }}</template></div>
|
||||
<div><strong>Ort:</strong> {{ row.plz }} {{ row.city }}</div>
|
||||
</div>
|
||||
<span class="small">{{ row.street }} {{ row.hausnummer }}<template v-if="row.stiege">/{{ row.stiege }}</template>, {{ row.plz }} {{ row.city }}</span>
|
||||
</template>
|
||||
|
||||
<template v-slot:status="{ row }">
|
||||
@@ -81,7 +78,7 @@ Vue.component('workorder-mph-admin', {
|
||||
<!-- Left Column (1/4): Docs Checkbox, Journal, Review -->
|
||||
<div class="col-xl-3 col-lg-4">
|
||||
<div class="mph-details-stack">
|
||||
<checkbox-documentation :workorder-mph-id="parseInt(row.id)" :is-admin="true"/>
|
||||
<checkbox-documentation :workorder-mph-id="parseInt(row.id)" :is-admin="true" @refresh="refresh"/>
|
||||
<workorder-mph-journal :journals="journals" :workorder-mph-id="row.id" :is-admin="true" @refresh="refresh"/>
|
||||
<workorder-mph-admin-review :docs="docs" :workorder-mph-id="row.id" @refresh="refresh"/>
|
||||
</div>
|
||||
@@ -89,7 +86,7 @@ Vue.component('workorder-mph-admin', {
|
||||
<!-- Right Column (3/4): Wohneinheiten, Documents -->
|
||||
<div class="col-xl-9 col-lg-8">
|
||||
<div class="mph-details-stack">
|
||||
<wohneinheit-status-manager :workorder-mph-id="parseInt(row.id)" :is-admin="true"/>
|
||||
<wohneinheit-status-manager :workorder-mph-id="parseInt(row.id)" :is-admin="true" @refresh="refresh"/>
|
||||
<workorder-mph-documents :docs="docs" :workorder-mph-id="row.id" :is-admin="true" @refresh="refresh"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -433,6 +433,25 @@
|
||||
margin: -12px;
|
||||
}
|
||||
|
||||
/* Custom Scrollbar for Journal */
|
||||
.mph-journal-list::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.mph-journal-list::-webkit-scrollbar-track {
|
||||
background: #f1f3f5;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.mph-journal-list::-webkit-scrollbar-thumb {
|
||||
background: #adb5bd;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.mph-journal-list::-webkit-scrollbar-thumb:hover {
|
||||
background: #868e96;
|
||||
}
|
||||
|
||||
.mph-journal-item {
|
||||
padding: 8px 12px;
|
||||
border-bottom: 1px solid #f1f3f5;
|
||||
|
||||
@@ -74,7 +74,7 @@ Vue.component('wohneinheit-status-manager', {
|
||||
<span><i class="fas fa-building"></i> Wohneinheiten</span>
|
||||
<div>
|
||||
<span v-if="loading" class="mr-2"><i class="fas fa-spinner fa-spin text-muted"></i></span>
|
||||
<a v-if="hausnummerId" :href="'/AddressDB/view/?id=' + hausnummerId" target="_blank" class="small text-muted">
|
||||
<a v-if="isAdmin && hausnummerId" :href="'/AddressDB/view/?id=' + hausnummerId" target="_blank" class="small text-muted">
|
||||
<i class="fas fa-external-link-alt mr-1"></i>AddressDB #{{ hausnummerId }}
|
||||
</a>
|
||||
</div>
|
||||
@@ -238,6 +238,7 @@ Vue.component('wohneinheit-status-manager', {
|
||||
workorderMphId: this.workorderMphId, wohneinheitId: we.wohneinheitId, status: we.status, spliceCompleted: we.spliceCompleted ? 1 : 0, tuer: we.tuer, zusatz: we.zusatz
|
||||
});
|
||||
this.$emit('wohneinheit-updated');
|
||||
this.$emit('refresh');
|
||||
} catch (e) { window.notify('error', 'Fehler beim Speichern'); } finally { we.saving = false; }
|
||||
},
|
||||
getStatusText(val) { const o = this.statusOptions.find(opt => opt.value === val); return o ? o.text : ''; },
|
||||
@@ -292,9 +293,12 @@ Vue.component('wohneinheit-status-manager', {
|
||||
window.notify('success', `${successCount} Datei(en) hochgeladen`);
|
||||
this.documentsModal.files = [];
|
||||
this.documentsModal.uploadDescription = '';
|
||||
this.$refs.weFileInput.value = '';
|
||||
this.$refs.weFileInput.value = '';
|
||||
const { data } = await axios.get(`${window.TT_CONFIG.BASE_PATH}${basePath}/getWohneinheitDocuments`, { params: { wohneinheitId: this.documentsModal.wohneinheitId } });
|
||||
this.documentsModal.docs = data.docs || [];
|
||||
// Update document count in wohneinheit list
|
||||
const we = this.wohneinheiten.find(w => w.wohneinheitId === this.documentsModal.wohneinheitId);
|
||||
if (we) we.documentCount = this.documentsModal.docs.length;
|
||||
} else {
|
||||
window.notify('error', 'Upload fehlgeschlagen');
|
||||
}
|
||||
@@ -305,9 +309,12 @@ Vue.component('wohneinheit-status-manager', {
|
||||
try {
|
||||
const basePath = this.isAdmin ? '/WorkorderMphAdmin' : '/WorkorderMphCompany';
|
||||
await axios.post(`${window.TT_CONFIG.BASE_PATH}${basePath}/deleteWohneinheitDocument`, { documentationId: file.id });
|
||||
window.notify('success', 'Gelöscht');
|
||||
window.notify('success', 'Gelöscht');
|
||||
const { data } = await axios.get(`${window.TT_CONFIG.BASE_PATH}${basePath}/getWohneinheitDocuments`, { params: { wohneinheitId: this.documentsModal.wohneinheitId } });
|
||||
this.documentsModal.docs = data.docs || [];
|
||||
// Update document count in wohneinheit list
|
||||
const we = this.wohneinheiten.find(w => w.wohneinheitId === this.documentsModal.wohneinheitId);
|
||||
if (we) we.documentCount = this.documentsModal.docs.length;
|
||||
} catch (e) { window.notify('error', 'Fehler beim Löschen'); }
|
||||
}
|
||||
},
|
||||
@@ -357,6 +364,7 @@ Vue.component('checkbox-documentation', {
|
||||
try {
|
||||
const basePath = this.isAdmin ? '/WorkorderMphAdmin' : '/WorkorderMphCompany';
|
||||
await axios.post(`${window.TT_CONFIG.BASE_PATH}${basePath}/updateCheckboxes`, { workorderMphId: this.workorderMphId, ...this.checkboxes });
|
||||
this.$emit('refresh');
|
||||
} catch (e) { window.notify('error', 'Speichern fehlgeschlagen'); } finally { this.saving = false; }
|
||||
}
|
||||
},
|
||||
|
||||
@@ -4,11 +4,7 @@ Vue.component('workorder-mph-company', {
|
||||
<tt-card>
|
||||
<tt-table-crud ref="table" :crud-config="crudConfig">
|
||||
<template v-slot:hausnummerinfo="{ row }">
|
||||
<div class="small">
|
||||
<div><strong>Adresse:</strong> {{ row.street }} {{ row.hausnummer }}<template v-if="row.stiege">/{{ row.stiege }}</template></div>
|
||||
<div><strong>Ort:</strong> {{ row.plz }} {{ row.city }}</div>
|
||||
<div><strong>Wohneinheiten:</strong> {{ row.wohneinheitCount }}</div>
|
||||
</div>
|
||||
<span class="small">{{ row.street }} {{ row.hausnummer }}<template v-if="row.stiege">/{{ row.stiege }}</template>, {{ row.plz }} {{ row.city }}</span>
|
||||
</template>
|
||||
|
||||
<template v-slot:status="{ row }">
|
||||
@@ -17,59 +13,71 @@ Vue.component('workorder-mph-company', {
|
||||
<span class="ml-2">{{ getStatusColumn(row.status).text }}</span>
|
||||
</template>
|
||||
|
||||
<template v-slot:additionalinfo="{ row }">
|
||||
<div v-if="editingAdditionalInfoId === row.id">
|
||||
<tt-textarea v-model="tempAdditionalInfo" @keydown.esc.native="cancelEdit" rows="3" no-form-group sm ref="editTextarea"/>
|
||||
<div class="mt-2 d-flex justify-content-end">
|
||||
<tt-button text="Abbrechen" @click="cancelEdit" sm additional-class="btn-secondary mr-2"/>
|
||||
<tt-button text="Speichern" @click="updateAdditionalInfo(row)" sm additional-class="btn-success"/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="d-flex align-items-start">
|
||||
<span style="white-space: pre-wrap; max-width: 250px; display: inline-block;">{{ row.additionalInfo || '-' }}</span>
|
||||
<tt-button v-if="!['completed', 'cancelled', 'documented'].includes(row.status)"
|
||||
icon="fas fa-edit" @click="startAdditionalInfoEdit(row)"
|
||||
additional-class="btn-link btn-sm p-0 ml-2" title="Notiz bearbeiten"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-slot:deadlinedate="{ row }">{{ formatDate(row.deadlineDate) }}</template>
|
||||
|
||||
<template v-slot:appointmentdate="{ row }">
|
||||
<div v-if="editingAppointmentId === row.id">
|
||||
<tt-date-picker :value="row.appointmentDate" :date-range="false" time-picker
|
||||
@input="scheduleAppointment(row, $event)" @blur="editingAppointmentId = null"
|
||||
sm no-form-group/>
|
||||
<div v-if="!row.appointmentDate && canSchedule(row)">
|
||||
<tt-date-picker placeholder="Termin festlegen..." :date-range="false"
|
||||
@input="scheduleAppointment(row, $event)" sm no-form-group
|
||||
:additional-props="{ timePicker: true, timePicker24Hour: true, locale: { format: 'DD.MM.YYYY HH:mm' }, drops: 'up' }"/>
|
||||
</div>
|
||||
<div v-else class="d-flex align-items-center">
|
||||
<div v-else-if="row.appointmentDate" class="d-flex align-items-center">
|
||||
<span>{{ formatDate(row.appointmentDate, true) }}</span>
|
||||
<tt-button v-if="canSchedule(row)" icon="fas fa-edit"
|
||||
@click="editingAppointmentId = row.id"
|
||||
additional-class="btn-link btn-sm p-0 ml-2" title="Termin planen"/>
|
||||
<tt-button v-if="canSchedule(row)"
|
||||
icon="fas fa-edit" @click="openRescheduleModal(row)"
|
||||
additional-class="btn-link btn-sm p-0 ml-2" title="Termin ändern"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-slot:additionalinfo="{ row }">
|
||||
<span style="white-space: pre-wrap; max-width: 250px; display: inline-block;">{{ row.additionalInfo || '-' }}</span>
|
||||
<span v-else>–</span>
|
||||
</template>
|
||||
|
||||
<template v-slot:expandedRow="{ row }">
|
||||
<div class="workorder-mph-expanded-wrapper">
|
||||
<!-- Action Buttons -->
|
||||
<div class="mb-3" v-if="!['completed', 'cancelled', 'documented'].includes(row.status)">
|
||||
<div class="btn-group" role="group">
|
||||
<tt-button v-if="row.status === 'assigned'" text="Termin planen"
|
||||
@click="editingAppointmentId = row.id" icon="fas fa-calendar-plus"
|
||||
additional-class="btn-primary"/>
|
||||
<tt-button v-if="row.status === 'scheduled'" text="Arbeit beginnen"
|
||||
@click="startWork(row)" icon="fas fa-play" additional-class="btn-success"/>
|
||||
<tt-button v-if="row.status === 'scheduled'" text="Termin verschieben"
|
||||
@click="openRescheduleModal(row)" icon="fas fa-calendar-alt"
|
||||
additional-class="btn-warning"/>
|
||||
<tt-button v-if="row.status === 'in_progress'" text="Auftrag abschließen"
|
||||
@click="openCompleteModal(row)" icon="fas fa-check-double"
|
||||
additional-class="btn-success"/>
|
||||
<workorder-mph-data-provider :workorder-mph-id="row.id" v-slot="{ docs, journals, refresh }">
|
||||
<div class="workorder-mph-expanded-wrapper">
|
||||
<!-- Action Buttons -->
|
||||
<div class="mb-3" v-if="!['completed', 'cancelled', 'documented'].includes(row.status)">
|
||||
<div class="btn-group" role="group">
|
||||
<tt-button v-if="row.status === 'scheduled'" text="Arbeit beginnen"
|
||||
@click="startWork(row)" icon="fas fa-play" additional-class="btn-success"/>
|
||||
<tt-button v-if="row.status === 'in_progress'" text="Auftrag abschließen"
|
||||
@click="openCompleteModal(row)" icon="fas fa-check-double"
|
||||
additional-class="btn-success"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-xl-4 col-lg-6">
|
||||
<checkbox-documentation :workorder-mph-id="parseInt(row.id)" :is-admin="false"/>
|
||||
</div>
|
||||
<div class="col-xl-8 col-lg-6">
|
||||
<workorder-mph-details-manager :workorder-mph-id="row.id" :is-admin="false"
|
||||
@workorder-completed="$refs.table.$refs.table.refreshTable()"/>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<wohneinheit-status-manager :workorder-mph-id="parseInt(row.id)" :is-admin="false"
|
||||
@wohneinheit-updated="checkAllWohneinheitenHaveNotes(row.id)"/>
|
||||
<div class="row g-2">
|
||||
<!-- Left Column (1/4): Docs Checkbox, Journal -->
|
||||
<div class="col-xl-3 col-lg-4">
|
||||
<div class="mph-details-stack">
|
||||
<checkbox-documentation :workorder-mph-id="parseInt(row.id)" :is-admin="false" @refresh="refresh"/>
|
||||
<workorder-mph-journal :journals="journals" :workorder-mph-id="row.id" :is-admin="false" @refresh="refresh"/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Right Column (3/4): Wohneinheiten, Documents -->
|
||||
<div class="col-xl-9 col-lg-8">
|
||||
<div class="mph-details-stack">
|
||||
<wohneinheit-status-manager :workorder-mph-id="parseInt(row.id)" :is-admin="false" @refresh="refresh"/>
|
||||
<workorder-mph-documents :docs="docs" :workorder-mph-id="row.id" :is-admin="false" @refresh="refresh"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</workorder-mph-data-provider>
|
||||
</template>
|
||||
</tt-table-crud>
|
||||
|
||||
@@ -77,7 +85,8 @@ Vue.component('workorder-mph-company', {
|
||||
title="Termin verschieben" @submit="rescheduleAppointment">
|
||||
<p>Aktueller Termin: <strong>{{ formatDate(rescheduleModalData.currentDate, true) }}</strong></p>
|
||||
<tt-date-picker label="Neuer Termin" v-model="rescheduleModalData.newDate"
|
||||
:date-range="false" time-picker sm row required/>
|
||||
:date-range="false" sm row required
|
||||
:additional-props="{ timePicker: true, timePicker24Hour: true, locale: { format: 'DD.MM.YYYY HH:mm' }, singleDatePicker: true }"/>
|
||||
<tt-textarea label="Grund" v-model="rescheduleModalData.reason" sm row required/>
|
||||
</tt-modal>
|
||||
|
||||
@@ -94,7 +103,8 @@ Vue.component('workorder-mph-company', {
|
||||
data() {
|
||||
return {
|
||||
window,
|
||||
editingAppointmentId: null,
|
||||
editingAdditionalInfoId: null,
|
||||
tempAdditionalInfo: '',
|
||||
rescheduleModalData: null,
|
||||
completeModalData: null,
|
||||
crudConfig: {
|
||||
@@ -102,7 +112,7 @@ Vue.component('workorder-mph-company', {
|
||||
selectable: false,
|
||||
expandable: true,
|
||||
customRowClass: (row) => {
|
||||
if (['completed', 'new', 'cancelled'].includes(row.status)) return 'tt-mph-workorder-irrelevant';
|
||||
if (['completed', 'new', 'cancelled', 'archived'].includes(row.status)) return 'tt-mph-workorder-irrelevant';
|
||||
const deadlineDate = moment.unix(row.deadlineDate);
|
||||
if (!deadlineDate.isValid()) return 'tt-mph-workorder-irrelevant';
|
||||
const daysLeft = deadlineDate.diff(moment(), 'days');
|
||||
@@ -123,17 +133,46 @@ Vue.component('workorder-mph-company', {
|
||||
return window.moment.unix(timestamp).format(withTime ? 'DD.MM.YYYY HH:mm' : 'DD.MM.YYYY');
|
||||
},
|
||||
canSchedule(row) {
|
||||
return ['assigned', 'scheduled'].includes(row.status);
|
||||
return ['assigned', 'scheduled', 'in_progress'].includes(row.status);
|
||||
},
|
||||
async scheduleAppointment(row, newDate) {
|
||||
if (!newDate) {
|
||||
this.editingAppointmentId = null;
|
||||
startAdditionalInfoEdit(row) {
|
||||
this.editingAdditionalInfoId = row.id;
|
||||
this.tempAdditionalInfo = row.additionalInfo || '';
|
||||
this.$nextTick(() => this.$refs.editTextarea?.$el.querySelector('textarea').focus());
|
||||
},
|
||||
cancelEdit() {
|
||||
this.editingAdditionalInfoId = null;
|
||||
this.tempAdditionalInfo = '';
|
||||
},
|
||||
async updateAdditionalInfo(row) {
|
||||
if (row.additionalInfo === this.tempAdditionalInfo) {
|
||||
this.cancelEdit();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const { data } = await axios.post(`${window.TT_CONFIG.BASE_PATH}/WorkorderMphCompany/updateAdditionalInfo`, {
|
||||
workorderMphId: row.id,
|
||||
additionalInfo: this.tempAdditionalInfo
|
||||
});
|
||||
if (data.success) {
|
||||
window.notify('success', data.message);
|
||||
row.additionalInfo = data.newInfo;
|
||||
} else {
|
||||
window.notify('error', data.message || 'Update fehlgeschlagen.');
|
||||
}
|
||||
} catch (e) {
|
||||
window.notify('error', 'Netzwerkfehler.');
|
||||
} finally {
|
||||
this.cancelEdit();
|
||||
}
|
||||
},
|
||||
async scheduleAppointment(row, newDate) {
|
||||
if (!newDate) return;
|
||||
|
||||
const hour = parseInt(moment.unix(newDate).format('H'));
|
||||
if (hour >= 23 || hour < 1) {
|
||||
window.notify('error', 'Bitte geben Sie eine Uhrzeit zwischen 01:00 und 22:59 an!');
|
||||
this.$refs.table.$refs.table.refreshTable();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -150,8 +189,6 @@ Vue.component('workorder-mph-company', {
|
||||
}
|
||||
} catch (e) {
|
||||
window.notify('error', 'Netzwerkfehler.');
|
||||
} finally {
|
||||
this.editingAppointmentId = null;
|
||||
}
|
||||
},
|
||||
openRescheduleModal(row) {
|
||||
@@ -169,8 +206,7 @@ Vue.component('workorder-mph-company', {
|
||||
|
||||
const hour = parseInt(moment.unix(this.rescheduleModalData.newDate).format('H'));
|
||||
if (hour >= 23 || hour < 1) {
|
||||
window.notify('error', 'Bitte geben Sie eine Uhrzeit zwischen 01:00 und 22:59 an!');
|
||||
return;
|
||||
return window.notify('error', 'Bitte geben Sie eine Uhrzeit zwischen 01:00 und 22:59 an!');
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -225,10 +261,6 @@ Vue.component('workorder-mph-company', {
|
||||
} catch (e) {
|
||||
window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.');
|
||||
}
|
||||
},
|
||||
async checkAllWohneinheitenHaveNotes(workorderId) {
|
||||
// This is called when a wohneinheit is updated
|
||||
// Could be used to enable/disable the complete button
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -78,6 +78,11 @@ Vue.component('workorder-tenant-config', {
|
||||
<div class="col-md-6">
|
||||
<h6 class="mb-3">Optionen</h6>
|
||||
<div v-if="editingId === config.id">
|
||||
<tt-checkbox label="Workorder aktivieren"
|
||||
v-model="editableItem.enableWorkorder" sm/>
|
||||
<tt-checkbox label="WorkorderMPH aktivieren"
|
||||
v-model="editableItem.enableWorkorderMph" sm/>
|
||||
<hr>
|
||||
<tt-checkbox label="Dokumentation für Tiefbau erforderlich"
|
||||
v-model="editableItem.civilEngineeringDocsRequired" sm/>
|
||||
<tt-checkbox label="Kabellänge erforderlich"
|
||||
@@ -86,6 +91,9 @@ Vue.component('workorder-tenant-config', {
|
||||
v-model="editableItem.requireCableType" sm/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<p>Workorder: <strong>{{ config.enableWorkorder ? 'Aktiviert' : 'Deaktiviert' }}</strong></p>
|
||||
<p>WorkorderMPH: <strong>{{ config.enableWorkorderMph ? 'Aktiviert' : 'Deaktiviert' }}</strong></p>
|
||||
<hr>
|
||||
<p>Tiefbau-Doku: <strong>{{ config.civilEngineeringDocsRequired ? 'Ja' : 'Nein' }}</strong></p>
|
||||
<p>Kabellänge-Doku: <strong>{{ config.requireCableLength ? 'Ja' : 'Nein' }}</strong></p>
|
||||
<p>Kabeltyp-Doku: <strong>{{ config.requireCableType ? 'Ja' : 'Nein' }}</strong></p>
|
||||
@@ -324,7 +332,9 @@ Vue.component('workorder-tenant-config', {
|
||||
workorderActiveFilters: '{}',
|
||||
civilEngineeringDocsRequired: 0,
|
||||
requireCableLength: 0,
|
||||
requireCableType: 0
|
||||
requireCableType: 0,
|
||||
enableWorkorder: 1,
|
||||
enableWorkorderMph: 1
|
||||
}
|
||||
: {visibleForAddressId: []};
|
||||
this.showModal = true;
|
||||
|
||||
Reference in New Issue
Block a user