mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-07-04 12:29:28 +00:00
show Tags in CoreHeader
This commit is contained in:
@@ -144,7 +144,7 @@ $config['stv_prestudent_tags'] = [
|
||||
'inwork_kf' => ['readonly' => false],
|
||||
'dd_auto' => ['readonly' => false],
|
||||
'wh_auto' => ['readonly' => false],
|
||||
'prewh_auto' => ['readonly' => false],
|
||||
'prewh_auto' => ['readonly' => true], //when readonly kein rendering für automatisierte tags
|
||||
'out_auto' => ['readonly' => false],
|
||||
'zgv_auto' => ['readonly' => false],
|
||||
'wiedereinstieg_auto' => ['readonly' => false],
|
||||
|
||||
@@ -8,6 +8,8 @@ class TagJob extends JOB_Controller
|
||||
{
|
||||
|
||||
const BATCHUSER = 'sftest';
|
||||
const SEMESTER = 'SS2024'; //docker
|
||||
//TODO semester
|
||||
|
||||
/**
|
||||
* API constructor
|
||||
@@ -22,8 +24,6 @@ class TagJob extends JOB_Controller
|
||||
// Library
|
||||
$this->load->library('TagLib');
|
||||
|
||||
// Tag-Helper
|
||||
|
||||
// Load Models
|
||||
$this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
|
||||
|
||||
@@ -103,7 +103,7 @@ class TagJob extends JOB_Controller
|
||||
print_r(PHP_EOL . "create Tags wiederholer " . PHP_EOL);
|
||||
$result = $this->PrestudentstatusModel-> loadWhere(array(
|
||||
'statusgrund_id' => 16,
|
||||
'studiensemester_kurzbz' => 'SS2026'
|
||||
'studiensemester_kurzbz' => self::SEMESTER
|
||||
));
|
||||
$data = $result->retval;
|
||||
$ids = array_map(function($item) {
|
||||
@@ -126,7 +126,7 @@ class TagJob extends JOB_Controller
|
||||
|
||||
$result = $this->PrestudentstatusModel-> loadWhere(array(
|
||||
'statusgrund_id' => 15,
|
||||
'studiensemester_kurzbz' => 'SS2026'
|
||||
'studiensemester_kurzbz' => self::SEMESTER
|
||||
));
|
||||
$data = $result->retval;
|
||||
$ids = array_map(function($item) {
|
||||
@@ -204,7 +204,7 @@ class TagJob extends JOB_Controller
|
||||
/**
|
||||
* delete All Automatic Tags
|
||||
*/
|
||||
public function deleteAllAutomatedTags()
|
||||
public function deleteAutomatedTags()
|
||||
{
|
||||
print_r( PHP_EOL . "Start Job delete ALL Automated Tags" . PHP_EOL);
|
||||
// $this->NotizModel->select('notiz_id');
|
||||
|
||||
@@ -19,6 +19,7 @@ class Tag_Controller extends FHCAPI_Controller
|
||||
'updateTag' => self::BERECHTIGUNG_KURZBZ,
|
||||
'doneTag' => self::BERECHTIGUNG_KURZBZ,
|
||||
'deleteTag' => self::BERECHTIGUNG_KURZBZ,
|
||||
'getAllTags' => self::BERECHTIGUNG_KURZBZ,
|
||||
];
|
||||
|
||||
$merged_permissions = array_merge($default_permissions, $permissions);
|
||||
@@ -65,6 +66,7 @@ class Tag_Controller extends FHCAPI_Controller
|
||||
array_to_json(bezeichnung_mehrsprachig::varchar[])->>". $language. " as bezeichnung,
|
||||
tbl_notiz.notiz_id,
|
||||
tbl_notiz_typ.style,
|
||||
tbl_notiz_typ.automatisiert,
|
||||
tbl_notiz.erledigt as done,
|
||||
tbl_notiz.insertamum,
|
||||
tbl_notiz.updateamum,
|
||||
@@ -82,6 +84,7 @@ class Tag_Controller extends FHCAPI_Controller
|
||||
|
||||
$notiz = $this->NotizModel->loadWhere(array('notiz_id' => $id));
|
||||
|
||||
|
||||
$this->terminateWithSuccess(hasData($notiz) ? getData($notiz)[0] : array());
|
||||
}
|
||||
|
||||
@@ -92,7 +95,8 @@ class Tag_Controller extends FHCAPI_Controller
|
||||
array_to_json(bezeichnung_mehrsprachig::varchar[])->>0 as bezeichnung,
|
||||
style,
|
||||
beschreibung,
|
||||
tag
|
||||
tag,
|
||||
automatisiert
|
||||
'
|
||||
);
|
||||
$this->NotiztypModel->addOrder('prioritaet');
|
||||
@@ -271,6 +275,61 @@ class Tag_Controller extends FHCAPI_Controller
|
||||
$this->terminateWithSuccess($deleteNotiz);
|
||||
}
|
||||
|
||||
public function getAllTags($readonly_tags = false){
|
||||
$language = $this->_getLanguageIndex();
|
||||
$prestudent_id = $this->input->get('prestudent_id');
|
||||
// $this->terminateWithError("id: " . $prestudent_id, self::ERROR_TYPE_GENERAL);
|
||||
|
||||
//TODO check for readonly: necessary?
|
||||
if (is_array($readonly_tags) && !isEmptyArray($readonly_tags))
|
||||
{
|
||||
$readonly_tags = $this->_filterTag($readonly_tags, true);
|
||||
|
||||
foreach ($readonly_tags as $key => $tag)
|
||||
{
|
||||
$readonly_tags[$key] = $this->NotizModel->db->escape($tag);
|
||||
}
|
||||
$tags = '(' . implode(',', $readonly_tags) . ')';
|
||||
|
||||
$this->NotizModel->addSelect("
|
||||
CASE
|
||||
WHEN tbl_notiz_typ.typ_kurzbz IN $tags
|
||||
THEN TRUE
|
||||
ELSE FALSE
|
||||
END as readonly
|
||||
");
|
||||
}
|
||||
|
||||
$this->NotizModel->addSelect(
|
||||
"tbl_notiz.titel,
|
||||
tbl_notiz.text,
|
||||
array_to_json(bezeichnung_mehrsprachig::varchar[])->>". $language. " as bezeichnung,
|
||||
tbl_notiz.notiz_id,
|
||||
tbl_notiz_typ.style,
|
||||
tbl_notiz_typ.automatisiert,
|
||||
tbl_notiz.erledigt as done,
|
||||
tbl_notiz.insertamum,
|
||||
tbl_notiz.updateamum,
|
||||
(verfasserperson.vorname || ' ' || verfasserperson.nachname || ' ' || '(' || verfasserbenutzer.uid || ')') as verfasser,
|
||||
(bearbeiterperson.vorname || ' ' || bearbeiterperson.nachname || ' ' || '(' || bearbeiterbenutzer.uid || ')') as bearbeiter
|
||||
"
|
||||
);
|
||||
$this->NotizModel->addJoin('public.tbl_notiz_typ', 'public.tbl_notiz.typ = public.tbl_notiz_typ.typ_kurzbz');
|
||||
|
||||
$this->NotizModel->addJoin('public.tbl_benutzer verfasserbenutzer', 'tbl_notiz.verfasser_uid = verfasserbenutzer.uid', 'LEFT');
|
||||
$this->NotizModel->addJoin('public.tbl_person verfasserperson', 'verfasserbenutzer.person_id = verfasserperson.person_id', 'LEFT');
|
||||
|
||||
$this->NotizModel->addJoin('public.tbl_benutzer bearbeiterbenutzer', 'tbl_notiz.bearbeiter_uid = bearbeiterbenutzer.uid', 'LEFT');
|
||||
$this->NotizModel->addJoin('public.tbl_person bearbeiterperson', 'bearbeiterbenutzer.person_id = bearbeiterperson.person_id', 'LEFT');
|
||||
|
||||
$this->NotizModel->addJoin('public.tbl_notizzuordnung notizzuordnung', 'tbl_notiz.notiz_id = notizzuordnung.notiz_id');
|
||||
|
||||
$notiz = $this->NotizModel->loadWhere(array('prestudent_id' => $prestudent_id));
|
||||
|
||||
|
||||
$this->terminateWithSuccess(hasData($notiz) ? getData($notiz) : array());
|
||||
}
|
||||
|
||||
private function _setAuthUID()
|
||||
{
|
||||
$this->_uid = getAuthUID();
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@
|
||||
}
|
||||
|
||||
.tag_auto {
|
||||
border: 2px solid #8BCF8A;
|
||||
border: 1px dashed white;
|
||||
}
|
||||
|
||||
.display_all {
|
||||
|
||||
@@ -51,4 +51,13 @@ export default {
|
||||
params: data
|
||||
};
|
||||
},
|
||||
|
||||
//TODO expand to other types
|
||||
getAllTagsPrestudent(prestudent_id){
|
||||
return {
|
||||
method: 'get',
|
||||
url: 'api/frontend/v1/stv/Tags/getAllTags',
|
||||
params: prestudent_id
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -1,11 +1,15 @@
|
||||
import ApiDetailHeader from "../../api/factory/detailHeader.js";
|
||||
import ApiHandleFoto from "../../api/factory/fotoHandling.js";
|
||||
import ModalUploadFoto from "./Modal/UploadFoto.js";
|
||||
import CoreTag from "../Tag/Tag.js";
|
||||
import ApiTag from "../../api/factory/stv/tag.js";
|
||||
import { idTagFormatter } from "../Tag/tagFormatter.js";
|
||||
|
||||
export default {
|
||||
name: 'DetailHeader',
|
||||
components: {
|
||||
ModalUploadFoto
|
||||
ModalUploadFoto,
|
||||
CoreTag
|
||||
},
|
||||
props: {
|
||||
headerData: {
|
||||
@@ -40,6 +44,12 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
inject: {
|
||||
tagsEnabled: {
|
||||
from: 'configStvTagsEnabled',
|
||||
default: false
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
appRoot() {
|
||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root;
|
||||
@@ -61,13 +71,23 @@ export default {
|
||||
hasTileUIDSlot() {
|
||||
return !!this.$slots.uid
|
||||
},
|
||||
|
||||
prestudentIds() {
|
||||
if (this.headerData[0].prestudent_id)
|
||||
{
|
||||
return [this.headerData[0].prestudent_id];
|
||||
}
|
||||
},
|
||||
},
|
||||
created(){
|
||||
if (this.typeHeader === 'student') {
|
||||
if (!this.headerData) {
|
||||
throw new Error('[DetailHeader] "headerData" is required.')
|
||||
}
|
||||
|
||||
if(this.tagsEnabled) {
|
||||
this.loadTagsAndRender(this.headerData[0].prestudent_id);
|
||||
}
|
||||
|
||||
} else if (this.typeHeader === 'mitarbeiter') {
|
||||
if (!this.person_id || !this.mitarbeiter_uid || !this.domain) {
|
||||
throw new Error(
|
||||
@@ -86,13 +106,23 @@ export default {
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
headerData: {
|
||||
handler(newVal) {
|
||||
if(this.tagsEnabled) {
|
||||
this.loadTagsAndRender(this.headerData[0].prestudent_id);
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
headerDataMa: {},
|
||||
departmentData: {},
|
||||
leitungData: {},
|
||||
isFetchingIssues: false
|
||||
isFetchingIssues: false,
|
||||
tagEndpoint: ApiTag,
|
||||
tagData: null,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@@ -179,7 +209,41 @@ export default {
|
||||
} else {
|
||||
return 'data:image/jpeg;base64,' + foto;
|
||||
}
|
||||
}
|
||||
},
|
||||
//methods tags
|
||||
async loadTagsAndRender(prestudent_id) {
|
||||
await this.getAllTags(prestudent_id);
|
||||
|
||||
const container = idTagFormatter(
|
||||
prestudent_id,
|
||||
this.tagData,
|
||||
this.$refs.tagComponent,
|
||||
'prestudent_id'
|
||||
);
|
||||
|
||||
this.$refs.tagWrapper.innerHTML = '';
|
||||
this.$refs.tagWrapper.appendChild(container);
|
||||
},
|
||||
getAllTags(prestudent_id){
|
||||
return this.$api
|
||||
.call(ApiTag.getAllTagsPrestudent({prestudent_id}))
|
||||
.then(result => {
|
||||
this.tagData = result.data;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
addedTag(addedTag)
|
||||
{
|
||||
this.reload();
|
||||
},
|
||||
deletedTag(id)
|
||||
{
|
||||
this.reload();
|
||||
},
|
||||
updatedTag(updatedTag)
|
||||
{
|
||||
this.reload();
|
||||
},
|
||||
},
|
||||
template: `
|
||||
<div class="core-header d-flex justify-content-start align-items-center w-100 overflow-auto pb-2 gap-3" style="max-height:9rem; min-width: 37.5rem;">
|
||||
@@ -245,6 +309,15 @@ export default {
|
||||
<span v-if="headerData[0].titelpost">, </span>
|
||||
{{headerData[0].titelpost}}
|
||||
</h2>
|
||||
<core-tag ref="tagComponent"
|
||||
v-if="tagsEnabled"
|
||||
:endpoint="tagEndpoint"
|
||||
:values="prestudentIds"
|
||||
@added="addedTag"
|
||||
@deleted="deletedTag"
|
||||
@updated="updatedTag"
|
||||
zuordnung_typ="prestudent_id"
|
||||
></core-tag>
|
||||
<h6 v-if="headerData[0].unruly" class="badge" :class="'bg-unruly rounded-0'"><strong>unruly</strong></h6>
|
||||
</div>
|
||||
|
||||
@@ -267,6 +340,7 @@ export default {
|
||||
<strong v-if="headerData[0].statusofsemester" class="text-muted"> | Status </strong>
|
||||
{{headerData[0].statusofsemester}}
|
||||
</h5>
|
||||
<div ref="tagWrapper"></div>
|
||||
|
||||
</div>
|
||||
<div v-if="headerData.length == 1" class="col-md-1 d-flex flex-column align-items-end justify-content-start ms-auto">
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
|
||||
|
||||
export function idTagFormatter (id, tagData, tagComponent, typeId)
|
||||
{
|
||||
if (!id) return;
|
||||
|
||||
const parsedTags = tagData.map(tag => ({
|
||||
id: tag.notiz_id,
|
||||
typ_kurzbz: tag.titel?.toLowerCase(),
|
||||
beschreibung: tag.bezeichnung,
|
||||
notiz: tag.text || "",
|
||||
style: tag.style,
|
||||
done: tag.done,
|
||||
automatisiert: tag.automatisiert,
|
||||
typeId: id
|
||||
}));
|
||||
|
||||
let container = document.createElement('div');
|
||||
container.className = "d-flex gap-1";
|
||||
|
||||
let maxVisibleTags = 5;
|
||||
let expanded = false;
|
||||
const renderTags = () => {
|
||||
container.innerHTML = '';
|
||||
|
||||
let filtered = parsedTags.filter(t => t != null);
|
||||
|
||||
filtered.sort((a, b) => {
|
||||
let adone = a.done ? 1 : 0;
|
||||
let bdone = b.done ? 1 : 0;
|
||||
|
||||
if (adone !== bdone) return adone - bdone;
|
||||
return b.id - a.id;
|
||||
});
|
||||
|
||||
const tagsToShow = expanded
|
||||
? filtered
|
||||
: filtered.slice(0, maxVisibleTags);
|
||||
|
||||
tagsToShow.forEach(tag => {
|
||||
let tagElement = document.createElement('span');
|
||||
tagElement.innerText = tag.beschreibung;
|
||||
tagElement.title = tag.notiz;
|
||||
tagElement.className = "tag " + tag.style;
|
||||
|
||||
if (tag.done) {
|
||||
tagElement.className += " tag_done";
|
||||
}
|
||||
if (tag.automatisiert)
|
||||
tagElement.className += " tag_auto";
|
||||
|
||||
tagElement.addEventListener('click', (event) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
tagComponent.editTag(tag.id);
|
||||
});
|
||||
|
||||
container.appendChild(tagElement);
|
||||
});
|
||||
|
||||
if (filtered.length > maxVisibleTags) {
|
||||
let toggle = document.createElement('button');
|
||||
toggle.innerText = (expanded ? '- ' : '+ ') + (filtered.length - maxVisibleTags);
|
||||
toggle.className = "display_all";
|
||||
|
||||
toggle.addEventListener('click', () => {
|
||||
expanded = !expanded;
|
||||
renderTags();
|
||||
});
|
||||
|
||||
container.appendChild(toggle);
|
||||
}
|
||||
};
|
||||
|
||||
renderTags();
|
||||
|
||||
return container;
|
||||
}
|
||||
@@ -1,5 +1,13 @@
|
||||
export function tagFormatter(cell, tagComponent)
|
||||
{
|
||||
//TODO readOnlyComponents nicht in der TagComponent enthalten
|
||||
//console.log(JSON.stringify(tagComponent));
|
||||
const mappedData = tagComponent.tags.map(tag => ({
|
||||
typ_kurzbz: tag.tag_typ_kurzbz,
|
||||
automatisiert: tag.automatisiert
|
||||
}));
|
||||
|
||||
|
||||
let tags = cell.getValue();
|
||||
if (!tags) return;
|
||||
|
||||
@@ -32,14 +40,29 @@ export function tagFormatter(cell, tagComponent)
|
||||
|
||||
tagsToShow.forEach(tag => {
|
||||
if (!tag) return;
|
||||
|
||||
let tagElement = document.createElement('span');
|
||||
tagElement.innerText = tag.beschreibung;
|
||||
tagElement.title = tag.notiz;
|
||||
tagElement.className = "tag " + tag.style;
|
||||
if (tag.done) tagElement.className += " tag_done";
|
||||
|
||||
//TODO automated styling
|
||||
if (tag.automatisiert) tagElement.className += " tag_done";
|
||||
const tagDef = mappedData.find(t => t.typ_kurzbz === tag.typ_kurzbz);
|
||||
|
||||
if (tagDef?.automatisiert)
|
||||
tagElement.className += " tag_auto";
|
||||
|
||||
/* TODO delete Testoutputs
|
||||
if (!tagDef) {
|
||||
console.log(tag.typ_kurzbz + " nicht in TagComponent enthalten");
|
||||
tagElement.className += " tag_auto";
|
||||
}
|
||||
else if (tagDef?.automatisiert) {
|
||||
console.log(tag.typ_kurzbz + " ist automatisiert");
|
||||
tagElement.className += " tag_auto";
|
||||
} else
|
||||
console.log (tag.typ_kurzbz + " nicht automatisiert");
|
||||
*/
|
||||
|
||||
tagElement.addEventListener('click', (event) => {
|
||||
event.stopPropagation();
|
||||
|
||||
Reference in New Issue
Block a user