diff --git a/app/controllers/contents/courseware.php b/app/controllers/contents/courseware.php index ffec9de5a98033951c8ed15f6d6a4f3c209d03e6..0dbc0b74ba1a31a35ddfeaf32f769fe56e4f9199 100755 --- a/app/controllers/contents/courseware.php +++ b/app/controllers/contents/courseware.php @@ -71,12 +71,10 @@ class Contents_CoursewareController extends AuthenticatedController */ public function courseware_action($action = false, $widgetId = null) { - global $perm; + global $perm, $user; Navigation::activateItem('/contents/courseware/courseware'); - $this->user_id = $GLOBALS['user']->id; - - $this->setCoursewareSidebar(); + $this->user_id = $user->id; $last = UserConfig::get($this->user_id)->getValue('COURSEWARE_LAST_ELEMENT'); @@ -89,12 +87,11 @@ class Contents_CoursewareController extends AuthenticatedController } // load courseware for current user - if (!$this->entry_element_id || !$struct || !$struct->canRead($GLOBALS['user'])) { - $user = User::find($this->user_id); + if (!$this->entry_element_id || !$struct || !$struct->canRead($user)) { if (!$user->courseware) { // create initial courseware dataset - StructuralElement::createEmptyCourseware($this->user_id, 'user'); + $struct = StructuralElement::createEmptyCourseware($this->user_id, 'user'); } $this->entry_element_id = $user->courseware->id; @@ -106,9 +103,19 @@ class Contents_CoursewareController extends AuthenticatedController $this->licenses = $this->getLicences(); $this->oer_enabled = Config::get()->OERCAMPUS_ENABLED && $perm->have_perm(Config::get()->OER_PUBLIC_STATUS); + + // Make sure struct has value., to evaluate the export (edit) capability. + if (!isset($struct)) { + $struct = \Courseware\StructuralElement::findOneBySQL( + "id = ? AND range_id = ? AND range_type = 'user'", + [$this->entry_element_id, $this->user_id] + ); + } + $canExport = !empty($struct) ? $struct->canEdit($user) : false; + $this->setCoursewareSidebar($canExport); } - private function setCoursewareSidebar() + private function setCoursewareSidebar(bool $canExport) { $sidebar = \Sidebar::Get(); $actions = new TemplateWidget( @@ -122,6 +129,14 @@ class Contents_CoursewareController extends AuthenticatedController $this->get_template_factory()->open('course/courseware/view_widget') ); $sidebar->addWidget($views)->addLayoutCSSClass('courseware-view-widget'); + + if ($canExport) { + $exports = new TemplateWidget( + _('Export '), + $this->get_template_factory()->open('course/courseware/export_widget') + ); + $sidebar->addWidget($exports)->addLayoutCSSClass('courseware-export-widget'); + } } private function getLicences() diff --git a/app/controllers/course/courseware.php b/app/controllers/course/courseware.php index 7c8cd786794b29b7fe37040c0dc072ea094662b2..e10e245eebee3bbdccd7d993712b8c8941feec99 100755 --- a/app/controllers/course/courseware.php +++ b/app/controllers/course/courseware.php @@ -50,7 +50,7 @@ class Course_CoursewareController extends AuthenticatedController if (!$course->courseware) { // create initial courseware dataset - StructuralElement::createEmptyCourseware(Context::getId(), 'course'); + $struct = StructuralElement::createEmptyCourseware(Context::getId(), 'course'); } $this->entry_element_id = $course->courseware->id; @@ -60,13 +60,22 @@ class Course_CoursewareController extends AuthenticatedController UserConfig::get($GLOBALS['user']->id)->store('COURSEWARE_LAST_ELEMENT', $last); Navigation::activateItem('course/courseware/content'); - $this->setIndexSidebar(); $this->licenses = []; $sorm_licenses = License::findBySQL('1 ORDER BY name ASC'); foreach ($sorm_licenses as $license) { array_push($this->licenses, $license->toArray()); } $this->licenses = json_encode($this->licenses); + + // Make sure struct has value., to evaluate the export (edit) capability. + if (!isset($struct)) { + $struct = StructuralElement::findOneBySQL("id = ? AND range_id = ? AND range_type = 'course'", [ + $this->entry_element_id, + Context::getId(), + ]); + } + $canExport = !empty($struct) ? $struct->canEdit($GLOBALS['user']) : false; + $this->setIndexSidebar($canExport); } public function dashboard_action(): void @@ -98,7 +107,7 @@ class Course_CoursewareController extends AuthenticatedController $this->render_pdf($element->pdfExport($this->user), trim($element->title).'.pdf'); } - private function setIndexSidebar(): void + private function setIndexSidebar(bool $canExport): void { $sidebar = Sidebar::Get(); $actions = new TemplateWidget( @@ -112,6 +121,14 @@ class Course_CoursewareController extends AuthenticatedController $this->get_template_factory()->open('course/courseware/view_widget') ); $sidebar->addWidget($views)->addLayoutCSSClass('courseware-view-widget'); + + if ($canExport) { + $exports = new TemplateWidget( + _('Export '), + $this->get_template_factory()->open('course/courseware/export_widget') + ); + $sidebar->addWidget($exports)->addLayoutCSSClass('courseware-export-widget'); + } } diff --git a/app/views/course/courseware/export_widget.php b/app/views/course/courseware/export_widget.php new file mode 100644 index 0000000000000000000000000000000000000000..1d7feb2c6e467b5e10160fe829589f0f4c80dd15 --- /dev/null +++ b/app/views/course/courseware/export_widget.php @@ -0,0 +1 @@ +<aside id="courseware-export-widget" class="widget-sidebar"></aside> diff --git a/resources/assets/stylesheets/scss/courseware.scss b/resources/assets/stylesheets/scss/courseware.scss index 2cceea1881af341be89b08dbfaa863f07aac7c1b..8143c18d0ed22b10ae448b62aab041f698897afb 100755 --- a/resources/assets/stylesheets/scss/courseware.scss +++ b/resources/assets/stylesheets/scss/courseware.scss @@ -1666,7 +1666,7 @@ b l o c k a d d e r display: block; } } - } + } } .cw-blockadder-item { @@ -1913,13 +1913,15 @@ v i e w w i d g e t .cw-action-widget-trash{ @include background-icon(trash, clickable); } - .cw-action-widget-export{ +} +.cw-export-widget { + .cw-export-widget-export{ @include background-icon(export, clickable); } - .cw-action-widget-export-pdf{ + .cw-export-widget-export-pdf{ @include background-icon(file-pdf, clickable); } - .cw-action-widget-oer{ + .cw-export-widget-oer{ @include background-icon(oer-campus, clickable); } } diff --git a/resources/vue/components/courseware/CoursewareActionWidget.vue b/resources/vue/components/courseware/CoursewareActionWidget.vue index 2c98a3ba22f833a96d07a4fbbe0018b25fa5751c..a718a648e0a5e5f6f88d50be5efcafd07033dd71 100644 --- a/resources/vue/components/courseware/CoursewareActionWidget.vue +++ b/resources/vue/components/courseware/CoursewareActionWidget.vue @@ -35,21 +35,6 @@ <translate>Lesezeichen setzen</translate> </a> </li> - <li v-if="canEdit" class="cw-action-widget-export"> - <a href="#" @click="exportElement"> - <translate>Seite exportieren</translate> - </a> - </li> - <li v-if="(canEdit || userIsTeacher) && canVisit" class="cw-action-widget-export-pdf"> - <a :href="pdfExportURL"> - <translate>Seite als pdf-Dokument exportieren</translate> - </a> - </li> - <li v-if="canEdit && oerEnabled" class="cw-action-widget-oer"> - <a href="#" @click="oerElement"> - <translate>Seite auf %{oerTitle} veröffentlichen</translate> - </a> - </li> <li v-if="!isRoot && canEdit" class="cw-action-widget-trash"> <a href="#" @click="deleteElement"> <translate>Seite löschen</translate> @@ -72,13 +57,9 @@ export default { mixins: [CoursewareExport], computed: { ...mapGetters({ - context: 'context', - oerEnabled: 'oerEnabled', - oerTitle: 'oerTitle', userId: 'userId', consumeMode: 'consumeMode', showToolbar: 'showToolbar', - userIsTeacher: 'userIsTeacher', }), isRoot() { if (!this.structuralElement) { @@ -111,48 +92,8 @@ export default { tocText() { return this.showToolbar ? this.$gettext('Inhaltsverzeichnis ausblenden') : this.$gettext('Inhaltsverzeichnis anzeigen'); }, - pdfExportURL() { - if (this.context.type === 'users') { - return STUDIP.URLHelper.getURL('dispatch.php/contents/courseware/pdf_export/' + this.structuralElement.id); - } - if (this.context.type === 'courses') { - return STUDIP.URLHelper.getURL('dispatch.php/course/courseware/pdf_export/' + this.structuralElement.id); - } - - return ''; - }, - isTask() { - return this.structuralElement?.relationships.task.data !== null; - }, - canExport() { - if (this.context.type === 'users') { - return true; - } - - return this.canEdit && this.userIsTeacher; - }, - tocText() { - return this.showToolbar ? this.$gettext('Inhaltsverzeichnis ausblenden') : this.$gettext('Inhaltsverzeichnis anzeigen'); - }, - pdfExportURL() { - if (this.context.type === 'users') { - return STUDIP.URLHelper.getURL('dispatch.php/contents/courseware/pdf_export/' + this.structuralElement.id); - } - if (this.context.type === 'courses') { - return STUDIP.URLHelper.getURL('dispatch.php/course/courseware/pdf_export/' + this.structuralElement.id); - } - - return ''; - }, isTask() { return this.structuralElement?.relationships.task.data !== null; - }, - canExport() { - if (this.context.type === 'users') { - return true; - } - - return this.canEdit && this.userIsTeacher; } }, methods: { @@ -161,8 +102,6 @@ export default { showElementAddDialog: 'showElementAddDialog', showElementDeleteDialog: 'showElementDeleteDialog', showElementInfoDialog: 'showElementInfoDialog', - showElementExportDialog: 'showElementExportDialog', - showElementOerDialog: 'showElementOerDialog', setStructuralElementSortMode: 'setStructuralElementSortMode', companionInfo: 'companionInfo', addBookmark: 'addBookmark', @@ -201,9 +140,6 @@ export default { addElement() { this.showElementAddDialog(true); }, - exportElement() { - this.showElementExportDialog(true); - }, showElementInfo() { this.showElementInfoDialog(true); }, @@ -211,9 +147,6 @@ export default { this.addBookmark(this.structuralElement); this.companionInfo({ info: this.$gettext('Das Lesezeichen wurde gesetzt.') }); }, - oerElement() { - this.showElementOerDialog(true); - }, toggleTOC() { this.setShowToolbar(!this.showToolbar); }, diff --git a/resources/vue/components/courseware/CoursewareExportWidget.vue b/resources/vue/components/courseware/CoursewareExportWidget.vue new file mode 100644 index 0000000000000000000000000000000000000000..e9c54dcda42f99dea4009d1b1d0c947a0d8c67a2 --- /dev/null +++ b/resources/vue/components/courseware/CoursewareExportWidget.vue @@ -0,0 +1,59 @@ +<template> + <ul class="widget-list widget-links cw-export-widget" v-if="structuralElement"> + <li class="cw-export-widget-export"> + <a href="#" @click="exportElement"> + <translate>Seite exportieren</translate> + </a> + </li> + <li v-if="canVisit" class="cw-export-widget-export-pdf"> + <a :href="pdfExportURL"> + <translate>Seite als pdf-Dokument exportieren</translate> + </a> + </li> + <li v-if="oerEnabled" class="cw-export-widget-oer"> + <a href="#" @click="oerElement"> + <translate>Seite auf %{oerTitle} veröffentlichen</translate> + </a> + </li> + </ul> +</template> + +<script> +import CoursewareExport from '@/vue/mixins/courseware/export.js'; +import { mapActions, mapGetters } from 'vuex'; + +export default { + name: 'courseware-export-widget', + props: ['structuralElement', 'canVisit'], + mixins: [CoursewareExport], + computed: { + ...mapGetters({ + context: 'context', + oerEnabled: 'oerEnabled', + oerTitle: 'oerTitle', + }), + pdfExportURL() { + if (this.context.type === 'users') { + return STUDIP.URLHelper.getURL('dispatch.php/contents/courseware/pdf_export/' + this.structuralElement.id); + } + if (this.context.type === 'courses') { + return STUDIP.URLHelper.getURL('dispatch.php/course/courseware/pdf_export/' + this.structuralElement.id); + } + + return ''; + }, + }, + methods: { + ...mapActions({ + showElementExportDialog: 'showElementExportDialog', + showElementOerDialog: 'showElementOerDialog', + }), + exportElement() { + this.showElementExportDialog(true); + }, + oerElement() { + this.showElementOerDialog(true); + } + }, +}; +</script> diff --git a/resources/vue/components/courseware/CoursewareStructuralElement.vue b/resources/vue/components/courseware/CoursewareStructuralElement.vue index 60f3aac77d02ba1ef6a00571bd900ff4ff8f0151..d35d7bd233c73f67fb9c9ebd0a4028b7f2c7e5f3 100755 --- a/resources/vue/components/courseware/CoursewareStructuralElement.vue +++ b/resources/vue/components/courseware/CoursewareStructuralElement.vue @@ -790,26 +790,6 @@ export default { menu.push({ id: 3, label: this.$gettext('Seite hinzufügen'), icon: 'add', emit: 'addElement' }); } - if ((this.userIsTeacher && this.canEdit) || this.context.type === 'users') { - menu.push({ - id: 6, - label: this.$gettext('Seite exportieren'), - icon: 'export', - emit: 'showExportOptions', - }); - } - if ((this.userIsTeacher || this.canEdit) && this.canVisit) { - menu.push({ - id: 7, - type: 'link', - label: this.$gettext('Seite als pdf-Dokument exportieren'), - icon: 'file-pdf', - url: this.pdfExportURL, - }); - } - if (this.canEdit && this.oerEnabled && this.userIsTeacher) { - menu.push({ id: 8, label: this.textOer.title, icon: 'oer-campus', emit: 'oerCurrentElement' }); - } if (!this.isRoot && this.canEdit && !this.isTask) { menu.push({ id: 9, diff --git a/resources/vue/components/courseware/IndexApp.vue b/resources/vue/components/courseware/IndexApp.vue index d2cc1f4309cc75c584b9da6ea7157459d6b33779..1a512727af026ae57215289fb9d811a49888a62d 100755 --- a/resources/vue/components/courseware/IndexApp.vue +++ b/resources/vue/components/courseware/IndexApp.vue @@ -10,6 +10,9 @@ <MountingPortal mountTo="#courseware-action-widget" name="sidebar-actions"> <courseware-action-widget :structural-element="selected" :canVisit="canVisit"></courseware-action-widget> </MountingPortal> + <MountingPortal mountTo="#courseware-export-widget" name="sidebar-actions" v-if="canExport"> + <courseware-export-widget :structural-element="selected" :canVisit="canVisit"></courseware-export-widget> + </MountingPortal> <MountingPortal mountTo="#courseware-view-widget" name="sidebar-views"> <courseware-view-widget :structural-element="selected" :canVisit="canVisit"></courseware-view-widget> </MountingPortal> @@ -31,6 +34,7 @@ import CoursewareStructuralElement from './CoursewareStructuralElement.vue'; import CoursewareViewWidget from './CoursewareViewWidget.vue'; import CoursewareActionWidget from './CoursewareActionWidget.vue'; +import CoursewareExportWidget from './CoursewareExportWidget.vue'; import CoursewareCompanionBox from './CoursewareCompanionBox.vue'; import StudipProgressIndicator from '../StudipProgressIndicator.vue'; import { mapActions, mapGetters } from 'vuex'; @@ -42,6 +46,7 @@ export default { CoursewareActionWidget, CoursewareCompanionBox, StudipProgressIndicator, + CoursewareExportWidget }, data: () => ({ canVisit: null, @@ -51,6 +56,7 @@ export default { }), computed: { ...mapGetters({ + context: 'context', courseware: 'courseware', orderedStructuralElements: 'courseware-structure/ordered', relatedStructuralElement: 'courseware-structural-elements/related', @@ -58,6 +64,7 @@ export default { structuralElements: 'courseware-structural-elements/all', structuralElementById: 'courseware-structural-elements/byId', userId: 'userId', + userIsTeacher: 'userIsTeacher' }), loadingErrorMessage() { switch (this.loadingErrorStatus) { @@ -68,7 +75,18 @@ export default { default: return this.$gettext('Beim Laden der Seite ist ein Fehler aufgetreten.'); } - } + }, + canExport() { + if (!this.selected) { + return false; + } + + if (this.context.type === 'users') { + return true; + } + + return this.selected.attributes['can-edit'] && this.userIsTeacher; + }, }, methods: { ...mapActions({