vue router merge cms & fhc app; viewData check and fetch in dashboard and widgets if not originating from that php controller; lvinfo app delete; code cleanup profil; WIP profil routing;

This commit is contained in:
Johann Hoffmann
2025-01-21 16:42:23 +01:00
parent 0ec3ba8e69
commit e9b01b7fa8
13 changed files with 861 additions and 941 deletions
+13 -2
View File
@@ -60,7 +60,15 @@ class Cms extends Auth_Controller
$content = current($content);
$this->load->view('CisVue/Cms/Content', ['content_id' => $content_id, 'template_kurzbz' => $content->template_kurzbz, 'version' => $version, 'sprache' => $sprache, 'sichtbar' => $sichtbar]);
$viewData = array(
'content_id' => $content_id,
'template_kurzbz' => $content->template_kurzbz,
'version' => $version,
'sichtbar' => $sichtbar
);
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'Content']);
// $this->load->view('CisVue/Cms/Content', ['content_id' => $content_id, 'template_kurzbz' => $content->template_kurzbz, 'version' => $version, 'sprache' => $sprache, 'sichtbar' => $sichtbar]);
}
/**
@@ -76,7 +84,10 @@ class Cms extends Auth_Controller
*/
public function news($infoscreen = false, $studiengang_kz = null, $semester = null, $mischen = true, $titel = '', $edit = false, $sichtbar = true)
{
$this->load->view('CisVue/Cms/Content', ['infoscreen' => $infoscreen, 'studiengang_kz' => $studiengang_kz, 'semester' => $semester, 'mischen' => $mischen, 'titel' => $titel, 'edit' => $edit, 'sichtbar' => $sichtbar]);
// TODO: what are those parameters and what are they used for?
$this->load->view('CisRouterView/CisRouterView.php', ['route' => 'News']);
// $this->load->view('CisVue/Cms/Content', ['infoscreen' => $infoscreen, 'studiengang_kz' => $studiengang_kz, 'semester' => $semester, 'mischen' => $mischen, 'titel' => $titel, 'edit' => $edit, 'sichtbar' => $sichtbar]);
}
public function getRoomInformation($ort_kurzbz){
@@ -0,0 +1,58 @@
<?php
/**
* Copyright (C) 2024 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
class Cis4FhcApi extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'getViewData' => self::PERM_LOGGED,
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* fetches ViewData
*/
public function getViewData()
{
$this->load->model('person/Person_model','PersonModel');
$personData = getData($this->PersonModel->getByUid(getAuthUID()))[0];
$viewData = array(
'uid' => getAuthUID(),
'name' => $personData->vorname,
'person_id' => $personData->person_id
);
$this->terminateWithSuccess($viewData);
}
}
@@ -17,7 +17,8 @@ $includesArray = array(
'public/css/components/MyLv.css',
'public/css/components/FilterComponent.css',
'public/css/components/Profil.css',
'public/css/components/FormUnderline.css'
'public/css/components/FormUnderline.css',
'public/css/Cis4/Cms.css',
),
'customJSs' => array(
'vendor/npm-asset/primevue/accordion/accordion.js',
@@ -32,6 +33,8 @@ $includesArray = array(
$this->load->view('templates/CISVUE-Header', $includesArray);
?>
<div id="fhccontent" route=<?php echo $route ?>>
<router-view view-data-string='<?php echo json_encode($viewData) ?>'></router-view>
<router-view
:view-data='<?php echo json_encode($viewData) ?>'
></router-view>
</div>
<?php $this->load->view('templates/CISVUE-Footer', $includesArray); ?>
+6
View File
@@ -0,0 +1,6 @@
export default {
async getViewData() {
const url = `/api/frontend/v1/Cis4FhcApi/getViewData`;
return this.$fhcApi.get(url, null, null)
},
}
+2
View File
@@ -35,11 +35,13 @@ import lehre from "./lehre.js";
import addons from "./addons.js";
import studiengang from "./studiengang.js";
import menu from "./menu.js";
import dashboard from "./dashboard";
export default {
search,
phrasen,
navigation,
dashboard,
filter,
studstatus,
profil,
+19 -19
View File
@@ -7,23 +7,23 @@ Vue.$fhcapi = fhcapifactory;
import {setScrollbarWidth} from "../../helpers/CssVarCalcHelpers";
import FhcApi from "../../plugin/FhcApi";
const ciPath = FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, '') + FHC_JS_DATA_STORAGE_OBJECT.ci_router;
const router = VueRouter.createRouter({
history: VueRouter.createWebHistory(`/${ciPath}/CisVue/Cms/`),
routes: [
{
path: `/content/:content_id`,
name: 'Content',
component: CmsContent,
props: (route) => ({ content_id: route.params.content_id })
},
{
path: `/news`,
name: 'News',
component: CmsNews,
}
]
})
// const ciPath = FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, '') + FHC_JS_DATA_STORAGE_OBJECT.ci_router;
// const router = VueRouter.createRouter({
// history: VueRouter.createWebHistory(`/${ciPath}/CisVue/Cms/`),
// routes: [
// {
// path: `/content/:content_id`,
// name: 'Content',
// component: CmsContent,
// props: (route) => ({ content_id: route.params.content_id })
// },
// {
// path: `/news`,
// name: 'News',
// component: CmsNews,
// }
// ]
// })
const app = Vue.createApp({
@@ -33,6 +33,8 @@ const app = Vue.createApp({
CmsContent,
},
mounted() {
// TODO: warum ist das hier? Content? News?
document.querySelectorAll("#cms [data-confirm]").forEach((el) => {
el.addEventListener("click", (evt) => {
evt.preventDefault();
@@ -60,8 +62,6 @@ const app = Vue.createApp({
setScrollbarWidth();
app.use(router);
window.cmsRouter = router;
app.use(FhcApi);
app.use(primevue.config.default, { zIndex: { overlay: 9999 } });
app.use(Phrasen);
-13
View File
@@ -1,13 +0,0 @@
import Info from "../../components/Cis/Mylv/Semester/Studiengang/Lv/Info.js";
import Phrasen from "../../plugin/Phrasen.js";
import {setScrollbarWidth} from "../../helpers/CssVarCalcHelpers";
const app = Vue.createApp({
components: {
Info
}
})
setScrollbarWidth();
app.use(Phrasen, { reload: true }).mount('#content');
+51 -44
View File
@@ -5,31 +5,51 @@ import {setScrollbarWidth} from "../../helpers/CssVarCalcHelpers";
import Stundenplan from "../../components/Cis/Stundenplan/Stundenplan";
import MylvStudent from "../../components/Cis/Mylv/Student";
import Profil from "../../components/Cis/Profil/Profil";
import CmsNews from "../../components/Cis/Cms/News";
import CmsContent from "../../components/Cis/Cms/Content";
import Info from "../../components/Cis/Mylv/Semester/Studiengang/Lv/Info";
const ciPath = FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, '') + FHC_JS_DATA_STORAGE_OBJECT.ci_router;
const router = VueRouter.createRouter({
history: VueRouter.createWebHistory(`/${ciPath}`),
routes: [
// {
// path: `/Cis/News`,
// name: 'Profil',
// component: Profil,
// props: true
// },
// {
// path: `/Cis/Profil`,
// name: 'Profil',
// component: Profil,
// props: true
// },
// {
// path: `/Cis/Profil/View/`,
// name: 'Profil',
// component: Profil,
// props: true
// },
{
path: `/CisVue/Cms/Content/:content_id`,
name: 'Content',
component: CmsContent,
props: true
},
{
path: `/CisVue/Cms/News`,
name: 'News',
component: CmsNews,
props: true
},
{
path: `/Cis/MyLv`,
name: 'MyLv',
component: MylvStudent,
props: true
},
{
path: `/Cis/MyLv/Info/:studien_semester/:lehrveranstaltung_id`,
name: 'LvInfo',
component: Info,
props: true
},
{
path: `/Cis/Stundenplan/:lv_id?`,
name: 'Stundenplan',
@@ -39,39 +59,24 @@ const router = VueRouter.createRouter({
path: `/`,
name: 'FhcDashboard',
component: FhcDashboard,
props: {dashboard: 'CIS'}
props: {dashboard: 'CIS'},
},
{
path: '/:catchAll(.*)',
redirect: {name: 'FhcDashboard'},
props: true
}
path: `/Cis4`,
name: 'Cis4',
component: FhcDashboard,
props: {dashboard: 'CIS'},
},
// only use the catchAll route if every cis4 Route is being handled in vue router, currently Profil is being
// codeigniter routed
// {
// path: '/:catchAll(.*)',
// redirect: {name: 'FhcDashboard'},
// props: true
// }
]
})
router.beforeEach((to, from) => {
console.log('from', from)
console.log('to', to)
})
router.beforeResolve(async to => {
// TODO: check if necessary viewData params have been provided
// if (to.meta.requiresCamera) {
// try {
// await askForCameraPermission()
// } catch (error) {
// if (error instanceof NotAllowedError) {
// // ... handle the error and then cancel the navigation
// return false
// } else {
// // unexpected error, cancel the navigation and pass the error to the global handler
// throw error
// }
// }
// }
})
const app = Vue.createApp({
name: 'FhcApp',
data: () => ({
@@ -85,19 +90,21 @@ const app = Vue.createApp({
},
handleClick(event) {
const target = event.target.closest('a');
// TODO: handle case of is internalRoute but not defined in vue router
if (target && this.isInternalRoute(target.href)) {
event.preventDefault(); // Prevent browser navigation
const path = new URL(target.href).pathname
const base = this.$router.options.history.base
const route = path.replace(base, '') || '/'
// let click event propagate normally if we dont route internally
const res = this.$router.resolve(route)
if(!res?.matched?.length) return
event.preventDefault(); // Prevent browser navigation
this.$router.push(route);
}
},
tryCis4Navigate(e) {
this.$router.push({name: e.detail});
},
getInitialRoute() {
const el = document.getElementById('fhccontent')
const r = el?.getAttribute('route')
@@ -106,9 +113,9 @@ const app = Vue.createApp({
}
},
mounted() {
// window.addEventListener('beforeunload', this.beforeUnloadListener)
document.addEventListener('click', this.handleClick);
window.addEventListener('fhcnavigate', this.tryCis4Navigate);
// TODO: handle required property content_id
this.$router.push({name: this.getInitialRoute()});
},
beforeUnmount() {
@@ -116,9 +123,9 @@ const app = Vue.createApp({
},
});
// kind of a bandaid for bad css on some pages to avoid horizontal scroll
setScrollbarWidth();
app.use(router);
window.fhcVueRouter = router
app.use(FhcApi);
app.use(primevue.config.default, {
zIndex: {
+1 -1
View File
@@ -6,7 +6,7 @@ export default {
props: {
content_id: {
type: [Number, String],
required: true,
required: true
},
version: {
type: [String, Number],
@@ -1,4 +1,4 @@
import { CoreFilterCmpt } from "../../../components/filter/Filter.js";
import {CoreFilterCmpt} from "../../../components/filter/Filter.js";
import EditProfil from "./ProfilModal/EditProfil.js";
import Adresse from "./ProfilComponents/Adresse.js";
import Kontakt from "./ProfilComponents/Kontakt.js";
@@ -11,475 +11,409 @@ import RoleInformation from "./ProfilComponents/RoleInformation.js";
import ProfilInformation from "./ProfilComponents/ProfilInformation.js";
export default {
components: {
CoreFilterCmpt,
EditProfil,
Adresse,
Kontakt,
FetchProfilUpdates,
AusweisStatus,
Mailverteiler,
QuickLinks,
ProfilEmails,
RoleInformation,
ProfilInformation,
},
components: {
CoreFilterCmpt,
EditProfil,
Adresse,
Kontakt,
FetchProfilUpdates,
AusweisStatus,
Mailverteiler,
QuickLinks,
ProfilEmails,
RoleInformation,
ProfilInformation,
},
inject: ["sortProfilUpdates", "collapseFunction"],
inject: ["sortProfilUpdates", "collapseFunction"],
data() {
return {
showModal: false,
editDataFilter: null,
data() {
return {
showModal: false,
editDataFilter: null,
// tabulator options
funktionen_table_options: {
height: 300,
layout: "fitColumns",
responsiveLayout: "collapse",
responsiveLayoutCollapseUseFormatters: false,
responsiveLayoutCollapseFormatter: Vue.$collapseFormatter,
data: [
{
Bezeichnung: "",
Organisationseinheit: "",
Gültig_von: "",
Gültig_bis: "",
Wochenstunden: "",
},
],
columns: [
{
title:
"<i id='collapseIconFunktionen' role='button' class='fa-solid fa-angle-down '></i>",
field: "collapse",
headerSort: false,
headerFilter: false,
formatter: "responsiveCollapse",
maxWidth: 40,
headerClick: this.collapseFunction,
},
{
title: "Bezeichnung",
field: "Bezeichnung",
headerFilter: true,
minWidth: 200,
},
{
title: "Organisationseinheit",
field: "Organisationseinheit",
headerFilter: true,
minWidth: 200,
},
{
title: "Gültig_von",
field: "Gültig_von",
headerFilter: true,
resizable: true,
minWidth: 200,
},
{
title: "Gültig_bis",
field: "Gültig_bis",
headerFilter: true,
resizable: true,
minWidth: 200,
},
{
title: "Wochenstunden",
field: "Wochenstunden",
headerFilter: true,
minWidth: 200,
},
],
},
// tabulator options
funktionen_table_options: {
height: 300,
layout: "fitColumns",
responsiveLayout: "collapse",
responsiveLayoutCollapseUseFormatters: false,
responsiveLayoutCollapseFormatter: Vue.$collapseFormatter,
data: [
{
Bezeichnung: "",
Organisationseinheit: "",
Gültig_von: "",
Gültig_bis: "",
Wochenstunden: "",
},
],
columns: [
{
title:
"<i id='collapseIconFunktionen' role='button' class='fa-solid fa-angle-down '></i>",
field: "collapse",
headerSort: false,
headerFilter: false,
formatter: "responsiveCollapse",
maxWidth: 40,
headerClick: this.collapseFunction,
},
{
title: "Bezeichnung",
field: "Bezeichnung",
headerFilter: true,
minWidth: 200,
},
{
title: "Organisationseinheit",
field: "Organisationseinheit",
headerFilter: true,
minWidth: 200,
},
{
title: "Gültig_von",
field: "Gültig_von",
headerFilter: true,
resizable: true,
minWidth: 200,
},
{
title: "Gültig_bis",
field: "Gültig_bis",
headerFilter: true,
resizable: true,
minWidth: 200,
},
{
title: "Wochenstunden",
field: "Wochenstunden",
headerFilter: true,
minWidth: 200,
},
],
},
betriebsmittel_table_options: {
height: 300,
layout: "fitColumns",
responsiveLayout: "collapse",
responsiveLayoutCollapseUseFormatters: false,
responsiveLayoutCollapseFormatter: Vue.$collapseFormatter,
data: [{ betriebsmittel: "", Nummer: "", Ausgegeben_am: "" }],
columns: [
{
title:
"<i id='collapseIconBetriebsmittel' role='button' class='fa-solid fa-angle-down '></i>",
field: "collapse",
headerSort: false,
headerFilter: false,
formatter: "responsiveCollapse",
maxWidth: 40,
headerClick: this.collapseFunction,
},
{
title: "Betriebsmittel",
field: "betriebsmittel",
headerFilter: true,
minWidth: 200,
},
{
title: "Nummer",
field: "Nummer",
headerFilter: true,
resizable: true,
minWidth: 200,
},
{
title: "Ausgegeben_am",
field: "Ausgegeben_am",
headerFilter: true,
minWidth: 200,
},
],
},
};
},
betriebsmittel_table_options: {
height: 300,
layout: "fitColumns",
responsiveLayout: "collapse",
responsiveLayoutCollapseUseFormatters: false,
responsiveLayoutCollapseFormatter: Vue.$collapseFormatter,
data: [{betriebsmittel: "", Nummer: "", Ausgegeben_am: ""}],
columns: [
{
title:
"<i id='collapseIconBetriebsmittel' role='button' class='fa-solid fa-angle-down '></i>",
field: "collapse",
headerSort: false,
headerFilter: false,
formatter: "responsiveCollapse",
maxWidth: 40,
headerClick: this.collapseFunction,
},
{
title: "Betriebsmittel",
field: "betriebsmittel",
headerFilter: true,
minWidth: 200,
},
{
title: "Nummer",
field: "Nummer",
headerFilter: true,
resizable: true,
minWidth: 200,
},
{
title: "Ausgegeben_am",
field: "Ausgegeben_am",
headerFilter: true,
minWidth: 200,
},
],
},
};
},
props: {
data: Object,
editData: Object,
},
props: {
data: Object,
editData: Object,
},
methods: {
betriebsmittelTableBuilt: function () {
this.$refs.betriebsmittelTable.tabulator.setData(this.data.mittel);
},
funktionenTableBuilt: function () {
this.$refs.funktionenTable.tabulator.setData(this.data.funktionen);
},
hideEditProfilModal: function () {
//? checks the editModal component property result, if the user made a successful request or not
if (this.$refs.editModal.result) {
this.$fhcApi.factory.profilUpdate.selectProfilRequest()
.then((request) => {
if (!request.error && request) {
this.data.profilUpdates = request.data;
this.data.profilUpdates.sort(this.sortProfilUpdates);
} else {
console.error("Error when fetching profile updates: " + res.data);
}
})
.catch((err) => {
console.error(err);
});
} else {
// when modal was closed without submitting request
}
this.showModal = false;
this.editDataFilter = null;
},
methods: {
betriebsmittelTableBuilt: function () {
this.$refs.betriebsmittelTable.tabulator.setData(this.data.mittel);
},
funktionenTableBuilt: function () {
this.$refs.funktionenTable.tabulator.setData(this.data.funktionen);
},
hideEditProfilModal: function () {
//? checks the editModal component property result, if the user made a successful request or not
if (this.$refs.editModal.result) {
this.$fhcApi.factory.profilUpdate.selectProfilRequest()
.then((request) => {
if (!request.error && request) {
this.data.profilUpdates = request.data;
this.data.profilUpdates.sort(this.sortProfilUpdates);
} else {
console.error("Error when fetching profile updates: " + res.data);
}
})
.catch((err) => {
console.error(err);
});
} else {
// when modal was closed without submitting request
}
this.showModal = false;
this.editDataFilter = null;
},
showEditProfilModal(view) {
if (view) {
this.editDataFilter = view;
}
showEditProfilModal(view) {
if (view) {
this.editDataFilter = view;
}
this.showModal = true;
Vue.nextTick(() => {
this.$refs.editModal.show();
});
this.showModal = true;
Vue.nextTick(() => {
this.$refs.editModal.show();
});
// after a state change, wait for the DOM updates to complete
},
// after a state change, wait for the DOM updates to complete
},
fetchProfilUpdates: function () {
this.$fhcApi.factory.profilUpdate.selectProfilRequest().then((res) => {
if (!res.error && res) {
this.data.profilUpdates = res.data?.length
? res.data.sort(this.sortProfilUpdates)
: null;
}
});
},
},
fetchProfilUpdates: function () {
this.$fhcApi.factory.profilUpdate.selectProfilRequest().then((res) => {
if (!res.error && res) {
this.data.profilUpdates = res.data?.length
? res.data.sort(this.sortProfilUpdates)
: null;
}
});
},
},
computed: {
editable() {
return this.data?.editAllowed ?? false;
},
filteredEditData() {
return this.editDataFilter
? this.editData.data[this.editDataFilter]
: this.editData;
},
profilInformation() {
if (!this.data) {
return {};
}
computed: {
editable() {
return this.data?.editAllowed ?? false;
},
filteredEditData() {
return this.editDataFilter
? this.editData.data[this.editDataFilter]
: this.editData;
},
profilInformation() {
if (!this.data) {
return {};
}
return {
Vorname: this.data.vorname,
Nachname: this.data.nachname,
Username: this.data.username,
Anrede: this.data.anrede,
Titel: this.data.titel,
Postnomen: this.data.postnomen,
foto_sperre: this.data.foto_sperre,
foto: this.data.foto,
};
},
return {
Vorname: this.data.vorname,
Nachname: this.data.nachname,
Username: this.data.username,
Anrede: this.data.anrede,
Titel: this.data.titel,
Postnomen: this.data.postnomen,
foto_sperre: this.data.foto_sperre,
foto: this.data.foto,
};
},
roleInformation() {
if (!this.data) {
return {};
}
roleInformation() {
if (!this.data) {
return {};
}
return {
[`${this.$p.t('profil','Geburtsdatum')}`]: this.data.gebdatum,
[`${this.$p.t('profil', 'Geburtsort')}`]: this.data.gebort,
[`${this.$p.t('profil', 'Kurzzeichen')}`]: this.data.kurzbz,
[`${this.$p.t('profil', 'Telefon')}`]:
(this.data.standort_telefon ? this.data.standort_telefon + " " + this.data.telefonklappe : this.data.telefonklappe),
[`${this.$p.t('profil', 'Büro')}`]: this.data.ort_kurzbz,
};
},
},
return {
[`${this.$p.t('profil', 'Geburtsdatum')}`]: this.data.gebdatum,
[`${this.$p.t('profil', 'Geburtsort')}`]: this.data.gebort,
[`${this.$p.t('profil', 'Kurzzeichen')}`]: this.data.kurzbz,
[`${this.$p.t('profil', 'Telefon')}`]:
(this.data.standort_telefon ? this.data.standort_telefon + " " + this.data.telefonklappe : this.data.telefonklappe),
[`${this.$p.t('profil', 'Büro')}`]: this.data.ort_kurzbz,
};
},
},
created() {
//? sorts the profil Updates: pending -> accepted -> rejected
this.data.profilUpdates?.sort(this.sortProfilUpdates);
},
mounted(){
},
created() {
//? sorts the profil Updates: pending -> accepted -> rejected
this.data.profilUpdates?.sort(this.sortProfilUpdates);
template: /*html*/ `
<div class="container-fluid text-break fhc-form" >
},
mounted() {
},
template: /*html*/ `
<div class="container-fluid text-break fhc-form" >
<edit-profil v-if="showModal" ref="editModal" @hideBsModal="hideEditProfilModal" :value="JSON.parse(JSON.stringify(filteredEditData))" :title="$p.t('profil','profilBearbeiten')"></edit-profil>
<div class="row">
<div class="d-md-none col-12 ">
<!--TODO: uncomment when implemented
<div class="row mb-3">
<div class="row">
<div class="d-md-none col-12 ">
<!--TODO: uncomment when implemented
<div class="row mb-3">
<div class="col">
<quick-links :title="$p.t('profil','quickLinks')" :mobile="true"></quick-links>
</div>
</div>-->
<!-- Bearbeiten Button -->
<div class="row mb-3 ">
<div class="col">
<quick-links :title="$p.t('profil','quickLinks')" :mobile="true"></quick-links>
</div>
</div>-->
<!-- Bearbeiten Button -->
<div class="row mb-3 ">
<div class="col">
<button @click="()=>showEditProfilModal()" type="button" class="text-start w-100 btn btn-outline-secondary" >
<div class="row">
<div class="col-auto">
<i class="fa fa-edit"></i>
</div>
<div class="col-auto">{{$p.t('ui','bearbeiten')}}</div>
</div>
</button>
</div>
</div>
<div v-if="data.profilUpdates" class="row mb-3">
<div class="col">
<!-- MOBILE PROFIL UPDATES -->
<fetch-profil-updates v-if="data.profilUpdates && data.profilUpdates.length" @fetchUpdates="fetchProfilUpdates" :data="data.profilUpdates" ></fetch-profil-updates>
</div>
</div>
</div>
<!-- END OF HIDDEN ROW (HIDDEN IN VIEWPORTS GREATER THEN-EQUAL MD) -->
<!-- MAIN PANNEL -->
<div class="col-sm-12 col-md-8 col-xxl-9 ">
<!-- ROW WITH PROFIL IMAGE AND INFORMATION -->
<!-- INFORMATION CONTENT START -->
<!-- ROW WITH THE PROFIL INFORMATION -->
<div class="row mb-4">
<div class="col-lg-12 col-xl-6 ">
<div class="row mb-4">
<div class="col">
<!-- PROFIL INFORMATION -->
<profil-information @showEditProfilModal="showEditProfilModal" :title="$p.t('profil','mitarbeiterIn')" :data="profilInformation" :editable="editable"></profil-information>
</div>
</div>
<div class="row mb-4">
<div class=" col-lg-12">
<!-- MITARBEITER INFO -->
<role-information :title="$p.t('profil','mitarbeiterInformation')" :data="roleInformation"></role-information>
</div>
</div>
<!-- START OF SECOND PROFIL INFORMATION COLUMN -->
</div>
<div class="col-xl-6 col-lg-12 ">
<div class="row mb-4">
<div class="col">
<!-- EMAILS -->
<profil-emails :title="this.$p.t('person','email')" :data="data.emails" ></profil-emails>
</div>
</div>
<div class="row mb-4 ">
<div class="col">
<!-- PRIVATE KONTAKTE-->
<div class="card">
<div class="card-header">
<div class="row">
<div @click="showEditProfilModal('Private_Kontakte')" class="col-auto" type="button">
<button @click="()=>showEditProfilModal()" type="button" class="text-start w-100 btn btn-outline-secondary" >
<div class="row">
<div class="col-auto">
<i class="fa fa-edit"></i>
</div>
<div class="col">
<span>{{$p.t('profil','privateKontakte')}}</span>
</div>
</div>
</div>
<div class="card-body ">
<div class="gy-3 row ">
<div v-for="element in data.kontakte" class="col-12">
<Kontakt :data="element"></Kontakt>
</div>
</div>
</div>
<div class="col-auto">{{$p.t('ui','bearbeiten')}}</div>
</div>
</div>
</div>
<div class="row mb-4">
<div class="col">
<!-- PRIVATE ADRESSEN-->
<div class="card">
<div class="card-header">
<div class="row">
<div @click="showEditProfilModal('Private_Adressen')" class="col-auto" type="button">
<i class="fa fa-edit"></i>
</div>
<div class="col">
<span>{{$p.t('profil','privateAdressen')}}</span>
</div>
</div>
</div>
<div class="card-body">
<div class="gy-3 row ">
<div v-for="element in data.adressen" class="col-12">
<Adresse :data="element"></Adresse>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div >
<div class="row">
<div class="col-12 mb-4" >
<!-- FUNKTIONEN TABELLE -->
<core-filter-cmpt @tableBuilt="funktionenTableBuilt" :title="$p.t('person','funktionen')" ref="funktionenTable" :tabulator-options="funktionen_table_options" tableOnly :sideMenu="false" />
</div>
<div class="col-12 mb-4" >
<!-- BETRIEBSMITTEL TABELLE -->
<core-filter-cmpt @tableBuilt="betriebsmittelTableBuilt" :title="$p.t('profil','entlehnteBetriebsmittel')" ref="betriebsmittelTable" :tabulator-options="betriebsmittel_table_options" tableOnly :sideMenu="false" />
</div>
</button>
</div>
</div>
<!-- START OF SIDE PANEL -->
<div class="col-md-4 col-xxl-3 col-sm-12 text-break" >
<!--TODO: uncomment when implemented
<div class="row d-none d-md-block mb-3">
</div>
<div v-if="data.profilUpdates" class="row mb-3">
<div class="col">
<quick-links :title="$p.t('profil','quickLinks')"></quick-links>
</div>
</div>-->
<!-- Bearbeiten Button -->
<div class="row d-none d-md-block ">
<div class="col mb-3">
<button @click="()=>showEditProfilModal()" type="button" class="text-start w-100 btn btn-outline-secondary" >
<div class="row">
<div class="col-auto">
<i class="fa fa-edit"></i>
<!-- MOBILE PROFIL UPDATES -->
<fetch-profil-updates v-if="data.profilUpdates && data.profilUpdates.length" @fetchUpdates="fetchProfilUpdates" :data="data.profilUpdates" ></fetch-profil-updates>
</div>
</div>
</div>
<!-- END OF HIDDEN ROW (HIDDEN IN VIEWPORTS GREATER THEN-EQUAL MD) -->
<!-- MAIN PANNEL -->
<div class="col-sm-12 col-md-8 col-xxl-9 ">
<!-- ROW WITH PROFIL IMAGE AND INFORMATION -->
<!-- INFORMATION CONTENT START -->
<!-- ROW WITH THE PROFIL INFORMATION -->
<div class="row mb-4">
<div class="col-lg-12 col-xl-6 ">
<div class="row mb-4">
<div class="col">
<!-- PROFIL INFORMATION -->
<profil-information @showEditProfilModal="showEditProfilModal" :title="$p.t('profil','mitarbeiterIn')" :data="profilInformation" :editable="editable"></profil-information>
</div>
</div>
<div class="col-auto">{{$p.t('ui','bearbeiten')}}</div>
</div>
</button>
<div class="row mb-4">
<div class=" col-lg-12">
<!-- MITARBEITER INFO -->
<role-information :title="$p.t('profil','mitarbeiterInformation')" :data="roleInformation"></role-information>
</div>
</div>
<!-- START OF SECOND PROFIL INFORMATION COLUMN -->
</div>
<div class="col-xl-6 col-lg-12 ">
<div class="row mb-4">
<div class="col">
<!-- EMAILS -->
<profil-emails :title="this.$p.t('person','email')" :data="data.emails" ></profil-emails>
</div>
</div>
<div class="row mb-4 ">
<div class="col">
<!-- PRIVATE KONTAKTE-->
<div class="card">
<div class="card-header">
<div class="row">
<div @click="showEditProfilModal('Private_Kontakte')" class="col-auto" type="button">
<i class="fa fa-edit"></i>
</div>
<div class="col">
<span>{{$p.t('profil','privateKontakte')}}</span>
</div>
</div>
</div>
<div class="card-body ">
<div class="gy-3 row ">
<div v-for="element in data.kontakte" class="col-12">
<Kontakt :data="element"></Kontakt>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row mb-4">
<div class="col">
<!-- PRIVATE ADRESSEN-->
<div class="card">
<div class="card-header">
<div class="row">
<div @click="showEditProfilModal('Private_Adressen')" class="col-auto" type="button">
<i class="fa fa-edit"></i>
</div>
<div class="col">
<span>{{$p.t('profil','privateAdressen')}}</span>
</div>
</div>
</div>
<div class="card-body">
<div class="gy-3 row ">
<div v-for="element in data.adressen" class="col-12">
<Adresse :data="element"></Adresse>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div v-if="data.profilUpdates" class="row d-none d-md-block mb-3">
</div >
<div class="row">
<div class="col-12 mb-4" >
<!-- FUNKTIONEN TABELLE -->
<core-filter-cmpt @tableBuilt="funktionenTableBuilt" :title="$p.t('person','funktionen')" ref="funktionenTable" :tabulator-options="funktionen_table_options" tableOnly :sideMenu="false" />
</div>
<div class="col-12 mb-4" >
<!-- BETRIEBSMITTEL TABELLE -->
<core-filter-cmpt @tableBuilt="betriebsmittelTableBuilt" :title="$p.t('profil','entlehnteBetriebsmittel')" ref="betriebsmittelTable" :tabulator-options="betriebsmittel_table_options" tableOnly :sideMenu="false" />
</div>
</div>
</div>
<!-- START OF SIDE PANEL -->
<div class="col-md-4 col-xxl-3 col-sm-12 text-break" >
<!--TODO: uncomment when implemented
<div class="row d-none d-md-block mb-3">
<div class="col">
<quick-links :title="$p.t('profil','quickLinks')"></quick-links>
</div>
</div>-->
<!-- Bearbeiten Button -->
<div class="row d-none d-md-block ">
<div class="col mb-3">
<button @click="()=>showEditProfilModal()" type="button" class="text-start w-100 btn btn-outline-secondary" >
<div class="row">
<div class="col-auto">
<i class="fa fa-edit"></i>
</div>
<div class="col-auto">{{$p.t('ui','bearbeiten')}}</div>
</div>
</button>
</div>
</div>
<div v-if="data.profilUpdates" class="row d-none d-md-block mb-3">
<div class="col mb-3">
<!-- PROFIL UPDATES -->
<fetch-profil-updates v-if="data.profilUpdates && data.profilUpdates.length" @fetchUpdates="fetchProfilUpdates" :data="data.profilUpdates"></fetch-profil-updates>
</div>
</div>
<div class="row mb-3" >
</div>
<div class="row mb-3" >
<div class="col-12">
<!-- AUSWEIS STATUS -->
<ausweis-status :data="data.zutrittsdatum"></ausweis-status>
</div>
<!-- AUSWEIS STATUS -->
<ausweis-status :data="data.zutrittsdatum"></ausweis-status>
</div>
<div class="row">
<div class="col">
<!-- MAILVERTEILER -->
</div>
<div class="row">
<div class="col">
<!-- MAILVERTEILER -->
<mailverteiler :data="data?.mailverteiler" :title="$p.t('profil','mailverteiler')"></mailverteiler>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`,
};
@@ -1,4 +1,4 @@
import { CoreFilterCmpt } from "../../../components/filter/Filter.js";
import {CoreFilterCmpt} from "../../../components/filter/Filter.js";
import Mailverteiler from "./ProfilComponents/Mailverteiler.js";
import QuickLinks from "./ProfilComponents/QuickLinks.js";
import RoleInformation from "./ProfilComponents/RoleInformation.js";
@@ -6,280 +6,219 @@ import ProfilEmails from "./ProfilComponents/ProfilEmails.js";
import ProfilInformation from "./ProfilComponents/ProfilInformation.js";
export default {
components: {
CoreFilterCmpt,
Mailverteiler,
QuickLinks,
RoleInformation,
ProfilEmails,
ProfilInformation,
},
inject: ["collapseFunction"],
data() {
return {
collapseIconFunktionen: true,
components: {
CoreFilterCmpt,
Mailverteiler,
QuickLinks,
RoleInformation,
ProfilEmails,
ProfilInformation,
},
inject: ["collapseFunction"],
data() {
return {
collapseIconFunktionen: true,
funktionen_table_options: {
height: 300,
layout: "fitColumns",
responsiveLayout: "collapse",
responsiveLayoutCollapseUseFormatters: false,
responsiveLayoutCollapseFormatter: Vue.$collapseFormatter,
data: [
{
Bezeichnung: "",
Organisationseinheit: "",
Gültig_von: "",
Gültig_bis: "",
Wochenstunden: "",
},
],
columns: [
//? option when wanting to hide the collapsed list
funktionen_table_options: {
height: 300,
layout: "fitColumns",
responsiveLayout: "collapse",
responsiveLayoutCollapseUseFormatters: false,
responsiveLayoutCollapseFormatter: Vue.$collapseFormatter,
data: [
{
Bezeichnung: "",
Organisationseinheit: "",
Gültig_von: "",
Gültig_bis: "",
Wochenstunden: "",
},
],
columns: [
//? option when wanting to hide the collapsed list
{
title:
"<i id='collapseIconFunktionen' role='button' class='fa-solid fa-angle-down '></i>",
field: "collapse",
headerSort: false,
headerFilter: false,
formatter: "responsiveCollapse",
maxWidth: 40,
headerClick: this.collapseFunction,
},
{
title: "Bezeichnung",
field: "Bezeichnung",
headerFilter: true,
minWidth: 200,
},
{
title: "Organisationseinheit",
field: "Organisationseinheit",
headerFilter: true,
minWidth: 200,
},
{
title: "Gültig_von",
field: "Gültig_von",
headerFilter: true,
resizable: true,
minWidth: 200,
},
{
title: "Gültig_bis",
field: "Gültig_bis",
headerFilter: true,
resizable: true,
minWidth: 200,
},
{
title: "Wochenstunden",
field: "Wochenstunden",
headerFilter: true,
minWidth: 200,
},
],
},
};
},
{
title:
"<i id='collapseIconFunktionen' role='button' class='fa-solid fa-angle-down '></i>",
field: "collapse",
headerSort: false,
headerFilter: false,
formatter: "responsiveCollapse",
maxWidth: 40,
headerClick: this.collapseFunction,
},
{
title: "Bezeichnung",
field: "Bezeichnung",
headerFilter: true,
minWidth: 200,
},
{
title: "Organisationseinheit",
field: "Organisationseinheit",
headerFilter: true,
minWidth: 200,
},
{
title: "Gültig_von",
field: "Gültig_von",
headerFilter: true,
resizable: true,
minWidth: 200,
},
{
title: "Gültig_bis",
field: "Gültig_bis",
headerFilter: true,
resizable: true,
minWidth: 200,
},
{
title: "Wochenstunden",
field: "Wochenstunden",
headerFilter: true,
minWidth: 200,
},
],
},
};
},
//? this is the prop passed to the dynamic component with the custom data of the view
props: ["data"],
methods: {
funktionenTableBuilt: function () {
this.$refs.funktionenTable.tabulator.setData(this.data.funktionen);
},
},
//? this is the prop passed to the dynamic component with the custom data of the view
props: ["data"],
methods: {
funktionenTableBuilt: function () {
this.$refs.funktionenTable.tabulator.setData(this.data.funktionen);
},
},
computed: {
editable() {
return this.data?.editAllowed ?? false;
},
personEmails() {
return this.data?.emails ? this.data.emails : [];
},
computed: {
editable() {
return this.data?.editAllowed ?? false;
},
profilInformation() {
if (!this.data) {
return {};
}
personEmails() {
return this.data?.emails ? this.data.emails : [];
},
return {
Vorname: this.data.vorname,
Nachname: this.data.nachname,
Username: this.data.username,
Anrede: this.data.anrede,
Titel: this.data.titel,
Postnomen: this.data.postnomen,
foto_sperre: this.data.foto_sperre,
foto: this.data.foto,
};
},
profilInformation() {
if (!this.data) {
return {};
}
roleInformation() {
if (!this.data) {
return {};
}
return {
Vorname: this.data.vorname,
Nachname: this.data.nachname,
Username: this.data.username,
Anrede: this.data.anrede,
Titel: this.data.titel,
Postnomen: this.data.postnomen,
foto_sperre: this.data.foto_sperre,
foto: this.data.foto,
};
},
return {
[`${this.$p.t('profil', 'Geburtsdatum')}`]: this.data.gebdatum,
[`${this.$p.t('profil', 'Geburtsort')}`]: this.data.gebort,
[`${this.$p.t('profil', 'Kurzzeichen')}`]: this.data.kurzbz,
[`${this.$p.t('profil', 'Telefon')}`]:
(this.data.standort_telefon ? this.data.standort_telefon + " " + this.data.telefonklappe : this.data.telefonklappe),
[`${this.$p.t('profil', 'Büro')}`]: this.data.ort_kurzbz,
};
},
},
roleInformation() {
if (!this.data) {
return {};
}
template: /*html*/ `
return {
[`${this.$p.t('profil', 'Geburtsdatum')}`]: this.data.gebdatum,
[`${this.$p.t('profil', 'Geburtsort')}`]: this.data.gebort,
[`${this.$p.t('profil', 'Kurzzeichen')}`]: this.data.kurzbz,
[`${this.$p.t('profil', 'Telefon')}`]:
(this.data.standort_telefon ? this.data.standort_telefon + " " + this.data.telefonklappe : this.data.telefonklappe),
[`${this.$p.t('profil', 'Büro')}`]: this.data.ort_kurzbz,
};
},
},
<div class="container-fluid text-break fhc-form" >
template: /*html*/ `
<div class="container-fluid text-break fhc-form" >
<!-- ROW -->
<div class="row">
<!-- HIDDEN QUICK LINKS -->
<!-- TODO: uncomment when implemented
<div class="d-md-none col-12 ">
<quick-links :title="$p.t('profil','quickLinks')" :mobile="true" ></quick-links>
</div>
-->
<!-- END OF HIDDEN QUCK LINKS -->
<!-- MAIN PANNEL -->
<div class="col-sm-12 col-md-8 col-xxl-9 ">
<!-- ROW WITH PROFIL IMAGE AND INFORMATION -->
<!-- INFORMATION CONTENT START -->
<!-- ROW WITH THE PROFIL INFORMATION -->
<div class="row">
<!-- HIDDEN QUICK LINKS -->
<!-- TODO: uncomment when implemented
<div class="d-md-none col-12 ">
<quick-links :title="$p.t('profil','quickLinks')" :mobile="true" ></quick-links>
</div>
-->
<!-- END OF HIDDEN QUCK LINKS -->
<!-- MAIN PANNEL -->
<div class="col-sm-12 col-md-8 col-xxl-9 ">
<!-- ROW WITH PROFIL IMAGE AND INFORMATION -->
<!-- INFORMATION CONTENT START -->
<!-- ROW WITH THE PROFIL INFORMATION -->
<div class="row mb-4">
<!-- FIRST KAESTCHEN -->
<div class="col-lg-12 col-xl-6 ">
<div class="row mb-4">
<!-- FIRST KAESTCHEN -->
<div class="col-lg-12 col-xl-6 ">
<div class="row mb-4">
<div class="col">
<!-- Profil Informationen -->
<profil-information :title="$p.t('profil','mitarbeiterIn')" :data="profilInformation" :editable="editable"></profil-information>
</div>
<div class="col">
<!-- Profil Informationen -->
<profil-information :title="$p.t('profil','mitarbeiterIn')" :data="profilInformation" :editable="editable"></profil-information>
</div>
</div>
<!-- START OF SECOND PROFIL INFORMATION COLUMN -->
<!-- START OF SECOND PROFIL INFORMATION COLUMN -->
<!-- END OF PROFIL INFORMATION ROW -->
<!-- INFORMATION CONTENT END -->
</div>
<div class="col-xl-6 col-lg-12 ">
</div>
<div class="col-xl-6 col-lg-12 ">
<div class="row mb-4">
<div class="col">
<!-- EMAILS -->
<profil-emails :title="this.$p.t('person','email')" :data="personEmails"></profil-emails>
</div></div>
<div class="col">
<!-- EMAILS -->
<profil-emails :title="this.$p.t('person','email')" :data="personEmails"></profil-emails>
</div>
</div>
<!-- SECOND ROW OF SECOND COLUMN IN MAIN CONTENT -->
<div class="row mb-4">
<div class=" col-lg-12">
<!-- roleInformation -->
<role-information :data="roleInformation" :title="$p.t('profil','mitarbeiterInformation')"></role-information>
<div class=" col-lg-12">
<!-- roleInformation -->
<role-information :data="roleInformation" :title="$p.t('profil','mitarbeiterInformation')"></role-information>
</div>
</div>
</div>
<!-- END OF SECOND ROW OF SECOND COLUMN IN MAIN CONTENT -->
<!-- END OF SECOND ROW OF SECOND COLUMN IN MAIN CONTENT -->
<!-- END OF THE SECOND INFORMATION COLUMN -->
</div>
<!-- START OF THE SECOND PROFIL INFORMATION ROW -->
<!-- ROW WITH PROFIL IMAGE AND INFORMATION END -->
</div >
<!-- SECOND ROW UNDER THE PROFIL IMAGE AND INFORMATION WITH THE TABLES -->
<div class="row">
<!-- FIRST TABLE -->
<div class="col-12 mb-4" >
<core-filter-cmpt @tableBuilt="funktionenTableBuilt" :title="$p.t('person','funktionen')" ref="funktionenTable" :tabulator-options="funktionen_table_options" tableOnly :sideMenu="false" />
</div>
<!-- END OF THE ROW WITH THE TABLES UNDER THE PROFIL INFORMATION -->
</div>
<!-- END OF MAIN CONTENT COL -->
</div>
<!-- START OF SIDE PANEL -->
<div class="col-md-4 col-xxl-3 col-sm-12 text-break" >
<!-- VISIBLE UNTIL VIEWPORT MD -->
<!--TODO: uncomment when implemented
<!-- START OF THE SECOND PROFIL INFORMATION ROW -->
<!-- ROW WITH PROFIL IMAGE AND INFORMATION END -->
</div >
<!-- SECOND ROW UNDER THE PROFIL IMAGE AND INFORMATION WITH THE TABLES -->
<div class="row">
<!-- FIRST TABLE -->
<div class="col-12 mb-4" >
<core-filter-cmpt @tableBuilt="funktionenTableBuilt" :title="$p.t('person','funktionen')" ref="funktionenTable" :tabulator-options="funktionen_table_options" tableOnly :sideMenu="false" />
</div>
<!-- END OF THE ROW WITH THE TABLES UNDER THE PROFIL INFORMATION -->
</div>
<!-- END OF MAIN CONTENT COL -->
</div>
<!-- START OF SIDE PANEL -->
<div class="col-md-4 col-xxl-3 col-sm-12 text-break" >
<!-- VISIBLE UNTIL VIEWPORT MD -->
<!--TODO: uncomment when implemented
<div class="row d-none d-md-block mb-3">
<div class="col">
<quick-links :title="$p.t('profil','quickLinks')" ></quick-links>
</div>
</div>
-->
<div class="row">
<div class="col">
<!-- MAILVERTEILER -->
<mailverteiler :data="data?.mailverteiler" :title="$p.t('profil','mailverteiler')"></mailverteiler>
<quick-links :title="$p.t('profil','quickLinks')" ></quick-links>
</div>
</div>
<!-- END OF SIDE PANEL -->
</div>
<!-- END OF CONTAINER ROW-->
</div>
<!-- END OF CONTAINER -->
</div>
`,
-->
<div class="row">
<div class="col">
<!-- MAILVERTEILER -->
<mailverteiler :data="data?.mailverteiler" :title="$p.t('profil','mailverteiler')"></mailverteiler>
</div>
</div>
<!-- END OF SIDE PANEL -->
</div>
<!-- END OF CONTAINER ROW-->
</div>
<!-- END OF CONTAINER -->
</div>
`,
};
@@ -5,185 +5,142 @@ import RoleInformation from "./ProfilComponents/RoleInformation.js";
import ProfilInformation from "./ProfilComponents/ProfilInformation.js";
export default {
data() {
return {};
},
components: {
QuickLinks,
Mailverteiler,
ProfilEmails,
RoleInformation,
ProfilInformation,
},
data() {
return {};
},
components: {
QuickLinks,
Mailverteiler,
ProfilEmails,
RoleInformation,
ProfilInformation,
},
props: ["data"],
methods: {},
props: ["data"],
methods: {},
computed: {
editable() {
return this.data?.editAllowed ?? false;
},
profilInformation() {
if (!this.data) {
return {};
}
computed: {
editable() {
return this.data?.editAllowed ?? false;
},
profilInformation() {
if (!this.data) {
return {};
}
return {
Vorname: this.data.vorname,
Nachname: this.data.nachname,
Username: this.data.username,
Anrede: this.data.anrede,
Titel: this.data.titel,
Postnomen: this.data.postnomen,
foto_sperre: this.data.foto_sperre,
foto: this.data.foto,
};
},
return {
Vorname: this.data.vorname,
Nachname: this.data.nachname,
Username: this.data.username,
Anrede: this.data.anrede,
Titel: this.data.titel,
Postnomen: this.data.postnomen,
foto_sperre: this.data.foto_sperre,
foto: this.data.foto,
};
},
personEmails() {
return this.data?.emails ? this.data.emails : [];
},
personEmails() {
return this.data?.emails ? this.data.emails : [];
},
roleInformation() {
if (!this.data) {
return {};
}
roleInformation() {
if (!this.data) {
return {};
}
return {
Geburtsdatum: this.data.gebdatum,
Geburtsort: this.data.gebort,
Personenkennzeichen: this.data.personenkennzeichen,
Studiengang: this.data.studiengang,
Semester: this.data.semester,
Verband: this.data.verband,
Gruppe: this.data.gruppe.trim(),
};
},
},
return {
Geburtsdatum: this.data.gebdatum,
Geburtsort: this.data.gebort,
Personenkennzeichen: this.data.personenkennzeichen,
Studiengang: this.data.studiengang,
Semester: this.data.semester,
Verband: this.data.verband,
Gruppe: this.data.gruppe.trim(),
};
},
},
mounted() {},
mounted() {
},
template: /*html*/ `
template: /*html*/ `
<div class="container-fluid text-break fhc-form" >
<div class="container-fluid text-break fhc-form" >
<!-- ROW -->
<div class="row">
<!-- HIDDEN QUICK LINKS -->
<!-- uncomment when implemented
<div class="d-md-none col-12 ">
<quick-links :title="$p.t('profil','quickLinks')" :mobile="true"></quick-links>
</div>-->
<!-- END OF HIDDEN QUCK LINKS -->
<!-- MAIN PANNEL -->
<div class="col-sm-12 col-md-8 col-xxl-9 ">
<!-- ROW WITH PROFIL IMAGE AND INFORMATION -->
<!-- INFORMATION CONTENT START -->
<!-- ROW WITH THE PROFIL INFORMATION -->
<div class="row">
<!-- HIDDEN QUICK LINKS -->
<!-- uncomment when implemented
<div class="d-md-none col-12 ">
<quick-links :title="$p.t('profil','quickLinks')" :mobile="true"></quick-links>
</div>-->
<!-- END OF HIDDEN QUCK LINKS -->
<!-- MAIN PANNEL -->
<div class="col-sm-12 col-md-8 col-xxl-9 ">
<!-- ROW WITH PROFIL IMAGE AND INFORMATION -->
<!-- INFORMATION CONTENT START -->
<!-- ROW WITH THE PROFIL INFORMATION -->
<div class="row mb-4">
<!-- FIRST KAESTCHEN -->
<div class="col-lg-12 col-xl-6 ">
<div class="row mb-4">
<!-- FIRST KAESTCHEN -->
<div class="col-lg-12 col-xl-6 ">
<div class="row mb-4">
<div class="col">
<profil-information :data="profilInformation" :title="$p.t('profil','studentIn')" :editable="editable"></profil-information>
</div>
<div class="col">
<profil-information :data="profilInformation" :title="$p.t('profil','studentIn')" :editable="editable"></profil-information>
</div>
</div>
<!-- START OF SECOND PROFIL INFORMATION COLUMN -->
<!-- START OF SECOND PROFIL INFORMATION COLUMN -->
<!-- END OF PROFIL INFORMATION ROW -->
<!-- INFORMATION CONTENT END -->
</div>
<div class="col-xl-6 col-lg-12 ">
<div class="row mb-4">
<div class="col">
<!-- EMAILS -->
<profil-emails :title="this.$p.t('person','email')" :data="personEmails"></profil-emails>
</div></div>
<!-- SECOND ROW OF SECOND COLUMN IN MAIN CONTENT -->
<div class=" row mb-4">
<div class=" col-lg-12">
<role-information :title="$p.t('profil','studentInformation')" :data="roleInformation"></role-information>
</div>
</div>
<!-- END OF SECOND ROW OF SECOND COLUMN IN MAIN CONTENT -->
<!-- END OF THE SECOND INFORMATION COLUMN -->
</div>
<!-- START OF THE SECOND PROFIL INFORMATION ROW -->
<!-- ROW WITH PROFIL IMAGE AND INFORMATION END -->
</div >
<!-- END OF MAIN CONTENT COL -->
</div>
<!-- START OF SIDE PANEL -->
<div class="col-md-4 col-xxl-3 col-sm-12 text-break" >
<!-- SRART OF QUICK LINKS IN THE SIDE PANEL -->
<!-- START OF THE FIRDT ROW IN THE SIDE PANEL -->
<!-- THESE QUCK LINKS ARE ONLY VISIBLE UNTIL VIEWPORT MD -->
<!--TODO: uncomment when implemented
<div class="row d-none d-md-block mb-3">
<div class="col">
<quick-links :title="$p.t('profil','quickLinks')"></quick-links>
</div>
</div>-->
<!-- START OF THE SECOND ROW IN THE SIDE PANEL -->
<div class="row">
<div class="col">
<!-- HIER SIND DIE MAILVERTEILER -->
<mailverteiler :title="$p.t('profil','mailverteiler')" :data="data?.mailverteiler"></mailverteiler>
</div>
<!-- END OF THE SECOND ROW IN THE SIDE PANEL -->
</div>
<!-- END OF SIDE PANEL -->
</div>
<!-- END OF CONTAINER ROW-->
</div>
<!-- END OF CONTAINER -->
</div>
<div class="col-xl-6 col-lg-12 ">
<div class="row mb-4">
<div class="col">
<!-- EMAILS -->
<profil-emails :title="this.$p.t('person','email')" :data="personEmails"></profil-emails>
</div>
</div>
<!-- SECOND ROW OF SECOND COLUMN IN MAIN CONTENT -->
<div class=" row mb-4">
<div class=" col-lg-12">
<role-information :title="$p.t('profil','studentInformation')" :data="roleInformation"></role-information>
</div>
</div>
<!-- END OF SECOND ROW OF SECOND COLUMN IN MAIN CONTENT -->
<!-- END OF THE SECOND INFORMATION COLUMN -->
</div>
<!-- START OF THE SECOND PROFIL INFORMATION ROW -->
<!-- ROW WITH PROFIL IMAGE AND INFORMATION END -->
</div >
<!-- END OF MAIN CONTENT COL -->
</div>
<!-- START OF SIDE PANEL -->
<div class="col-md-4 col-xxl-3 col-sm-12 text-break" >
<!-- SRART OF QUICK LINKS IN THE SIDE PANEL -->
<!-- START OF THE FIRDT ROW IN THE SIDE PANEL -->
<!-- THESE QUCK LINKS ARE ONLY VISIBLE UNTIL VIEWPORT MD -->
<!--TODO: uncomment when implemented
<div class="row d-none d-md-block mb-3">
<div class="col">
<quick-links :title="$p.t('profil','quickLinks')"></quick-links>
</div>
</div>-->
<!-- START OF THE SECOND ROW IN THE SIDE PANEL -->
<div class="row">
<div class="col">
<!-- HIER SIND DIE MAILVERTEILER -->
<mailverteiler :title="$p.t('profil','mailverteiler')" :data="data?.mailverteiler"></mailverteiler>
</div>
<!-- END OF THE SECOND ROW IN THE SIDE PANEL -->
</div>
<!-- END OF SIDE PANEL -->
</div>
<!-- END OF CONTAINER ROW-->
</div>
<!-- END OF CONTAINER -->
</div>
`,
};
+24 -8
View File
@@ -7,22 +7,32 @@ export default {
DashboardSection,
DashboardWidgetPicker
},
props: [
"dashboard",
"viewDataString"
],
props: {
dashboard: {
type: String,
required: true,
default: 'CIS'
},
viewData: {
type: Object,
required: true,
default: () => ({name: '', uid: ''}),
validator(value) {
return value && value.name && value.uid
}
}
},
data() {
return {
sections: [],
widgets: null,
viewData: JSON.parse(this.viewDataString ?? '{}'),
editMode: false
editMode: false,
viewDataInternal: this.viewData
}
},
provide() {
return {
editMode: Vue.computed(()=>this.editMode),
viewData: Vue.computed(()=>Vue.reactive(this.viewData)),
}
},
computed: {
@@ -151,10 +161,16 @@ export default {
}
}).catch(err => console.error('ERROR:', err));
},
async beforeMount() {
if(!this.viewData.name || !this.viewData.uid) {
const res = await this.$fhcApi.factory.dashboard.getViewData()
this.viewDataInternal = res.data
}
},
template: `
<div class="core-dashboard">
<h3>
{{ $p.t('global/personalGreeting', [ viewData?.name ]) }}
{{ $p.t('global/personalGreeting', [ viewDataInternal?.name ]) }}
<button style="margin-left: 8px;" class="btn" @click="editMode = !editMode"><i class="fa-solid fa-gear"></i></button>
</h3>
<dashboard-section v-for="(section, index) in sections" :key="section.name" :seperator="index" :name="section.name" :widgets="section.widgets" @widgetAdd="widgetAdd" @widgetUpdate="widgetUpdate" @widgetRemove="widgetRemove"></dashboard-section>