Merge branch 'master' into feature-25999/C4_cleanup

This commit is contained in:
SimonGschnell
2025-01-08 11:17:29 +01:00
30 changed files with 1750 additions and 33 deletions
@@ -70,7 +70,7 @@ export default {
cssclass: "position-relative",
calcheightonly: true,
types: [
"student",
"studentStv",
"prestudent"
],
actions: {
+245
View File
@@ -0,0 +1,245 @@
import CoreForm from '../Form/Form.js';
import FormInput from "../Form/Input.js";
import BsModal from '../Bootstrap/Modal.js';
export default {
components: {
CoreForm,
FormInput,
BsModal,
},
emits: [
'added',
'updated',
'deleted',
],
props: {
endpoint: {
type: Object,
required: true
},
zuordnung_typ: String,
savepoint: {},
values: {
type: Array,
required: true
},
confirmLimit: {
type: Number,
default: 20
}
},
data() {
return {
showList: false,
selectedTagId: null,
tagData: {
beschreibung: "",
tag_typ_kurzbz: "",
notiz: "",
style: "",
zuordnung_typ: "",
id: "",
insertamum: "",
insertvon: "",
updateamum: "",
updatevon: "",
response: ""
},
mode: "create"
};
},
created() {
this.init();
},
mounted() {},
methods: {
init() {
if (!this.endpoint)
return;
this.endpoint.getTags()
.then(response => response.data)
.then(response => {
this.tags = response
})
},
hideList() {
this.showList = false;
},
async editTag(tag_id) {
let getData = {
'id': tag_id
};
this.endpoint.getTag(getData)
.then(result => result.data)
.then(result => this.openModal(result))
},
openModal(item = null)
{
this.tagData.beschreibung = item.bezeichnung;
this.tagData.tag_typ_kurzbz = item.tag_typ_kurzbz;
this.tagData.style = item.style;
this.tagData.zuordnung_typ = this.zuordnung_typ;
this.tagData.done = item.done;
this.tagData.insertamum = item.insertamum;
this.tagData.updateamum = item.updateamum;
this.tagData.updatevon = item.updatevon;
this.tagData.insertvon = item.insertvon;
if (item && item.notiz_id)
{
this.selectedTagId = item.notiz_id;
this.tagData.notiz = item.text;
this.mode = "edit";
}
else
{
this.selectedTagId = null;
this.tagData.notiz = "";
this.mode = "create";
}
if (this.mode === "create" && item.tag)
this.saveTag()
else
this.$refs.tagModal.show();
},
async saveTag()
{
let postData = {
tag_typ_kurzbz: this.tagData.tag_typ_kurzbz,
notiz: this.tagData.notiz,
zuordnung_typ: this.tagData.zuordnung_typ,
values: this.values
}
if (this.mode === "edit")
{
postData.id = this.selectedTagId;
this.tagData.id = this.selectedTagId;
this.endpoint.updateTag(postData);
this.$emit("updated", this.tagData);
this.$refs.tagModal.hide();
}
else
{
if (this.$fhcAlert && postData.values.length >= this.confirmLimit)
{
if (await this.$fhcAlert.confirm({message: `Der Tag wird für ${postData.values.length} Einträge gesetzt. Sind Sie sicher?`}) === false)
return;
}
this.endpoint.addTag(postData)
.then(response => response.data)
.then(response => {
if (typeof response === 'number') {
this.tagData.id = response;
} else {
this.tagData.response = response;
}
})
.then(() => {
this.$emit("added", this.tagData);
})
.then(() => {
this.$refs.tagModal.hide();
});
}
},
async doneTag()
{
this.tagData.id = this.selectedTagId;
this.tagData.done = !this.tagData.done;
let postData = {
id: this.selectedTagId,
done: !this.tagData.done
}
this.endpoint.doneTag(postData)
this.$emit("updated", this.tagData);
this.$refs.tagModal.hide();
},
async deleteTag()
{
let postData = {
id: this.selectedTagId
}
this.endpoint.deleteTag(postData)
this.$emit("deleted", this.selectedTagId)
this.$refs.tagModal.hide();
},
reset() {
this.tagData = {
beschreibung: "",
tag_typ_kurzbz: "",
notiz: "",
style: "",
zuordnung_typ: "",
id: "",
done: false,
insertamum: "",
insertvon: "",
updateamum: "",
updatevon: "",
response: ""
};
this.selectedTagId = null;
this.mode = "create";
}
},
template: `
<div class="plus_button_container" @mouseleave="hideList">
<button @mouseover="showList = true"
:disabled="!values || values.length === 0"
class="btn btn-sm">
<i class="fa-solid fa-tag fa-xl"></i>
</button>
<ul v-if="showList" class="dropdown_list">
<li v-for="(item, index) in tags" :key="index" @click="openModal(item)" :title="item.bezeichnung">
{{ item.bezeichnung }}
</li>
</ul>
</div>
<bs-modal
ref="tagModal"
class="fade text-center"
dialog-class="modal-dialog-centered"
@hidden-bs-modal="reset"
>
<template #title>
<span :class="['tag', tagData.style]">{{ tagData.beschreibung }}</span>
</template>
<template #default>
<div class="col">
<form-input
v-model="tagData.notiz"
type="textarea"
field="notiz"
placeholder="Notiz..."
></form-input>
<div class="modificationdate">angelegt von {{ tagData.insertvon }} am {{ tagData.insertamum }}</div>
</div>
</template>
<template #footer>
<div class="d-flex justify-content-between w-100">
<div>
<button
v-if="mode === 'edit'"
class="btn btn-success me-2"
@click="doneTag"
>
{{ tagData.done ? 'Rückgängig' : 'Erledigt' }}
</button>
<button v-if="mode === 'edit'" class="btn btn-danger" @click="deleteTag">Löschen</button>
</div>
<button type="button" class="btn btn-primary" @click="saveTag">
{{ mode === "edit" ? $p.t('ui', 'bearbeiten') : $p.t('studierendenantrag', 'btn_create') }}
</button>
</div>
</template>
</bs-modal>`,
}
+11 -5
View File
@@ -20,6 +20,7 @@ import FilterConfig from './Filter/Config.js';
import FilterColumns from './Filter/Columns.js';
import TableDownload from './Table/Download.js';
import collapseAutoClose from '../../directives/collapseAutoClose.js';
import { defaultHeaderFilter } from '../../tabulator/filters/defaultHeaderFilter.js';
//
const FILTER_COMPONENT_NEW_FILTER = 'Filter Component New Filter';
@@ -72,7 +73,8 @@ export const CoreFilterCmpt = {
uniqueId: String,
// TODO soll im master kommen?
idField: String,
parentIdField: String
parentIdField: String,
countOnly: Boolean
},
data: function() {
return {
@@ -206,6 +208,7 @@ export const CoreFilterCmpt = {
movableColumns: true,
columnDefaults:{
tooltip: true,
headerFilterFunc: defaultHeaderFilter,
},
placeholder,
reactiveData: true,
@@ -275,11 +278,11 @@ export const CoreFilterCmpt = {
const cols = this.tabulator.getColumns();
this.fields = cols.map(col => col.getField());
this.selectedFields = cols.filter(col => col.isVisible()).map(col => col.getField());
});
}
},
updateTabulator() {
if (this.tabulator) {
@@ -610,7 +613,10 @@ export const CoreFilterCmpt = {
<button v-if="reload" class="btn btn-outline-secondary" aria-label="Reload" @click="reloadTable">
<span class="fa-solid fa-rotate-right" aria-hidden="true"></span>
</button>
<span v-if="$slots.actions && tabulatorHasSelector">Mit {{selectedData.length}} ausgewählten:</span>
<span v-if="$slots.actions && tabulatorHasSelector">
<span v-if="countOnly">{{ selectedData.length }} ausgewählt</span>
<span v-else> Mit {{ selectedData.length }} ausgewählten:</span>
</span>
<slot name="actions" v-bind="{selected: tabulatorHasSelector ? selectedData : []}"></slot>
<slot name="search"></slot>
</div>
+1 -1
View File
@@ -52,7 +52,7 @@ export default {
<div v-else-if="searchresult.length < 1">Es wurden keine Ergebnisse gefunden.</div>
<template v-else="" v-for="res in searchresult">
<person v-if="res.type === 'person'" :res="res" :actions="this.searchoptions.actions.person" @actionexecuted="this.hideresult"></person>
<student v-else-if="res.type === 'student'" :res="res" :actions="this.searchoptions.actions.student" @actionexecuted="this.hideresult"></student>
<student v-else-if="res.type === 'student' || res.type === 'studentStv'" :res="res" :actions="this.searchoptions.actions.student" @actionexecuted="this.hideresult"></student>
<prestudent v-else-if="res.type === 'prestudent'" :res="res" :actions="this.searchoptions.actions.prestudent" @actionexecuted="this.hideresult"></prestudent>
<employee v-else-if="res.type === 'mitarbeiter' || res.type === 'mitarbeiter_ohne_zuordnung'" :res="res" :actions="this.searchoptions.actions.employee" @actionexecuted="this.hideresult"></employee>
<organisationunit v-else-if="res.type === 'organisationunit'" :res="res" :actions="this.searchoptions.actions.organisationunit" @actionexecuted="this.hideresult"></organisationunit>
+20 -9
View File
@@ -9,14 +9,14 @@ export default {
},
emits: [ 'actionexecuted' ],
template: `
<div class="searchbar_result searchbar_student">
<div class="searchbar_result searchbar_student" :class="(!res?.aktiv) ? 'searchbar_inaktiv' : ''">
<div class="searchbar_grid">
<div class="searchbar_icon">
<action :res="this.res" :action="this.actions.defaultaction" @actionexecuted="$emit('actionexecuted')">
<img v-if="(typeof res.foto !== 'undefined') && (res.foto !== null)"
:src="'data:image/jpeg;base64,' + res.foto"
class="rounded-circle" height="100"/>
:src="studentImage"
class="rounded" style="max-height: 120px; max-width: 90px;" />
<i v-else class="fas fa-user-circle fa-5x"></i>
</action>
</div>
@@ -29,18 +29,25 @@ export default {
<div class="mb-3"></div>
<div class="searchbar_table">
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Student_uid</div>
<div class="searchbar_tablecell">Student UID</div>
<div class="searchbar_tablecell">
{{ res.uid }}
</div>
</div>
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Person_id</div>
<div class="searchbar_tablecell">Studiengang</div>
<div class="searchbar_tablecell">
{{ res.person_id }}
{{ res.studiengang }}
</div>
</div>
<div class="searchbar_tablerow">
<div class="searchbar_tablecell">Verband</div>
<div class="searchbar_tablecell">
{{ res.verband }}
</div>
</div>
@@ -75,6 +82,10 @@ export default {
computed: {
mailtourl: function() {
return 'mailto:' + this.res.email;
}
},
studentImage: function () {
if (!this.res.foto) return;
return 'data:image/jpeg;base64,'.concat(this.res.foto);
},
}
};