diff --git a/app/controllers/contents/courseware.php b/app/controllers/contents/courseware.php index 68926468a7887eb92fe1cea5755b86d667c17565..b8adb28585efa6b4aa922084fecb4044f0fa3778 100755 --- a/app/controllers/contents/courseware.php +++ b/app/controllers/contents/courseware.php @@ -55,12 +55,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'); @@ -73,12 +71,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; @@ -95,9 +92,19 @@ class Contents_CoursewareController extends AuthenticatedController $this->licenses = json_encode($this->licenses); $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( @@ -112,6 +119,13 @@ class Contents_CoursewareController extends AuthenticatedController ); $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/controllers/course/courseware.php b/app/controllers/course/courseware.php index 1d93a0a75162311a45ded29d4cb8d81b9eb6f8b4..decd88be56e5404a2b4f69a361decae86987d71b 100755 --- a/app/controllers/course/courseware.php +++ b/app/controllers/course/courseware.php @@ -49,7 +49,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; @@ -59,13 +59,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 @@ -89,7 +98,7 @@ class Course_CoursewareController extends AuthenticatedController } } - private function setIndexSidebar(): void + private function setIndexSidebar(bool $canExport): void { $sidebar = Sidebar::Get(); $actions = new TemplateWidget( @@ -103,6 +112,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'); + } } private function getProgressData(bool $showProgressForAllParticipants = false): iterable 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 9703adfee963d92e9b6078a840b2ce95a1b2dbe0..4aee207bbef030c0bfe1889ca0d93324c2f458bb 100755 --- a/resources/assets/stylesheets/scss/courseware.scss +++ b/resources/assets/stylesheets/scss/courseware.scss @@ -1458,7 +1458,7 @@ b l o c k a d d e r display: block; } } - } + } } .cw-blockadder-item { @@ -1694,7 +1694,9 @@ 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-oer{ diff --git a/resources/vue/components/courseware/CoursewareActionWidget.vue b/resources/vue/components/courseware/CoursewareActionWidget.vue index bf3fdcafb05118475f2052b0ea900cdb4efe0fe5..a289c5babfba8ce3f4b9362e66d1347c91f44216 100644 --- a/resources/vue/components/courseware/CoursewareActionWidget.vue +++ b/resources/vue/components/courseware/CoursewareActionWidget.vue @@ -30,16 +30,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 && 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> @@ -62,12 +52,9 @@ export default { mixins: [CoursewareExport], computed: { ...mapGetters({ - oerEnabled: 'oerEnabled', - oerTitle: 'oerTitle', userId: 'userId', consumeMode: 'consumeMode', showToolbar: 'showToolbar', - userIsTeacher: 'userIsTeacher', }), isRoot() { if (!this.structuralElement) { @@ -107,8 +94,7 @@ export default { showElementAddDialog: 'showElementAddDialog', showElementDeleteDialog: 'showElementDeleteDialog', showElementInfoDialog: 'showElementInfoDialog', - showElementExportDialog: 'showElementExportDialog', - showElementOerDialog: 'showElementOerDialog', + setStructuralElementSortMode: 'setStructuralElementSortMode', companionInfo: 'companionInfo', addBookmark: 'addBookmark', lockObject: 'lockObject', @@ -143,9 +129,6 @@ export default { addElement() { this.showElementAddDialog(true); }, - exportElement() { - this.showElementExportDialog(true); - }, showElementInfo() { this.showElementInfoDialog(true); }, @@ -153,9 +136,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 92e7c4c3f6e80aa544519acbd60b60d2a0c60e9d..68f58ea812f63d2d39b459504bf1074435dff378 100755 --- a/resources/vue/components/courseware/CoursewareStructuralElement.vue +++ b/resources/vue/components/courseware/CoursewareStructuralElement.vue @@ -737,19 +737,10 @@ export default { emit: 'editCurrentElement', }); menu.push({ id: 2, label: this.$gettext('Seite hinzufügen'), icon: 'add', emit: 'addElement' }); - menu.push({ - id: 5, - label: this.$gettext('Seite exportieren'), - icon: 'export', - emit: 'showExportOptions', - }); - } - if (this.canEdit && this.oerEnabled) { - menu.push({ id: 6, label: this.textOer.title, icon: 'oer-campus', emit: 'oerCurrentElement' }); } if (!this.isRoot && this.canEdit) { menu.push({ - id: 7, + id: 9, label: this.$gettext('Seite löschen'), icon: 'trash', emit: 'deleteCurrentElement', diff --git a/resources/vue/components/courseware/IndexApp.vue b/resources/vue/components/courseware/IndexApp.vue index 4f271069bd603826c33584c28351b4846b6273c8..579fe21a0e12a2e90903e4a3a9a53a67d939eb16 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"></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></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({