added tenant configuration
This commit is contained in:
@@ -8,4 +8,23 @@ class WorkorderCompanyModel extends TTCrudBaseModel {
|
||||
public ?string $visibleForAddressId;
|
||||
public int $create;
|
||||
public int $createBy;
|
||||
|
||||
public static function getCompanyWorkers(int $companyId): array {
|
||||
if (!$company = self::get($companyId)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$db = self::getDB();
|
||||
$addressId = $db->real_escape_string($company->addressId);
|
||||
|
||||
$sql = "SELECT w.id, w.name, w.email
|
||||
FROM `" . FRONKDB_DBNAME . "`.`Worker` w
|
||||
JOIN `" . FRONKDB_DBNAME . "`.`WorkerPermission` wp ON w.id = wp.worker_id
|
||||
WHERE w.address_id = '$addressId' AND wp.canRMLCompany = 'true' AND w.active = 1
|
||||
ORDER BY w.name ASC";
|
||||
|
||||
$result = $db->query($sql);
|
||||
|
||||
return $result ? $result->fetch_all(MYSQLI_ASSOC) : [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
class WorkorderTenantConfigController extends TTCrud {
|
||||
protected string $headerTitle = 'Mandanten & Firmen Konfiguration';
|
||||
protected bool $createText = false;
|
||||
protected array $columns = [];
|
||||
|
||||
protected function indexAction() {
|
||||
Helper::renderVue($this, 'WorkorderTenantConfig', $this->headerTitle, []);
|
||||
}
|
||||
|
||||
protected function getTenantConfigsAction() {
|
||||
$configs = WorkorderTenantConfigModel::getAll([], null, 0, ['key' => 'name', 'order' => 'ASC']);
|
||||
self::returnJson($configs);
|
||||
}
|
||||
|
||||
protected function saveTenantConfigAction() {
|
||||
$data = $this->postData;
|
||||
$data['documentationTypes'] = json_encode($data['documentationTypes'] ?? []);
|
||||
$data['interventionTypes'] = json_encode($data['interventionTypes'] ?? []);
|
||||
$data['workorderCreationFilters'] ??= '{}';
|
||||
|
||||
if (empty($data['id'])) {
|
||||
$data['create'] = time();
|
||||
$data['createBy'] = $this->user->id;
|
||||
WorkorderTenantConfigModel::create($data);
|
||||
} else {
|
||||
WorkorderTenantConfigModel::update($data);
|
||||
}
|
||||
self::returnJson(['success' => true, 'message' => 'Mandanten-Konfiguration gespeichert.']);
|
||||
}
|
||||
|
||||
protected function deleteTenantConfigAction() {
|
||||
if (empty($this->postData['id'])) self::sendError("ID fehlt.");
|
||||
|
||||
WorkorderTenantConfigModel::delete($this->postData['id']);
|
||||
self::returnJson(['success' => true, 'message' => 'Mandanten-Konfiguration gelöscht.']);
|
||||
}
|
||||
|
||||
protected function getCompaniesAction() {
|
||||
$companies = WorkorderCompanyModel::getAll([], null, 0, ['key' => 'name', 'order' => 'ASC']);
|
||||
foreach ($companies as $company) {
|
||||
$company->workers = WorkorderCompanyModel::getCompanyWorkers($company->id);
|
||||
}
|
||||
self::returnJson($companies);
|
||||
}
|
||||
|
||||
protected function saveCompanyAction() {
|
||||
$data = $this->postData;
|
||||
if (empty($data['name']) || empty($data['addressId'])) self::sendError("Name und Adresse sind erforderlich.");
|
||||
|
||||
unset($data['workers']);
|
||||
$data['visibleForAddressId'] = json_encode($data['visibleForAddressId'] ?? []);
|
||||
|
||||
if (empty($data['id'])) {
|
||||
$data['create'] = time();
|
||||
$data['createBy'] = $this->user->id;
|
||||
WorkorderCompanyModel::create($data);
|
||||
} else {
|
||||
WorkorderCompanyModel::update($data);
|
||||
}
|
||||
self::returnJson(['success' => true, 'message' => 'Firma gespeichert.']);
|
||||
}
|
||||
|
||||
protected function deleteCompanyAction() {
|
||||
if (empty($this->postData['id'])) self::sendError("ID fehlt.");
|
||||
|
||||
WorkorderCompanyModel::delete($this->postData['id']);
|
||||
self::returnJson(['success' => true, 'message' => 'Firma gelöscht.']);
|
||||
}
|
||||
|
||||
protected function addressAutocompleteAction() {
|
||||
$search = trim($this->request->q ?? '');
|
||||
$searchedID = $this->request->searchedID ?? null;
|
||||
$addresses = [];
|
||||
|
||||
if ($searchedID) {
|
||||
$ids = array_filter(explode(',', $searchedID));
|
||||
if ($ids) $addresses = AddressModel::search(['id' => $ids]);
|
||||
} elseif (strlen($search) >= 2) {
|
||||
$addresses = array_slice(AddressModel::search(["company" => $search]), 0, 15);
|
||||
}
|
||||
|
||||
$results = array_map(function($address) {
|
||||
return [
|
||||
'value' => $address->id,
|
||||
'text' => "{$address->getCompanyOrName()} ({$address->zip} {$address->city})"
|
||||
];
|
||||
}, $addresses);
|
||||
|
||||
self::returnJson($results);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/* WorkorderTenantConfig.css */
|
||||
|
||||
.config-card .card-header {
|
||||
background-color: #f8f9fa;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
.config-card .card-body h6 {
|
||||
font-weight: 600;
|
||||
color: #495057;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.config-card .list-group-item {
|
||||
font-size: 0.9rem;
|
||||
border-color: #f1f1f1;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.code-block {
|
||||
background-color: #e9ecef;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
font-family: monospace;
|
||||
font-size: 0.85rem;
|
||||
white-space: pre-wrap;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.type-list .list-group-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding-top: .4rem;
|
||||
padding-bottom: .4rem;
|
||||
}
|
||||
|
||||
.type-list .list-group-item span {
|
||||
font-size: 0.95rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.type-list .list-group-item small.code-font {
|
||||
font-family: monospace;
|
||||
color: #6c757d;
|
||||
background-color: #e9ecef;
|
||||
padding: 0.1rem 0.4rem;
|
||||
border-radius: 3px;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
.tenant-tags-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 0.25rem;
|
||||
min-height: 38px;
|
||||
}
|
||||
|
||||
.tenant-tag {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.3em 0.75em;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.tenant-tag i.fa-times-circle {
|
||||
margin-left: 0.5em;
|
||||
cursor: pointer;
|
||||
opacity: 0.7;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.tenant-tag i.fa-times-circle:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.tenant-edit-list .list-group-item {
|
||||
padding: 0.5rem 0.75rem;
|
||||
}
|
||||
|
||||
.tenant-edit-list .btn-link {
|
||||
padding: 0;
|
||||
}
|
||||
333
public/js/pages/WorkorderTenantConfig/WorkorderTenantConfig.js
Normal file
333
public/js/pages/WorkorderTenantConfig/WorkorderTenantConfig.js
Normal file
@@ -0,0 +1,333 @@
|
||||
// WorkorderTenantConfig.js
|
||||
Vue.component('workorder-tenant-config', {
|
||||
template: `
|
||||
<tt-card>
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<ul class="nav nav-pills">
|
||||
<li class="nav-item"><a class="nav-link" :class="{active: activeTab === 'configs'}" href="#"
|
||||
@click.prevent="activeTab = 'configs'"><i class="fas fa-cogs mr-1"></i>
|
||||
Mandanten-Konfigurationen</a></li>
|
||||
<li class="nav-item"><a class="nav-link" :class="{active: activeTab === 'companies'}" href="#"
|
||||
@click.prevent="activeTab = 'companies'"><i class="fas fa-building mr-1"></i>
|
||||
Firmenverwaltung</a></li>
|
||||
</ul>
|
||||
<tt-button :text="activeTab === 'configs' ? 'Neue Konfiguration' : 'Neue Firma'" @click="openCreateModal"
|
||||
icon="fas fa-plus" additional-class="btn-primary"/>
|
||||
</div>
|
||||
|
||||
<div v-if="loading" class="text-center p-5"><i class="fas fa-spinner fa-spin fa-2x"></i></div>
|
||||
|
||||
<div v-show="!loading && activeTab === 'configs'">
|
||||
<div v-for="config in configs" :key="config.id" class="card mb-3 config-card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0">
|
||||
<i class="fas fa-file-alt mr-2"></i>
|
||||
<tt-autocomplete v-if="editingId === config.id" :api-url="addressApiUrl"
|
||||
v-model="editableItem.addressId" @input="editableItem.name = $event.text" no-form-group
|
||||
sm/>
|
||||
<strong v-else>{{ config.name }}</strong>
|
||||
</h5>
|
||||
<div>
|
||||
<tt-button v-if="editingId !== config.id" @click="startEdit(config)" icon="fas fa-edit"
|
||||
additional-class="btn-sm btn-outline-primary mr-2"/>
|
||||
<tt-button v-if="editingId === config.id" @click="saveItem" icon="fas fa-save"
|
||||
additional-class="btn-sm btn-success mr-2"/>
|
||||
<tt-button v-if="editingId === config.id" @click="cancelEdit" icon="fas fa-times"
|
||||
additional-class="btn-sm btn-secondary mr-2"/>
|
||||
<tt-button @click="deleteItem(config, 'configs')" icon="fas fa-trash"
|
||||
additional-class="btn-sm btn-outline-danger"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h6>Dokumentationstypen</h6>
|
||||
<tt-positions-manager :config="docTypesConfig" v-model="editableItem.documentationTypes"
|
||||
v-if="editingId === config.id"/>
|
||||
<ul v-else class="list-group list-group-flush type-list">
|
||||
<li v-for="doc in JSON.parse(config.documentationTypes || '[]')" class="list-group-item">
|
||||
<span>{{ doc.text }}</span><small class="code-font">{{ doc.value }}</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h6>Interventionstypen</h6>
|
||||
<tt-positions-manager :config="interventionTypesConfig" v-model="editableItem.interventionTypes"
|
||||
v-if="editingId === config.id"/>
|
||||
<ul v-else class="list-group list-group-flush type-list">
|
||||
<li v-for="intervention in JSON.parse(config.interventionTypes || '[]')" class="list-group-item">
|
||||
<span>{{ intervention.text }}</span><small class="code-font">{{ intervention.value }}</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row mt-3">
|
||||
<div class="col-md-4">
|
||||
<h6>Filter für Auftragserstellung</h6>
|
||||
<pre v-if="editingId !== config.id"
|
||||
class="code-block">{{ JSON.stringify(JSON.parse(config.workorderCreationFilters || '{}'), null, 2) }}</pre>
|
||||
<tt-textarea v-else v-model="editableJsonFilter" rows="6"/>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<h6 class="mb-3">Optionen</h6>
|
||||
<tt-checkbox label="Dokumentation für Tiefbau erforderlich"
|
||||
v-model="editableItem.civilEngineeringDocsRequired" sm v-if="editingId === config.id"/>
|
||||
<p v-else>Tiefbau-Doku: {{ config.civilEngineeringDocsRequired ? 'Ja' : 'Nein' }}</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<h6>Zugeordnete Firmen</h6>
|
||||
<ul v-if="companiesByTenantMap[config.addressId] && companiesByTenantMap[config.addressId].length"
|
||||
class="list-group">
|
||||
<li v-for="company in companiesByTenantMap[config.addressId]" class="list-group-item py-1"><i
|
||||
class="fas fa-building mr-2 text-muted"></i>{{ company.name }}
|
||||
</li>
|
||||
</ul>
|
||||
<div v-else class="text-muted p-3">Keine Firmen zugeordnet.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="!loading && activeTab === 'companies'">
|
||||
<div v-for="company in companies" :key="company.id" class="card mb-3 config-card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0"><i class="fas fa-building mr-2"></i><strong>{{ company.name }}</strong></h5>
|
||||
<div>
|
||||
<tt-button v-if="editingId !== company.id" @click="startEdit(company)" icon="fas fa-edit"
|
||||
additional-class="btn-sm btn-outline-primary mr-2"/>
|
||||
<tt-button v-if="editingId === company.id" @click="saveItem" icon="fas fa-save"
|
||||
additional-class="btn-sm btn-success mr-2"/>
|
||||
<tt-button v-if="editingId === company.id" @click="cancelEdit" icon="fas fa-times"
|
||||
additional-class="btn-sm btn-secondary mr-2"/>
|
||||
<tt-button @click="deleteItem(company, 'companies')" icon="fas fa-trash"
|
||||
additional-class="btn-sm btn-outline-danger"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h6>Sichtbar für Mandanten</h6>
|
||||
<div v-if="editingId === company.id">
|
||||
<ul class="list-group tenant-edit-list mb-2">
|
||||
<li v-for="(tenantId, index) in editableItem.visibleForAddressId" :key="tenantId"
|
||||
class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<tt-resolver :value="tenantId" reference="/WorkorderTenantConfig/addressAutocomplete"
|
||||
:autocomplete="true"/>
|
||||
<tt-button icon="fas fa-trash" @click="removeTenant(index)"
|
||||
additional-class="btn-sm btn-link text-danger"/>
|
||||
</li>
|
||||
</ul>
|
||||
<tt-autocomplete :api-url="addressApiUrl" v-model="tenantToAdd" @input="addTenant"
|
||||
placeholder="Mandant hinzufügen..." sm no-form-group/>
|
||||
</div>
|
||||
<ul v-else class="list-group list-group-flush">
|
||||
<li v-for="tenantId in JSON.parse(company.visibleForAddressId || '[]')"
|
||||
class="list-group-item py-1">
|
||||
<tt-resolver :value="tenantId" reference="/WorkorderTenantConfig/addressAutocomplete"
|
||||
:autocomplete="true"/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h6>Zugehörige Mitarbeiter <small>(mit RMLCompany-Recht)</small></h6>
|
||||
<ul v-if="company.workers && company.workers.length" class="list-group list-group-flush">
|
||||
<li v-for="worker in company.workers" class="list-group-item py-1">{{ worker.name }} (
|
||||
{{ worker.email }})
|
||||
</li>
|
||||
</ul>
|
||||
<div v-else class="text-muted p-3">Keine Mitarbeiter für diese Firma gefunden.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<tt-modal v-if="showModal" :show.sync="showModal" :title="modalTitle" @submit="saveNewItem" :delete="false">
|
||||
<div v-if="activeTab === 'configs'">
|
||||
<tt-autocomplete label="Mandant" :api-url="addressApiUrl" v-model="newItem.addressId"
|
||||
@input="newItem.name = $event.text" sm row required/>
|
||||
</div>
|
||||
<div v-if="activeTab === 'companies'">
|
||||
<tt-autocomplete label="Firma" :api-url="addressApiUrl" v-model="newItem.addressId"
|
||||
@input="newItem.name = $event.text" sm row required/>
|
||||
<div class="form-group row">
|
||||
<label class="col-form-label col-sm-4 col-form-label-sm">Sichtbar für Mandanten</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="tenant-tags-container mb-2">
|
||||
<span v-for="(tenantId, index) in newItem.visibleForAddressId" :key="tenantId"
|
||||
class="badge badge-primary tenant-tag">
|
||||
<tt-resolver :value="tenantId" reference="/WorkorderTenantConfig/addressAutocomplete"
|
||||
:autocomplete="true"/>
|
||||
<i class="fas fa-times-circle" @click="removeTenant(index, true)"></i>
|
||||
</span>
|
||||
</div>
|
||||
<tt-autocomplete :api-url="addressApiUrl" v-model="tenantToAdd" @input="addTenant($event, true)"
|
||||
placeholder="Mandant hinzufügen..." sm no-form-group/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</tt-modal>
|
||||
</tt-card>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
loading: true, activeTab: 'configs', configs: [], companies: [], editingId: null, editableItem: {},
|
||||
editableJsonFilter: '', showModal: false, newItem: {}, tenantToAdd: null,
|
||||
addressApiUrl: `${window.TT_CONFIG.BASE_PATH}/WorkorderTenantConfig/addressAutocomplete`,
|
||||
docTypesConfig: {
|
||||
fields: {
|
||||
text: {type: 'input', label: 'Anzeigename'},
|
||||
value: {type: 'input', label: 'Schlüssel'}
|
||||
}
|
||||
},
|
||||
interventionTypesConfig: {
|
||||
fields: {
|
||||
text: {type: 'input', label: 'Anzeigename'},
|
||||
value: {type: 'input', label: 'Schlüssel'}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
modalTitle() {
|
||||
return this.activeTab === 'configs' ? 'Neue Konfiguration erstellen' : 'Neue Firma anlegen';
|
||||
},
|
||||
companiesByTenantMap() {
|
||||
const map = {};
|
||||
this.configs.forEach(config => {
|
||||
map[config.addressId] = [];
|
||||
});
|
||||
this.companies.forEach(company => {
|
||||
try {
|
||||
const visibleFor = JSON.parse(company.visibleForAddressId || '[]');
|
||||
if (Array.isArray(visibleFor)) {
|
||||
visibleFor.forEach(tenantId => {
|
||||
if (map[tenantId]) map[tenantId].push(company);
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
});
|
||||
return map;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async fetchData() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const [configsRes, companiesRes] = await Promise.all([
|
||||
axios.get(`${window.TT_CONFIG.BASE_PATH}/WorkorderTenantConfig/getTenantConfigs`),
|
||||
axios.get(`${window.TT_CONFIG.BASE_PATH}/WorkorderTenantConfig/getCompanies`),
|
||||
]);
|
||||
this.configs = configsRes.data;
|
||||
this.companies = companiesRes.data;
|
||||
} catch (e) {
|
||||
window.notify('error', 'Daten konnten nicht geladen werden.');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
startEdit(item) {
|
||||
this.editingId = item.id;
|
||||
this.editableItem = JSON.parse(JSON.stringify(item));
|
||||
if (this.activeTab === 'configs') {
|
||||
this.editableItem.documentationTypes = JSON.parse(this.editableItem.documentationTypes || '[]');
|
||||
this.editableItem.interventionTypes = JSON.parse(this.editableItem.interventionTypes || '[]');
|
||||
this.editableJsonFilter = JSON.stringify(JSON.parse(this.editableItem.workorderCreationFilters || '{}'), null, 2);
|
||||
} else {
|
||||
try {
|
||||
this.editableItem.visibleForAddressId = JSON.parse(this.editableItem.visibleForAddressId || '[]');
|
||||
} catch (e) {
|
||||
this.editableItem.visibleForAddressId = [];
|
||||
}
|
||||
}
|
||||
},
|
||||
cancelEdit() {
|
||||
this.editingId = null;
|
||||
this.editableItem = {};
|
||||
this.editableJsonFilter = '';
|
||||
},
|
||||
async saveItem() {
|
||||
const endpoint = this.activeTab === 'configs' ? 'saveTenantConfig' : 'saveCompany';
|
||||
let payload = {...this.editableItem};
|
||||
|
||||
if (this.activeTab === 'configs') {
|
||||
try {
|
||||
JSON.parse(this.editableJsonFilter);
|
||||
payload.workorderCreationFilters = this.editableJsonFilter;
|
||||
} catch (e) {
|
||||
return window.notify('error', 'Filter für Auftragserstellung ist kein valides JSON.');
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const {data} = await axios.post(`${window.TT_CONFIG.BASE_PATH}/WorkorderTenantConfig/${endpoint}`, payload);
|
||||
if (data.success) {
|
||||
window.notify('success', data.message);
|
||||
this.cancelEdit();
|
||||
await this.fetchData();
|
||||
} else {
|
||||
window.notify('error', data.message || 'Speichern fehlgeschlagen.');
|
||||
}
|
||||
} catch (e) {
|
||||
window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.');
|
||||
}
|
||||
},
|
||||
async deleteItem(item, type) {
|
||||
if (!confirm(`Soll der Eintrag "${item.name}" wirklich gelöscht werden?`)) return;
|
||||
const endpoint = type === 'configs' ? 'deleteTenantConfig' : 'deleteCompany';
|
||||
try {
|
||||
const {data} = await axios.post(`${window.TT_CONFIG.BASE_PATH}/WorkorderTenantConfig/${endpoint}`, {id: item.id});
|
||||
if (data.success) {
|
||||
window.notify('success', data.message);
|
||||
await this.fetchData();
|
||||
} else {
|
||||
window.notify('error', data.message || 'Löschen fehlgeschlagen.');
|
||||
}
|
||||
} catch (e) {
|
||||
window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.');
|
||||
}
|
||||
},
|
||||
openCreateModal() {
|
||||
this.newItem = this.activeTab === 'configs'
|
||||
? {
|
||||
documentationTypes: [],
|
||||
interventionTypes: [],
|
||||
workorderCreationFilters: '{}',
|
||||
civilEngineeringDocsRequired: 0
|
||||
}
|
||||
: {visibleForAddressId: []};
|
||||
this.showModal = true;
|
||||
},
|
||||
async saveNewItem() {
|
||||
const endpoint = this.activeTab === 'configs' ? 'saveTenantConfig' : 'saveCompany';
|
||||
try {
|
||||
const {data} = await axios.post(`${window.TT_CONFIG.BASE_PATH}/WorkorderTenantConfig/${endpoint}`, this.newItem);
|
||||
if (data.success) {
|
||||
window.notify('success', data.message);
|
||||
this.showModal = false;
|
||||
await this.fetchData();
|
||||
} else {
|
||||
window.notify('error', data.message || 'Speichern fehlgeschlagen.');
|
||||
}
|
||||
} catch (e) {
|
||||
window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.');
|
||||
}
|
||||
},
|
||||
addTenant(tenant, isNewItem = false) {
|
||||
const tenantId = typeof tenant === 'object' && tenant !== null ? tenant.value : tenant;
|
||||
const targetArray = isNewItem ? this.newItem.visibleForAddressId : this.editableItem.visibleForAddressId;
|
||||
if (tenantId && !targetArray.includes(tenantId)) targetArray.push(tenantId);
|
||||
this.$nextTick(() => {
|
||||
this.tenantToAdd = null;
|
||||
});
|
||||
},
|
||||
removeTenant(index, isNewItem = false) {
|
||||
const targetArray = isNewItem ? this.newItem.visibleForAddressId : this.editableItem.visibleForAddressId;
|
||||
targetArray.splice(index, 1);
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
await this.fetchData();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user