mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-01 20:29:29 +00:00
NotenTab: Document download/archive
This commit is contained in:
@@ -99,6 +99,8 @@ class Config extends FHCAPI_Controller
|
||||
'usePoints' => defined('CIS_GESAMTNOTE_PUNKTE') && CIS_GESAMTNOTE_PUNKTE,
|
||||
'edit' => 'both', // Possible values: both|header|inline
|
||||
'delete' => 'both', // Possible values: both|header|inline
|
||||
'documents' => 'both', // Possible values: both|header|inline
|
||||
'documentslist' => $this->gradesDocumentsList()
|
||||
]
|
||||
];
|
||||
|
||||
@@ -235,4 +237,157 @@ class Config extends FHCAPI_Controller
|
||||
]
|
||||
] + $this->kontoColumns();
|
||||
}
|
||||
protected function gradesDocumentsList()
|
||||
{
|
||||
$permissioncheck = site_url("api/frontend/v1/documents/permissionAlternativeFormat/{studiengang_kz}");
|
||||
|
||||
$title_ger = $this->p->t("global", "deutsch");
|
||||
$title_eng = $this->p->t("global", "englisch");
|
||||
$title_ff = 'Zertifikat'; // TODO(chris): phrase
|
||||
$title_lv = 'LV Zeugnis'; // TODO(chris): phrase
|
||||
|
||||
$link_ff = "documents/export/" .
|
||||
"zertifikat.rdf.php/" .
|
||||
"Zertifikat" .
|
||||
"?stg_kz={studiengang_kz_lv}" .
|
||||
"&uid={uid}" .
|
||||
"&ss={studiensemester_kurzbz}" .
|
||||
"&lvid={lehrveranstaltung_id}";
|
||||
$link_lv_ger = "documents/export/" .
|
||||
"lehrveranstaltungszeugnis.rdf.php/" .
|
||||
"LVZeugnis" .
|
||||
"?stg_kz={studiengang_kz}" .
|
||||
"&uid={uid}" .
|
||||
"&ss={studiensemester_kurzbz}" .
|
||||
"&lvid={lehrveranstaltung_id}";
|
||||
$link_lv_eng = "documents/export/" .
|
||||
"lehrveranstaltungszeugnis.rdf.php/" .
|
||||
"LVZeugnisEng" .
|
||||
"?stg_kz={studiengang_kz}" .
|
||||
"&uid={uid}" .
|
||||
"&ss={studiensemester_kurzbz}" .
|
||||
"&lvid={lehrveranstaltung_id}";
|
||||
|
||||
$archive_url = "api/frontend/v1/documents/archiveSigned";
|
||||
$archive_response = $this->p->t("stv", "document_signed_and_archived");
|
||||
$archive_post_ff = [
|
||||
"xml" => "zertifikat.rdf.php",
|
||||
"xsl" => "Zertifikat",
|
||||
"stg_kz" => "{studiengang_kz_lv}",
|
||||
"uid" => "{uid}",
|
||||
"ss" => "{studiensemester_kurzbz}",
|
||||
"lvid" => "{lehrveranstaltung_id}"
|
||||
];
|
||||
$archive_post_lv_ger = [
|
||||
"xml" => "lehrveranstaltungszeugnis.rdf.php",
|
||||
"xsl" => "LVZeugnis",
|
||||
"stg_kz" => "{studiengang_kz}",
|
||||
"uid" => "{uid}",
|
||||
"ss" => "{studiensemester_kurzbz}",
|
||||
"lvid" => "{lehrveranstaltung_id}"
|
||||
];
|
||||
$archive_post_lv_eng = [
|
||||
"xml" => "lehrveranstaltungszeugnis.rdf.php",
|
||||
"xsl" => "LVZeugnisEng",
|
||||
"stg_kz" => "{studiengang_kz}",
|
||||
"uid" => "{uid}",
|
||||
"ss" => "{studiensemester_kurzbz}",
|
||||
"lvid" => "{lehrveranstaltung_id}"
|
||||
];
|
||||
|
||||
$list = [
|
||||
[
|
||||
'title' => '<i class="fa fa-download" title="Download"></i>', // TODO(chris): phrase
|
||||
'children' => [
|
||||
[
|
||||
'title' => $title_ff,
|
||||
'link' => site_url($link_ff)
|
||||
],
|
||||
[
|
||||
'title' => $title_lv,
|
||||
'children' => [
|
||||
[
|
||||
'title' => $title_ger,
|
||||
'link' => site_url($link_lv_ger),
|
||||
'children' => [
|
||||
[
|
||||
'title' => 'PDF',
|
||||
'permissioncheck' => $permissioncheck,
|
||||
'link' => site_url($link_lv_ger)
|
||||
],
|
||||
[
|
||||
'title' => 'DOC',
|
||||
'permissioncheck' => $permissioncheck,
|
||||
'link' => site_url($link_lv_ger . "&output=doc")
|
||||
],
|
||||
[
|
||||
'title' => 'ODT',
|
||||
'permissioncheck' => $permissioncheck,
|
||||
'link' => site_url($link_lv_ger . "&output=odt")
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'title' => $title_eng,
|
||||
'link' => site_url($link_lv_eng),
|
||||
'children' => [
|
||||
[
|
||||
'title' => 'PDF',
|
||||
'permissioncheck' => $permissioncheck,
|
||||
'link' => site_url($link_lv_eng)
|
||||
],
|
||||
[
|
||||
'title' => 'DOC',
|
||||
'permissioncheck' => $permissioncheck,
|
||||
'link' => site_url($link_lv_eng . "&output=doc")
|
||||
],
|
||||
[
|
||||
'title' => 'ODT',
|
||||
'permissioncheck' => $permissioncheck,
|
||||
'link' => site_url($link_lv_eng . "&output=odt")
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'title' => '<i class="fas fa-archive" title="Archivieren"></i>', // TODO(chris): phrase
|
||||
'children' => [
|
||||
[
|
||||
'title' => $title_ff,
|
||||
'action' => [
|
||||
'url' => site_url($archive_url),
|
||||
'post' => $archive_post_ff,
|
||||
'response' => $archive_response
|
||||
]
|
||||
],
|
||||
[
|
||||
'title' => $title_lv,
|
||||
'children' => [
|
||||
[
|
||||
'title' => $title_ger,
|
||||
'action' => [
|
||||
'url' => site_url($archive_url),
|
||||
'post' => $archive_post_lv_ger,
|
||||
'response' => $archive_response
|
||||
]
|
||||
],
|
||||
[
|
||||
'title' => $title_eng,
|
||||
'action' => [
|
||||
'url' => site_url($archive_url),
|
||||
'post' => $archive_post_lv_eng,
|
||||
'response' => $archive_response
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import {CoreFilterCmpt} from "../../../../filter/Filter.js";
|
||||
import ZeugnisActions from './Zeugnis/Actions.js';
|
||||
import ZeugnisDocuments from './Zeugnis/Documents.js';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CoreFilterCmpt,
|
||||
ZeugnisActions
|
||||
ZeugnisActions,
|
||||
ZeugnisDocuments
|
||||
},
|
||||
inject: [
|
||||
'config'
|
||||
@@ -15,9 +17,27 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tabulatorEvents: [],
|
||||
tabulatorEvents: [
|
||||
{
|
||||
event: "dataLoaded",
|
||||
handler: data => this.data = data.map(item => {
|
||||
item.documentslist = document.createElement("div");
|
||||
return item;
|
||||
})
|
||||
},
|
||||
{
|
||||
event: "rowSelected",
|
||||
handler: row => row.getElement().style.zIndex = 12
|
||||
},
|
||||
{
|
||||
event: "rowDeselected",
|
||||
handler: row => row.getElement().style.zIndex = ''
|
||||
}
|
||||
],
|
||||
stdsem: '',
|
||||
lastGradeList: []
|
||||
lastGradeList: [],
|
||||
lastClickedRow: null,
|
||||
data: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -125,13 +145,14 @@ export default {
|
||||
{ field: 'lehrveranstaltung_bezeichnung_english', title: 'Englisch', visible: false }
|
||||
];
|
||||
|
||||
const hasDownload = ['both', 'inline'].includes(this.config.download);
|
||||
const hasDocuments = ['both', 'inline'].includes(this.config.documents);
|
||||
const hasDelete = ['both', 'inline'].includes(this.config.delete);
|
||||
|
||||
if (hasDownload || hasDelete) {
|
||||
if (hasDocuments || hasDelete) {
|
||||
columns.push({
|
||||
field: 'actions',
|
||||
title: 'Actions',
|
||||
cssClass: "overflow-visible",
|
||||
headerSort: false,
|
||||
formatter: cell => {
|
||||
// get row data
|
||||
@@ -141,13 +162,20 @@ export default {
|
||||
let container = document.createElement('div');
|
||||
container.className = "d-flex gap-2 justify-content-end";
|
||||
|
||||
if (hasDocuments) {
|
||||
container.append(data.documentslist);
|
||||
}
|
||||
|
||||
if (hasDelete) {
|
||||
let deleteButton = document.createElement('button');
|
||||
deleteButton.className = 'btn btn-outline-secondary';
|
||||
deleteButton.innerHTML = '<i class="fa fa-trash"></i>';
|
||||
const icon = document.createElement('i');
|
||||
icon.className = 'fa fa-trash';
|
||||
icon.title = this.$p.t('ui/loeschen');
|
||||
deleteButton.append(icon);
|
||||
deleteButton.addEventListener('click', evt => {
|
||||
evt.stopPropagation();
|
||||
this.deleteGrade(data);
|
||||
this.deleteGrade(data);// TODO(chris): test with new data object
|
||||
});
|
||||
container.append(deleteButton);
|
||||
}
|
||||
@@ -202,7 +230,7 @@ export default {
|
||||
.then(result => result ? data : Promise.reject({handled:true}))
|
||||
.then(this.$fhcApi.factory.stv.grades.deleteCertificate)
|
||||
.then(this.$refs.table.reloadTable)
|
||||
.then(() => this.$fhcAlert.alertSuccess('deleted')) // TODO(chris): phrase
|
||||
.then(() => this.$fhcAlert.alertSuccess(this.$p.t('ui/successDelete')))
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
}
|
||||
},
|
||||
@@ -223,5 +251,12 @@ export default {
|
||||
<zeugnis-actions :selected="selected" @set-grade="setGrade" @delete-grade="deleteGrade"></zeugnis-actions>
|
||||
</template>
|
||||
</core-filter-cmpt>
|
||||
<Teleport
|
||||
v-for="grade in data"
|
||||
:key="grade.uid + '_' + grade.studiensemester_kurzbz + '_' + grade.lehrveranstaltung_id"
|
||||
:to="grade.documentslist"
|
||||
>
|
||||
<zeugnis-documents :data="grade" :list="config.documentslist"></zeugnis-documents>
|
||||
</Teleport>
|
||||
</div>`
|
||||
};
|
||||
@@ -1,11 +1,13 @@
|
||||
import CoreForm from '../../../../../Form/Form.js';
|
||||
import FormInput from '../../../../../Form/Input.js';
|
||||
import ZeugnisDocuments from './Documents.js';
|
||||
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CoreForm,
|
||||
FormInput
|
||||
FormInput,
|
||||
ZeugnisDocuments
|
||||
},
|
||||
emits: [
|
||||
'setGrade',
|
||||
@@ -117,13 +119,20 @@ export default {
|
||||
<option v-for="grade in grades" :key="grade.note" :value="grade.note">{{ grade.bezeichnung }}</option>
|
||||
</select>
|
||||
</template>
|
||||
<zeugnis-documents
|
||||
v-if="['both', 'header'].includes(config.documents)"
|
||||
:data="selected.find(Boolean)"
|
||||
:list="config.documentslist"
|
||||
:disabled="!selected.length"
|
||||
>
|
||||
</zeugnis-documents>
|
||||
<button
|
||||
v-if="['both', 'header'].includes(config.delete)"
|
||||
class="btn btn-outline-secondary"
|
||||
:disabled="!selected.length"
|
||||
@click="deleteGrades"
|
||||
>
|
||||
<i class="fa fa-trash"></i>
|
||||
<i class="fa fa-trash" :title="$p.t('ui/loeschen')"></i>
|
||||
</button>
|
||||
</div>`
|
||||
};
|
||||
@@ -0,0 +1,98 @@
|
||||
// NOTE(chris): cache calls globally to prevent multiple calls on the same source
|
||||
const calledPermissionUrls = {};
|
||||
async function callPermissionUrl($fhcApi, url) {
|
||||
if (!calledPermissionUrls[url]) {
|
||||
calledPermissionUrls[url] = $fhcApi.get(url);
|
||||
}
|
||||
return (await calledPermissionUrls[url]).data;
|
||||
}
|
||||
|
||||
export default {
|
||||
components: {
|
||||
PvTieredMenu: primevue.tieredmenu
|
||||
},
|
||||
props: {
|
||||
list: Array,
|
||||
data: Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
filteredList: []
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
async data() {
|
||||
this.filteredList = await this.copyListPart(this.list);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
addParamsToString(link) {
|
||||
for (var k in this.data)
|
||||
link = link.replace("{" + k + "}", this.data[k]);
|
||||
return link;
|
||||
},
|
||||
async copyListPart(list) {
|
||||
let result = [], res;
|
||||
|
||||
for (const part of list) {
|
||||
if (part.permissioncheck) {
|
||||
if (!this.data)
|
||||
continue;
|
||||
let permissioncheckUrl = part.permissioncheck;
|
||||
for (const k in this.data) {
|
||||
permissioncheckUrl = permissioncheckUrl.replace("{" + k + "}", this.data[k]);
|
||||
}
|
||||
if (!await callPermissionUrl(this.$fhcApi, permissioncheckUrl))
|
||||
continue;
|
||||
}
|
||||
const item = {label: part.title};
|
||||
if (part.children)
|
||||
item.items = await this.copyListPart(part.children);
|
||||
if (!item.items || !item.items.length) {
|
||||
if (part.action && part.action.url) {
|
||||
item.command = () => {
|
||||
const post = {};
|
||||
if (part.action.post)
|
||||
Object.entries(part.action.post)
|
||||
.forEach(
|
||||
([key, value]) =>
|
||||
post[key] = value[0] == '{'
|
||||
? this.data[value.slice(1,-1)]
|
||||
: value
|
||||
);
|
||||
this.$fhcApi
|
||||
.post(this.addParamsToString(part.action.url), post)
|
||||
.then(() => part.action.response || 'TODO(chris): phrase default')
|
||||
.then(this.$fhcAlert.alertSuccess)
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
};
|
||||
} else if(part.link) {
|
||||
item.url = this.addParamsToString(part.link);
|
||||
item.target = '_blank';
|
||||
}
|
||||
}
|
||||
result.push(item);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
this.filteredList = await this.copyListPart(this.list);
|
||||
},
|
||||
template: `
|
||||
<div class="stv-details-noten-zeugnis-documents d-inline-flex gap-2">
|
||||
<template v-for="(item, i) in filteredList" :key="i">
|
||||
<button
|
||||
type="button"
|
||||
label="Toggle"
|
||||
@click="evt => $refs.menu[i].toggle(evt)"
|
||||
aria-haspopup="true"
|
||||
class="btn btn-outline-secondary dropdown-toggle"
|
||||
v-html="item.label"
|
||||
v-bind="$attrs"
|
||||
/>
|
||||
<pv-tiered-menu ref="menu" :model="item.items" popup />
|
||||
</template>
|
||||
</div>`
|
||||
};
|
||||
Reference in New Issue
Block a user