mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-07-25 16:44:28 +00:00
Merge branch 'master' into feature-30660/FHC4_StudierendenGUI_Prototyp
This commit is contained in:
@@ -44,9 +44,9 @@
|
||||
}
|
||||
|
||||
.tabulator-cell .btn {
|
||||
padding: 0 .5rem;
|
||||
max-height: 22px;
|
||||
min-width: 30px;
|
||||
padding: 0 .7rem;
|
||||
min-height: 25px;
|
||||
min-width: 25px;
|
||||
}
|
||||
|
||||
.tabulator-row.tabulator-selectable:focus {
|
||||
|
||||
@@ -164,12 +164,12 @@ export default {
|
||||
},
|
||||
modelValueCmp: {
|
||||
get() {
|
||||
if (this.$attrs.modelValue === undefined)
|
||||
if (!this.$attrs.hasOwnProperty('modelValue'))
|
||||
return this.modelValueDummy;
|
||||
return this.$attrs.modelValue;
|
||||
},
|
||||
set(v) {
|
||||
if (this.$attrs.modelValue === undefined)
|
||||
if (!this.$attrs.hasOwnProperty('modelValue'))
|
||||
this.modelValueDummy = v;
|
||||
this.$emit('update:modelValue', v);
|
||||
}
|
||||
@@ -240,7 +240,7 @@ export default {
|
||||
},
|
||||
template: `
|
||||
<component :is="!hasContainer ? 'FhcFragment' : 'div'" class="position-relative" :class="autoContainerClass">
|
||||
<label v-if="label && lcType != 'radio' && lcType != 'checkbox'" :for="idCmp">{{label}}</label>
|
||||
<label v-if="label && lcType != 'radio' && lcType != 'checkbox'" :class="!noAutoClass && 'form-label'" :for="idCmp">{{label}}</label>
|
||||
<input v-if="tag == 'input'" :type="lcType" ref="input" v-model="modelValueCmp" v-bind="$attrs" :id="idCmp" :name="name" :class="validationClass" :modelValue="undefined" @input="clearValidationForThisName(); $emit('input', $event)">
|
||||
<textarea v-else-if="tag == 'textarea'" ref="input" v-model="modelValueCmp" v-bind="$attrs" :id="idCmp" :name="name" :class="validationClass" :modelValue="undefined" @input="clearValidationForThisName(); $emit('input', $event)"></textarea>
|
||||
<select v-else-if="tag == 'select'" ref="input" v-model="modelValueCmp" v-bind="$attrs" :id="idCmp" :name="name" :class="validationClass" :modelValue="undefined" @input="clearValidationForThisName(); $emit('input', $event)">
|
||||
@@ -276,6 +276,17 @@ export default {
|
||||
@update:model-value="clearValidationForThisName"
|
||||
>
|
||||
<slot></slot>
|
||||
<template #chip="data"><slot name="chip" v-bind="data"></slot></template>
|
||||
<template #header="data"><slot name="header" v-bind="data"></slot></template>
|
||||
<template #footer="data"><slot name="footer" v-bind="data"></slot></template>
|
||||
<template #option="data"><slot name="option" v-bind="data"></slot></template>
|
||||
<template #optiongroup="data"><slot name="optiongroup" v-bind="data"></slot></template>
|
||||
<template #content="data"><slot name="content" v-bind="data"></slot></template>
|
||||
<template #loader="data"><slot name="loader" v-bind="data"></slot></template>
|
||||
<template #empty="data"><slot name="empty" v-bind="data"></slot></template>
|
||||
<template #dropdownicon="data"><slot name="dropdownicon" v-bind="data"></slot></template>
|
||||
<template #removetokenicon="data"><slot name="removetokenicon" v-bind="data"></slot></template>
|
||||
<template #loadingicon="data"><slot name="loadingicon" v-bind="data"></slot></template>
|
||||
</component>
|
||||
<component
|
||||
v-else-if="tag == 'UploadDms'"
|
||||
|
||||
@@ -265,7 +265,7 @@ export default {
|
||||
allowed_status_for_download = ['Genehmigt'];
|
||||
break;
|
||||
case 'AbmeldungStgl':
|
||||
allowed_status_for_download = ['Genehmigt', 'Beeinsprucht', 'EinspruchAbgelehnt', 'Abgemeldet'];
|
||||
allowed_status_for_download = ['EinspruchAbgelehnt', 'Abgemeldet'];
|
||||
break;
|
||||
case 'Unterbrechung':
|
||||
allowed_status_for_download = ['Genehmigt', 'EmailVersandt'];
|
||||
|
||||
@@ -75,7 +75,7 @@ export default {
|
||||
|
||||
tabs[key] = {
|
||||
component: Vue.markRaw(Vue.defineAsyncComponent(() => import(item.component))),
|
||||
title: item.title || key,
|
||||
title: Vue.computed(() => item.title || key),
|
||||
config: item.config,
|
||||
key
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
import {CoreRESTClient} from '../../RESTClient.js';
|
||||
|
||||
//
|
||||
//
|
||||
const CORE_FILTER_CMPT_TIMEOUT = 7000;
|
||||
|
||||
/**
|
||||
|
||||
@@ -65,7 +65,11 @@ export const CoreFilterCmpt = {
|
||||
newBtnShow: Boolean,
|
||||
newBtnClass: [String, Array, Object],
|
||||
newBtnDisabled: Boolean,
|
||||
newBtnLabel: String
|
||||
newBtnLabel: String,
|
||||
uniqueId: String,
|
||||
// TODO soll im master kommen?
|
||||
idField: String,
|
||||
parentIdField: String
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
@@ -212,6 +216,13 @@ export const CoreFilterCmpt = {
|
||||
|
||||
if (tabulatorOptions.selectable || (tabulatorOptions.columns && tabulatorOptions.columns.filter(el => el.formatter == 'rowSelection').length))
|
||||
this.tabulatorHasSelector = true;
|
||||
// TODO check ob im core bleiben soll
|
||||
if (this.idField) {
|
||||
// enable nested tabulator if parent Id given
|
||||
if (this.parentIdField) tabulatorOptions.dataTree = true;
|
||||
// set tabulator index
|
||||
tabulatorOptions.index = this.idField;
|
||||
}
|
||||
|
||||
// Start the tabulator with the build options
|
||||
this.tabulator = new Tabulator(
|
||||
@@ -229,6 +240,33 @@ export const CoreFilterCmpt = {
|
||||
this.tabulator.on("rowSelectionChanged", data => {
|
||||
this.selectedData = data;
|
||||
});
|
||||
// TODO check ob im core so bleiben soll
|
||||
// if nested tabulator, restructure data
|
||||
if (this.parentIdField && this.idField) {
|
||||
this.tabulator.on("dataLoading", data => {
|
||||
let toDelete = [];
|
||||
|
||||
// loop through all data
|
||||
for (let childIdx = 0; childIdx < data.length; childIdx++)
|
||||
{
|
||||
let child = data[childIdx];
|
||||
|
||||
// if it has parent id, it is a child
|
||||
if (child[this.parentIdField])
|
||||
{
|
||||
// append the child on the right place. If parent found, mark original sw child on 0 level for deleting
|
||||
if (this.appendChild(data, child)) toDelete.push(childIdx);
|
||||
}
|
||||
}
|
||||
|
||||
// delete the marked children from 0 level
|
||||
for (let counter = 0; counter < toDelete.length; counter++)
|
||||
{
|
||||
// decrease index by counter as index of data array changes after every deletion
|
||||
data.splice(toDelete[counter] - counter, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (this.tableOnly) {
|
||||
this.tabulator.on('tableBuilt', () => {
|
||||
const cols = this.tabulator.getColumns();
|
||||
@@ -409,6 +447,9 @@ export const CoreFilterCmpt = {
|
||||
apiFunctionParameters.filterUniqueId = FHC_JS_DATA_STORAGE_OBJECT.called_path + "/" + FHC_JS_DATA_STORAGE_OBJECT.called_method;
|
||||
apiFunctionParameters.filterType = this.filterType;
|
||||
|
||||
if (this.uniqueId)
|
||||
apiFunctionParameters.filterUniqueId += '_' + this.uniqueId;
|
||||
|
||||
// Assign parameters to the FetchCmpt binded properties
|
||||
this.fetchCmptApiFunctionParams = apiFunctionParameters;
|
||||
// Assign data fetch callback to the FetchCmpt binded properties
|
||||
@@ -487,6 +528,36 @@ export const CoreFilterCmpt = {
|
||||
},
|
||||
this.getFilter
|
||||
);
|
||||
},
|
||||
// TODO check ob im core so bleiben soll
|
||||
// append child to it's parent
|
||||
appendChild(data, child) {
|
||||
// get parent id
|
||||
let parentId = child[this.parentIdField];
|
||||
|
||||
// loop thorugh all data
|
||||
for (let parentIdx = 0; parentIdx < data.length; parentIdx++)
|
||||
{
|
||||
let parent = data[parentIdx];
|
||||
|
||||
// if it's the parent
|
||||
if (parent[this.idField] == parentId)
|
||||
{
|
||||
// create children array if not done yet
|
||||
if (!parent._children) parent._children = [];
|
||||
|
||||
// if child is not included in children array, append the child
|
||||
if (!parent._children.includes(child)) parent._children.push(child);
|
||||
|
||||
// parent found
|
||||
return true;
|
||||
}
|
||||
// search children for parents
|
||||
else if (parent._children) this.appendChild(parent._children, child);
|
||||
}
|
||||
|
||||
// parent not found
|
||||
return false;
|
||||
}
|
||||
},
|
||||
beforeCreate() {
|
||||
@@ -515,7 +586,7 @@ export const CoreFilterCmpt = {
|
||||
|
||||
<div class="row" v-if="title != null && title != ''">
|
||||
<div class="col-lg-12">
|
||||
<h3 class="page-header">
|
||||
<h3 class="page-header mt-1 mb-4">
|
||||
{{ title }}
|
||||
</h3>
|
||||
</div>
|
||||
@@ -524,7 +595,7 @@ export const CoreFilterCmpt = {
|
||||
<div :id="'filterCollapsables' + idExtra">
|
||||
|
||||
<div class="d-flex flex-row justify-content-between flex-wrap">
|
||||
<div v-if="newBtnShow || reload || $slots.actions" class="d-flex gap-2 align-items-baseline flex-wrap">
|
||||
<div v-if="newBtnShow || reload || $slots.search || $slots.actions" class="d-flex gap-2 align-items-baseline flex-wrap">
|
||||
<button v-if="newBtnShow" class="btn btn-primary" :class="newBtnClass" :title="newBtnLabel ? undefined : 'New'" :aria-label="newBtnLabel ? undefined : 'New'" @click="$emit('click:new', $event)" :disabled="newBtnDisabled">
|
||||
<span class="fa-solid fa-plus" aria-hidden="true"></span>
|
||||
{{ newBtnLabel }}
|
||||
@@ -532,8 +603,9 @@ 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">Mit {{selectedData.length}} ausgewählten:</span>
|
||||
<slot name="actions" v-bind="{selected: tabulatorHasSelector ? selectedData : []}"></slot>
|
||||
<slot name="search"></slot>
|
||||
</div>
|
||||
<div class="d-flex gap-1 align-items-baseline flex-grow-1 justify-content-end">
|
||||
<span v-if="!tableOnly">[ {{ filterName }} ]</span>
|
||||
|
||||
Reference in New Issue
Block a user