mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-07-16 14:32:18 +00:00
Merge branch 'feature-63192/FHC4-Studierendenverwaltung_Semsterauswahl_fuer_mehrere_Tabs_anpassen' into rc1_FHC4_C4
This commit is contained in:
@@ -48,6 +48,33 @@ const router = VueRouter.createRouter({
|
||||
next();
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'studiengang',
|
||||
path: `/${ciPath}/studentenverwaltung/:studiensemester_kurzbz/:studiengang`,
|
||||
component: FhcStudentenverwaltung,
|
||||
props: (route) => {
|
||||
return {
|
||||
url_studiensemester_kurzbz: route.params.studiensemester_kurzbz,
|
||||
url_studiengang: route.params.studiengang,
|
||||
};
|
||||
},
|
||||
beforeEnter: (to, from, next) => {
|
||||
const isSemester = /^[WS]S\d{4}$/.test(to.params.studiensemester_kurzbz);
|
||||
if (!isSemester) {
|
||||
return next({name: 'index'});
|
||||
}
|
||||
const isStudiengang = /^[A-Z]{3}/.test(to.params.studiengang);
|
||||
if (!isStudiengang) {
|
||||
return next({
|
||||
name: 'studiensemester',
|
||||
params: {
|
||||
studiensemester_kurzbz: to.params.studiensemester_kurzbz
|
||||
}
|
||||
});
|
||||
}
|
||||
next();
|
||||
}
|
||||
},
|
||||
{
|
||||
path: `/${ciPath}/studentenverwaltung/:studiensemester_kurzbz/prestudent/:prestudent_id`,
|
||||
component: FhcStudentenverwaltung,
|
||||
@@ -131,11 +158,14 @@ const router = VueRouter.createRouter({
|
||||
});
|
||||
|
||||
router.afterEach((to, from, failure) => {
|
||||
if (to.params.studiensemester_kurzbz) {
|
||||
document.title = to.params.studiensemester_kurzbz + ' - Studierendenverwaltung FH-Complete';
|
||||
} else {
|
||||
document.title = 'Studierendenverwaltung FH-Complete';
|
||||
let title = 'Studierendenverwaltung FH-Complete';
|
||||
if (to.params.studiengang) {
|
||||
title = to.params.studiengang + ' ' + title;
|
||||
}
|
||||
if (to.params.studiensemester_kurzbz) {
|
||||
title = to.params.studiensemester_kurzbz + ' ' + title;
|
||||
}
|
||||
document.title = title;
|
||||
});
|
||||
|
||||
const app = Vue.createApp({
|
||||
|
||||
@@ -24,6 +24,7 @@ import StvStudiensemester from "./Studentenverwaltung/Studiensemester.js";
|
||||
|
||||
import ApiSearchbar from "../../api/factory/searchbar.js";
|
||||
import ApiStv from "../../api/factory/stv.js";
|
||||
import ApiStvVerband from '../../api/factory/stv/verband.js';
|
||||
|
||||
|
||||
export default {
|
||||
@@ -42,7 +43,12 @@ export default {
|
||||
permissions: Object,
|
||||
stvRoot: String,
|
||||
cisRoot: String,
|
||||
activeAddons: String // semicolon separated list of active addons
|
||||
activeAddons: String, // semicolon separated list of active addons
|
||||
url_studiensemester_kurzbz: String,
|
||||
url_mode: String,
|
||||
url_prestudent_id: String,
|
||||
url_tab: String,
|
||||
url_studiengang: String
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
@@ -113,23 +119,30 @@ export default {
|
||||
mergeResults: 'person'
|
||||
},
|
||||
studiengangKz: undefined,
|
||||
studiengangKuerzel: '',
|
||||
studiensemesterKurzbz: this.defaultSemester,
|
||||
lists: {
|
||||
nations: [],
|
||||
sprachen: [],
|
||||
geschlechter: []
|
||||
}
|
||||
},
|
||||
verbandEndpoint: ApiStvVerband
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$attrs.url_studiensemester_kurzbz': function (newVal, oldVal) {
|
||||
'url_studiensemester_kurzbz': function (newVal, oldVal) {
|
||||
if (newVal !== oldVal) {
|
||||
this.studiensemesterKurzbz = newVal;
|
||||
this.$refs.stvList.updateUrl();
|
||||
this.$refs.details.reload();
|
||||
}
|
||||
},
|
||||
'$attrs.url_mode': function () {
|
||||
'url_studiengang': function (newVal, oldVal) {
|
||||
if (newVal !== oldVal) {
|
||||
this.checkUrlStudiengang();
|
||||
}
|
||||
},
|
||||
'url_mode': function () {
|
||||
this.handlePersonUrl();
|
||||
}
|
||||
},
|
||||
@@ -173,16 +186,32 @@ export default {
|
||||
{
|
||||
urlpath = 'CURRENT_SEMESTER' + '/' + urlpath;
|
||||
}
|
||||
this.$refs.stvList.updateUrl(ApiStv.students.verband(urlpath));
|
||||
|
||||
this.studiengangKz = studiengang_kz;
|
||||
this.$refs.stvList.updateUrl(
|
||||
ApiStv.students.verband(urlpath)
|
||||
);
|
||||
this.$router.push({
|
||||
name: 'studiensemester',
|
||||
params: {
|
||||
studiensemester_kurzbz: this.studiensemesterKurzbz
|
||||
}
|
||||
const stg = this.lists.stgs.find((element) => {
|
||||
return (element.studiengang_kz === this.studiengangKz);
|
||||
});
|
||||
if (stg)
|
||||
{
|
||||
this.studiengangKuerzel = (stg.typ + stg.kurzbz).toUpperCase()
|
||||
this.$router.push({
|
||||
name: 'studiengang',
|
||||
params: {
|
||||
studiensemester_kurzbz: this.studiensemesterKurzbz,
|
||||
studiengang: this.studiengangKuerzel
|
||||
}
|
||||
});
|
||||
} else
|
||||
{
|
||||
this.studiengangKuerzel = '';
|
||||
this.$router.push({
|
||||
name: 'studiensemester',
|
||||
params: {
|
||||
studiensemester_kurzbz: this.studiensemesterKurzbz
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
studiensemesterChanged(v) {
|
||||
this.studiensemesterKurzbz = v;
|
||||
@@ -219,10 +248,29 @@ export default {
|
||||
true
|
||||
);
|
||||
}
|
||||
},
|
||||
checkUrlStudiengang() {
|
||||
if (this.url_studiengang) {
|
||||
const stg = this.lists.stgs.find((element) => {
|
||||
const kuerzel = (element.typ + element.kurzbz).toUpperCase();
|
||||
return (this.url_studiengang === kuerzel);
|
||||
});
|
||||
if (stg) {
|
||||
this.studiengangKz = stg.studiengang_kz;
|
||||
this.studiengangKuerzel = (stg.typ + stg.kurzbz).toUpperCase();
|
||||
} else {
|
||||
this.$router.replace({
|
||||
name: 'studiensemester',
|
||||
params: {
|
||||
studiensemester_kurzbz: this.studiensemesterKurzbz
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (!this.$attrs?.url_studiensemester_kurzbz) {
|
||||
if (!this.url_studiensemester_kurzbz) {
|
||||
this.$router.replace({
|
||||
name: 'studiensemester',
|
||||
params: {
|
||||
@@ -230,7 +278,7 @@ export default {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.studiensemesterKurzbz = this.$attrs.url_studiensemester_kurzbz;
|
||||
this.studiensemesterKurzbz = this.url_studiensemester_kurzbz;
|
||||
}
|
||||
|
||||
this.$api
|
||||
@@ -266,6 +314,7 @@ export default {
|
||||
.then(result => {
|
||||
this.lists.stgs = result.data;
|
||||
this.lists.active_stgs = this.lists.stgs.filter(stg => stg.aktiv);
|
||||
this.checkUrlStudiengang();
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
|
||||
@@ -299,7 +348,7 @@ export default {
|
||||
template: `
|
||||
<div class="stv">
|
||||
<header class="navbar navbar-expand-lg navbar-dark bg-dark flex-md-nowrap p-0 shadow">
|
||||
<a class="navbar-brand col-md-4 col-lg-3 col-xl-2 me-0 px-3" :href="stvRoot">FHC 4.0</a>
|
||||
<a class="navbar-brand col-md-4 col-lg-3 col-xl-2 me-0 px-3" :href="stvRoot">StudVw: {{studiensemesterKurzbz}} {{studiengangKuerzel}}</a>
|
||||
<button class="navbar-toggler d-md-none m-1 collapsed" type="button" data-bs-toggle="offcanvas" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" :aria-label="$p.t('ui/toggle_nav')"><span class="navbar-toggler-icon"></span></button>
|
||||
<core-searchbar
|
||||
:searchoptions="searchbaroptions"
|
||||
@@ -313,7 +362,7 @@ export default {
|
||||
<div class="offcanvas-header justify-content-end px-1 d-md-none">
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" :aria-label="$p.t('ui/schliessen')"></button>
|
||||
</div>
|
||||
<stv-verband @select-verband="onSelectVerband" class="col" style="height:0%"></stv-verband>
|
||||
<stv-verband :preselectedKey="'' + studiengangKz" :endpoint="verbandEndpoint" @select-verband="onSelectVerband" class="col" style="height:0%"></stv-verband>
|
||||
<stv-studiensemester v-model:studiensemester-kurzbz="studiensemesterKurzbz" @update:studiensemester-kurzbz="studiensemesterChanged"></stv-studiensemester>
|
||||
</nav>
|
||||
<main class="col-md-8 ms-sm-auto col-lg-9 col-xl-10">
|
||||
|
||||
@@ -5,8 +5,6 @@ import PvTree from "../../../../../index.ci.php/public/js/components/primevue/tr
|
||||
import PvTreetable from "../../../../../index.ci.php/public/js/components/primevue/treetable/treetable.esm.min.js";
|
||||
import PvColumn from "../../../../../index.ci.php/public/js/components/primevue/column/column.esm.min.js";
|
||||
|
||||
import ApiStvVerband from '../../../api/factory/stv/verband.js';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
PvTree,
|
||||
@@ -16,11 +14,22 @@ export default {
|
||||
emits: [
|
||||
'selectVerband'
|
||||
],
|
||||
props: {
|
||||
endpoint: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
preselectedKey: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
nodes: [],
|
||||
selectedKey: [],
|
||||
expandedKeys: {},
|
||||
filters: {}, // TODO(chris): filter only 1st level?
|
||||
favnodes: [],
|
||||
favorites: {on: false, list: []}
|
||||
@@ -32,6 +41,13 @@ export default {
|
||||
return this.favorites.on ? this.favnodes : this.nodes;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'preselectedKey': function (newVal, oldVal) {
|
||||
if (newVal !== oldVal) {
|
||||
this.setPreselection();
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
findNodeByKey(key, arr) {
|
||||
if (!arr)
|
||||
@@ -44,7 +60,7 @@ export default {
|
||||
return res.pop();
|
||||
return null;
|
||||
},
|
||||
onExpandTreeNode(node) {
|
||||
async onExpandTreeNode(node) {
|
||||
if (!node.children) {
|
||||
if (node.data.link) {
|
||||
let activeEl = null;
|
||||
@@ -55,8 +71,8 @@ export default {
|
||||
});
|
||||
this.loading = true;
|
||||
|
||||
this.$api
|
||||
.call(ApiStvVerband.get(node.data.link))
|
||||
return this.$api
|
||||
.call(this.endpoint.get(node.data.link))
|
||||
.then(result => result.data)
|
||||
.then(result => {
|
||||
const subNodes = result.map(this.mapResultToTreeData);
|
||||
@@ -68,7 +84,7 @@ export default {
|
||||
|
||||
let treeitem = this.$refs.tree.$el.querySelector('[data-tree-item-key="' + node.key + '"]');
|
||||
treeitem = treeitem.closest('[role="row"]');
|
||||
|
||||
|
||||
this.$nextTick(() => {
|
||||
if (activeEl == document.activeElement)
|
||||
treeitem.dispatchEvent(new KeyboardEvent('keydown', {
|
||||
@@ -108,7 +124,7 @@ export default {
|
||||
}
|
||||
this.favorites.on = !this.favorites.on;
|
||||
this.$api
|
||||
.call(ApiStvVerband.favorites.set(
|
||||
.call(this.endpoint.favorites.set(
|
||||
JSON.stringify(this.favorites)
|
||||
));
|
||||
this.loading = false;
|
||||
@@ -135,7 +151,7 @@ export default {
|
||||
for (let parent in sortedInParents)
|
||||
promises.push(
|
||||
this.$api
|
||||
.call(ApiStvVerband.get(parent == '_' ? '' : parent))
|
||||
.call(this.endpoint.get(parent == '_' ? '' : parent))
|
||||
.then(res => res.data)
|
||||
.then(res => res.filter(node => sortedInParents[parent].includes(node.link + '')))
|
||||
);
|
||||
@@ -160,9 +176,9 @@ export default {
|
||||
this.favnodes.push((await this.loadNodes([key.data.link])).pop());
|
||||
this.favorites.list.push(key.data.link + '');
|
||||
}
|
||||
|
||||
|
||||
this.$api
|
||||
.call(ApiStvVerband.favorites.set(
|
||||
.call(this.endpoint.favorites.set(
|
||||
JSON.stringify(this.favorites)
|
||||
));
|
||||
},
|
||||
@@ -181,19 +197,55 @@ export default {
|
||||
let items = e.target.querySelectorAll('[data-link-fav-add][tabindex="-1"]');
|
||||
items.forEach(el => el.tabIndex = 0);
|
||||
}
|
||||
},
|
||||
async setPreselection()
|
||||
{
|
||||
if (!this.preselectedKey)
|
||||
return;
|
||||
|
||||
let rawKey = this.preselectedKey
|
||||
|
||||
if (!rawKey || typeof rawKey !== 'string')
|
||||
return;
|
||||
|
||||
const parts = this.preselectedKey.split('/');
|
||||
let currentKey = parts[0];
|
||||
let currentNode = this.findNodeByKey(currentKey);
|
||||
|
||||
if (!currentNode)
|
||||
return;
|
||||
|
||||
for (let i = 1; i < parts.length; i++)
|
||||
{
|
||||
this.expandedKeys[currentNode.key] = true;
|
||||
|
||||
await this.onExpandTreeNode(currentNode);
|
||||
|
||||
currentKey += '-' + parts[i];
|
||||
currentNode = this.findNodeByKey(currentKey);
|
||||
|
||||
if (!currentNode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.selectedKey = {[currentNode.key]: true};
|
||||
this.onSelectTreeNode(currentNode);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$api
|
||||
.call(ApiStvVerband.get())
|
||||
.call(this.endpoint.get())
|
||||
.then(result => {
|
||||
this.nodes = result.data.map(this.mapResultToTreeData);
|
||||
this.setPreselection();
|
||||
this.loading = false;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
|
||||
this.$api
|
||||
.call(ApiStvVerband.favorites.get())
|
||||
.call(this.endpoint.favorites.get())
|
||||
.then(result => {
|
||||
if (result.data) {
|
||||
let f = JSON.parse(result.data);
|
||||
@@ -218,6 +270,7 @@ export default {
|
||||
:value="filteredNodes"
|
||||
@node-expand="onExpandTreeNode"
|
||||
selection-mode="single"
|
||||
v-model:expanded-keys="expandedKeys"
|
||||
v-model:selection-keys="selectedKey"
|
||||
@node-select="onSelectTreeNode"
|
||||
scrollable
|
||||
|
||||
Reference in New Issue
Block a user