mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-01 12:19:28 +00:00
Merge branch 'master' of https://github.com/FH-Complete/FHC-Core
This commit is contained in:
@@ -188,4 +188,20 @@ class Organisationseinheit_model extends DB_Model
|
||||
}
|
||||
return $this->loadWhere($condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get OEs by eventQuery string. Use with autocomplete event queries.
|
||||
* @param $eventQuery String
|
||||
* @return array
|
||||
*/
|
||||
public function getAutocompleteSuggestions($eventQuery)
|
||||
{
|
||||
$this->addSelect('oe_kurzbz');
|
||||
$this->addSelect('organisationseinheittyp_kurzbz, oe_kurzbz, bezeichnung, aktiv, lehre');
|
||||
$this->addOrder('organisationseinheittyp_kurzbz, bezeichnung');
|
||||
|
||||
return $this->loadWhere("
|
||||
oe_kurzbz ILIKE '%". $this->escapeLike($eventQuery). "%'
|
||||
");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +127,11 @@
|
||||
generateJSsInclude('vendor/npm-asset/primevue/autocomplete/autocomplete.min.js');
|
||||
generateJSsInclude('vendor/npm-asset/primevue/overlaypanel/overlaypanel.min.js');
|
||||
generateJSsInclude('vendor/npm-asset/primevue/datatable/datatable.min.js');
|
||||
// TODO check ob notwendig
|
||||
generateJSsInclude('vendor/npm-asset/primevue/toast/toast.min.js');
|
||||
generateJSsInclude('vendor/npm-asset/primevue/toastservice/toastservice.min.js');
|
||||
generateJSsInclude('vendor/npm-asset/primevue/confirmdialog/confirmdialog.min.js');
|
||||
generateJSsInclude('vendor/npm-asset/primevue/confirmationservice/confirmationservice.min.js');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -270,7 +270,7 @@ if (isset($_POST['titel']))
|
||||
foreach($addon_obj->result as $addon)
|
||||
{
|
||||
if(file_exists('../../../addons/'.$addon->kurzbz.'/cis/init.js.php'))
|
||||
echo '<script type="application/x-javascript" src="../../../addons/'.$addon->kurzbz.'/cis/init.js.php" ></script>';
|
||||
echo '<script type="application/x-javascript" src="../../../addons/'.$addon->kurzbz.'/cis/init.js.php"></script>';
|
||||
}
|
||||
|
||||
// Wenn Seite fertig geladen ist Addons aufrufen
|
||||
|
||||
@@ -382,7 +382,7 @@ class projekt extends basis_db
|
||||
JOIN fue.tbl_projekt_ressource USING(ressource_id)
|
||||
JOIN fue.tbl_projekt USING(projekt_kurzbz)
|
||||
WHERE (beginn<=now() or beginn is null)
|
||||
AND (ende + interval '1 month 1 day' >=now() OR ende is null)
|
||||
AND (ende + interval '2 month 1 day' >=now() OR ende is null)
|
||||
AND
|
||||
(
|
||||
mitarbeiter_uid=" . $this->db_add_param($mitarbeiter_uid) . " OR
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
}
|
||||
|
||||
.tabulator-cell .btn {
|
||||
padding: 0 .5rem;
|
||||
max-height: 22px;
|
||||
min-width: 30px;
|
||||
padding: 0 .7rem;
|
||||
min-height: 25px;
|
||||
min-width: 25px;
|
||||
}
|
||||
|
||||
@@ -160,12 +160,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);
|
||||
}
|
||||
@@ -236,12 +236,13 @@ export default {
|
||||
},
|
||||
template: `
|
||||
<component :is="!hasContainer ? 'FhcFragment' : 'div'" class="position-relative" :class="autoContainerClass">
|
||||
<label v-if="$attrs.label && lcType != 'radio' && lcType != 'checkbox'" :for="idCmp">{{$attrs.label}}</label>
|
||||
<label v-if="$attrs.label && lcType != 'radio' && lcType != 'checkbox'" :class="!noAutoClass && 'form-label'" :for="idCmp">{{$attrs.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)">
|
||||
<slot></slot>
|
||||
</select>
|
||||
|
||||
<component
|
||||
v-else-if="tag == 'VueDatePicker'"
|
||||
ref="input"
|
||||
@@ -272,6 +273,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'"
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -62,7 +62,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 {
|
||||
@@ -209,6 +213,13 @@ export const CoreFilterCmpt = {
|
||||
|
||||
if (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(
|
||||
@@ -226,6 +237,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();
|
||||
@@ -406,6 +444,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
|
||||
@@ -484,6 +525,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() {
|
||||
@@ -512,7 +583,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>
|
||||
@@ -521,7 +592,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 }}
|
||||
@@ -529,8 +600,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="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>
|
||||
|
||||
@@ -1280,6 +1280,77 @@ $filters = array(
|
||||
',
|
||||
'oe_kurzbz' => null,
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'dataset_name' => 'softwareManagement',
|
||||
'filter_kurzbz' => 'SoftwareManagement',
|
||||
'description' => '{Software Verwaltung}',
|
||||
'sort' => 1,
|
||||
'default_filter' => true,
|
||||
'filter' => '
|
||||
{
|
||||
"name": "SoftwareManagement",
|
||||
"columns": [
|
||||
{"name": "software_kurzbz"},
|
||||
{"name": "version"},
|
||||
{"name": "beschreibung"},
|
||||
{"name": "hersteller"},
|
||||
{"name": "os"},
|
||||
{"name": "softwarestatus_kurzbz"}
|
||||
],
|
||||
"filters": []
|
||||
}
|
||||
',
|
||||
'oe_kurzbz' => null,
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'dataset_name' => 'imageVerwaltung',
|
||||
'filter_kurzbz' => 'ImageVerwaltung',
|
||||
'description' => '{Image Verwaltung}',
|
||||
'sort' => 1,
|
||||
'default_filter' => true,
|
||||
'filter' => '
|
||||
{
|
||||
"name": "ImageVerwaltung",
|
||||
"columns": [
|
||||
{"name": "bezeichnung"},
|
||||
{"name": "betriebssystem"},
|
||||
{"name": "verfuegbarkeit_start"},
|
||||
{"name": "verfuegbarkeit_ende"},
|
||||
{"name": "anmerkung"},
|
||||
{"name": "ort_count"},
|
||||
{"name": "software_count"}
|
||||
],
|
||||
"filters": []
|
||||
}
|
||||
',
|
||||
'oe_kurzbz' => null,
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'dataset_name' => 'lizenzserverVerwaltung',
|
||||
'filter_kurzbz' => 'LizenzserverVerwaltung',
|
||||
'description' => '{Lizenzserver Verwaltung}',
|
||||
'sort' => 1,
|
||||
'default_filter' => true,
|
||||
'filter' => '
|
||||
{
|
||||
"name": "LizenzserverVerwaltung",
|
||||
"columns": [
|
||||
{"name": "lizenzserver_kurzbz"},
|
||||
{"name": "bezeichnung"},
|
||||
{"name": "macadresse"},
|
||||
{"name": "ipadresse"},
|
||||
{"name": "ansprechpartner"},
|
||||
{"name": "anmerkung"},
|
||||
{"name": "location"}
|
||||
],
|
||||
"filters": []
|
||||
}
|
||||
',
|
||||
'oe_kurzbz' => null,
|
||||
),
|
||||
array(
|
||||
'app' => 'fhctemplate',
|
||||
'dataset_name' => 'exampledata',
|
||||
|
||||
+1401
-1
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user