added new useredit page

This commit is contained in:
2025-09-09 12:40:34 +02:00
parent 6fd3f3c6c0
commit 8abf7444f3
8 changed files with 936 additions and 1 deletions
@@ -0,0 +1,49 @@
.template-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 1rem;
border-bottom: 1px solid #dee2e6;
margin-bottom: 0.5rem;
}
.template-header h3 {
margin: 0;
}
.template-list .list-group-item {
display: flex;
justify-content: space-between;
align-items: center;
}
.template-list .list-group-item .actions {
display: flex;
gap: 0.5rem;
}
/* Modal Styles */
.permissions-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1rem 2rem;
}
.permission-group {
border: 1px solid #dee2e6;
border-radius: 0.3rem;
padding: 1rem;
background-color: #f8f9fa;
}
.permission-group h5 {
font-size: 1.1rem;
border-bottom: 1px solid #e0e0e0;
padding-bottom: 0.5rem;
margin-bottom: 1rem;
}
.form-check-label {
user-select: none;
}
@@ -0,0 +1,147 @@
Vue.component('UserPermissionTemplate', {
template: `
<tt-card>
<div class="template-header">
<h3>Berechtigungsvorlagen</h3>
<tt-button text="Neue Vorlage erstellen" icon="fas fa-plus" additional-class="btn-primary" @click="openModal()"/>
</div>
<div v-if="loading" class="text-center p-5"><i class="fas fa-spinner fa-spin fa-2x"></i></div>
<ul v-else-if="templates.length" class="list-group list-group-flush template-list">
<li v-for="template in templates" :key="template.id" class="list-group-item">
<span>{{ template.name }}</span>
<div class="actions">
<tt-button icon="far fa-edit" additional-class="btn-outline-primary" sm @click="openModal(template)" title="Bearbeiten"/>
<tt-button icon="fas fa-trash" additional-class="btn-outline-danger" sm @click="deleteTemplate(template)" title="Löschen"/>
</div>
</li>
</ul>
<div v-else class="text-center text-muted p-5">
Keine Vorlagen gefunden.
</div>
<tt-modal v-if="showModal" :show.sync="showModal" :title="modalTitle" @submit="saveTemplate" :delete="false" :save-loading="isSaving" size="xl">
<tt-input label="Vorlagename" v-model="editableTemplate.name" required sm/>
<hr>
<div class="permissions-grid">
<div v-for="(group, groupName) in permissionsConfig" :key="groupName" class="permission-group">
<h5>{{ groupName }}</h5>
<div v-for="(label, key) in group" :key="key" class="form-group form-check">
<input type="checkbox" class="form-check-input" :id="'perm-' + key + modalKey" v-model="editableTemplate.permissions[key]">
<label class="form-check-label" :for="'perm-' + key + modalKey" v-html="label"></label>
</div>
</div>
</div>
</tt-modal>
</tt-card>
`,
data() {
// Helper function to get a fresh permissions object. It's defined here to avoid relying on `this`.
const getFreshPermissions = (config) => {
const permissions = {};
if (!config) return permissions;
Object.values(config).forEach(group => {
Object.keys(group).forEach(key => {
permissions[key] = false;
});
});
return permissions;
};
return {
loading: true,
templates: [],
showModal: false,
isSaving: false,
editableTemplate: {
id: null,
name: '',
permissions: getFreshPermissions(window.TT_CONFIG.PERMISSIONS_CONFIG) // Initialize correctly
},
modalKey: Date.now(),
}
},
computed: {
permissionsConfig() {
return window.TT_CONFIG.PERMISSIONS_CONFIG;
},
modalTitle() {
return this.editableTemplate && this.editableTemplate.id ? 'Vorlage bearbeiten' : 'Neue Vorlage erstellen';
}
},
methods: {
fetchTemplates() {
this.loading = true;
axios.get('/UserEdit/getPermissionTemplates')
.then(response => {
this.templates = response.data;
})
.catch(e => window.notify('error', 'Vorlagen konnten nicht geladen werden.'))
.finally(() => this.loading = false);
},
openModal(template = null) {
this.modalKey = Date.now(); // Ensure unique IDs for checkboxes in modal
if (template) {
this.editableTemplate = JSON.parse(JSON.stringify(template)); // Deep copy
const permissions = this.freshPermissions();
// Ensure all keys from config exist on the loaded template's permissions
for (const key in permissions) {
if (this.editableTemplate.permissions.hasOwnProperty(key)) {
permissions[key] = this.editableTemplate.permissions[key];
}
}
this.editableTemplate.permissions = permissions;
} else {
this.editableTemplate = { id: null, name: '', permissions: this.freshPermissions() };
}
this.showModal = true;
},
freshPermissions() {
const permissions = {};
Object.values(this.permissionsConfig).forEach(group => {
Object.keys(group).forEach(key => {
permissions[key] = false;
});
});
return permissions;
},
async saveTemplate() {
if (!this.editableTemplate.name) {
return window.notify('error', 'Bitte einen Namen für die Vorlage eingeben.');
}
this.isSaving = true;
try {
const response = await axios.post('/UserEdit/savePermissionTemplate', this.editableTemplate);
if(response.data.success) {
window.notify('success', response.data.message);
this.showModal = false;
this.fetchTemplates(); // Refresh list
} else {
window.notify('error', response.data.message || 'Fehler beim Speichern.');
}
} catch (e) {
window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.');
} finally {
this.isSaving = false;
}
},
async deleteTemplate(template) {
if (!confirm(`Soll die Vorlage "${template.name}" wirklich gelöscht werden?`)) return;
try {
const response = await axios.post('/UserEdit/deletePermissionTemplate', { id: template.id });
if(response.data.success) {
window.notify('success', response.data.message);
this.fetchTemplates(); // Refresh list
} else {
window.notify('error', response.data.message || 'Fehler beim Löschen.');
}
} catch (e) {
window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.');
}
}
},
mounted() {
this.fetchTemplates();
}
});