diff --git a/app/controllers/contents/courseware.php b/app/controllers/contents/courseware.php index c1ca32137bd1de4ed6293f4faa28a5c9b836fa2d..c7edcaced56a533916d8e4ae7c8bb0934ee79934 100644 --- a/app/controllers/contents/courseware.php +++ b/app/controllers/contents/courseware.php @@ -117,11 +117,7 @@ class Contents_CoursewareController extends AuthenticatedController private function setCoursewareSidebar() { $sidebar = \Sidebar::Get(); - $actions = new TemplateWidget( - _('Aktionen'), - $this->get_template_factory()->open('course/courseware/action_widget') - ); - $sidebar->addWidget($actions)->addLayoutCSSClass('courseware-action-widget'); + $sidebar->addWidget(new VueWidget('courseware-action-widget')); $views = new TemplateWidget( _('Suche'), @@ -129,17 +125,8 @@ class Contents_CoursewareController extends AuthenticatedController ); $sidebar->addWidget($views)->addLayoutCSSClass('courseware-search-widget'); - $views = new \TemplateWidget( - _('Ansichten'), - $this->get_template_factory()->open('course/courseware/view_widget') - ); - $sidebar->addWidget($views)->addLayoutCSSClass('courseware-view-widget'); - - $exports = new TemplateWidget( - _('Export '), - $this->get_template_factory()->open('course/courseware/export_widget') - ); - $sidebar->addWidget($exports)->addLayoutCSSClass('courseware-export-widget'); + $sidebar->addWidget(new VueWidget('courseware-view-widget')); + $sidebar->addWidget(new VueWidget('courseware-export-widget')); } private function getLicences() diff --git a/app/controllers/course/courseware.php b/app/controllers/course/courseware.php index 7c41756a92f2c56aac003a71eca35c7f8a19766e..9174192226a8f87d555c16db2aef759f4dca903c 100644 --- a/app/controllers/course/courseware.php +++ b/app/controllers/course/courseware.php @@ -110,11 +110,7 @@ class Course_CoursewareController extends AuthenticatedController private function setIndexSidebar(): void { $sidebar = Sidebar::Get(); - $actions = new TemplateWidget( - _('Aktionen'), - $this->get_template_factory()->open('course/courseware/action_widget') - ); - $sidebar->addWidget($actions)->addLayoutCSSClass('courseware-action-widget'); + $sidebar->addWidget(new VueWidget('courseware-action-widget')); $views = new TemplateWidget( _('Suche'), @@ -122,20 +118,10 @@ class Course_CoursewareController extends AuthenticatedController ); $sidebar->addWidget($views)->addLayoutCSSClass('courseware-search-widget'); - $views = new TemplateWidget( - _('Ansichten'), - $this->get_template_factory()->open('course/courseware/view_widget') - ); - $sidebar->addWidget($views)->addLayoutCSSClass('courseware-view-widget'); - - $exports = new TemplateWidget( - _('Export '), - $this->get_template_factory()->open('course/courseware/export_widget') - ); - $sidebar->addWidget($exports)->addLayoutCSSClass('courseware-export-widget'); + $sidebar->addWidget(new VueWidget('courseware-view-widget')); + $sidebar->addWidget(new VueWidget('courseware-export-widget')); } - private function setDashboardSidebar(): void { $sidebar = Sidebar::Get(); diff --git a/app/views/course/courseware/action_widget.php b/app/views/course/courseware/action_widget.php deleted file mode 100644 index b13792e2cc059f27d0d6d3ca64219c73c6025d4c..0000000000000000000000000000000000000000 --- a/app/views/course/courseware/action_widget.php +++ /dev/null @@ -1 +0,0 @@ -<aside id="courseware-action-widget" class="widget-sidebar"></aside> diff --git a/app/views/course/courseware/export_widget.php b/app/views/course/courseware/export_widget.php deleted file mode 100644 index 1d7feb2c6e467b5e10160fe829589f0f4c80dd15..0000000000000000000000000000000000000000 --- a/app/views/course/courseware/export_widget.php +++ /dev/null @@ -1 +0,0 @@ -<aside id="courseware-export-widget" class="widget-sidebar"></aside> diff --git a/app/views/course/courseware/view_widget.php b/app/views/course/courseware/view_widget.php deleted file mode 100644 index 826913411ac922bd5a2f02844bff7946e2e985b5..0000000000000000000000000000000000000000 --- a/app/views/course/courseware/view_widget.php +++ /dev/null @@ -1 +0,0 @@ -<aside id="courseware-view-widget" class="widget-sidebar"></aside> diff --git a/lib/classes/sidebar/VueWidget.php b/lib/classes/sidebar/VueWidget.php new file mode 100644 index 0000000000000000000000000000000000000000..f4f0583acc2466d98374ab47e65ecdfe934ebf1f --- /dev/null +++ b/lib/classes/sidebar/VueWidget.php @@ -0,0 +1,20 @@ +<?php +/** + * This widget type delegates all rendering of the widget to vuejs. + * + * @author Elmar Ludwig + * @license GPL2 or any later version + * @since Stud.IP 5.0 + */ +class VueWidget extends Widget +{ + /** + * Constructs the widget with the given id on the element. + */ + public function __construct($id) + { + $this->id = $id; + $this->layout = 'widgets/vue-widget'; + $this->forced_rendering = true; + } +} diff --git a/resources/vue/base-components.js b/resources/vue/base-components.js index 526687b39763215284e518e8ae748ffc806ca419..97231d2827d47162ce34672b2cec476f0e55646c 100644 --- a/resources/vue/base-components.js +++ b/resources/vue/base-components.js @@ -1,6 +1,7 @@ import Multiselect from './components/Multiselect.vue'; import EditableList from "./components/EditableList.vue"; import Quicksearch from './components/Quicksearch.vue'; +import SidebarWidget from './components/SidebarWidget.vue'; import StudipActionMenu from './components/StudipActionMenu.vue'; import StudipAssetImg from './components/StudipAssetImg.vue'; import StudipDateTime from './components/StudipDateTime.vue'; @@ -23,6 +24,7 @@ const BaseComponents = { EditableList, Quicksearch, RangeInput, + SidebarWidget, StudipActionMenu, StudipAssetImg, StudipDateTime, diff --git a/resources/vue/components/SidebarWidget.vue b/resources/vue/components/SidebarWidget.vue new file mode 100644 index 0000000000000000000000000000000000000000..34d935d84faadd3648ae4788e86e6f46f8fd6cc9 --- /dev/null +++ b/resources/vue/components/SidebarWidget.vue @@ -0,0 +1,19 @@ +<template> + <div class="sidebar-widget"> + <div class="sidebar-widget-header" v-if="title"> + {{ title }} + </div> + <div class="sidebar-widget-content"> + <slot name="content" /> + </div> + </div> +</template> + +<script> +export default { + name: 'sidebar-widget', + props: { + title: String, + }, +} +</script> diff --git a/resources/vue/components/courseware/CoursewareActionWidget.vue b/resources/vue/components/courseware/CoursewareActionWidget.vue index 572a94e6bc758042d047ecee96e521b81e4ff46a..cc1738d55a129aa8dd88ba9bcd67161c1b8c07b7 100644 --- a/resources/vue/components/courseware/CoursewareActionWidget.vue +++ b/resources/vue/components/courseware/CoursewareActionWidget.vue @@ -1,60 +1,65 @@ <template> - <ul class="widget-list widget-links cw-action-widget" v-if="structuralElement"> - <li class="cw-action-widget-show-toc"> - <button @click="toggleTOC"> - {{ tocText }} - </button> - </li> - <li class="cw-action-widget-show-consume-mode"> - <button @click="showConsumeMode"> - <translate>Vollbild einschalten</translate> - </button> - </li> - <li v-if="canEdit" class="cw-action-widget-edit"> - <button @click="editElement"> - <translate>Seite bearbeiten</translate> - </button> - </li> - <li v-if="canEdit" class="cw-action-widget-sort"> - <button @click="sortContainers"> - <translate>Abschnitte sortieren</translate> - </button> - </li> - <li v-if="canEdit" class="cw-action-widget-add"> - <button @click="addElement"> - <translate>Seite hinzufügen</translate> - </button> - </li> - <li class="cw-action-widget-info"> - <button @click="showElementInfo"> - <translate>Informationen anzeigen</translate> - </button> - </li> - <li class="cw-action-widget-star"> - <button @click="createBookmark"> - <translate>Lesezeichen setzen</translate> - </button> - </li> - <li v-if="context.type === 'users'" class="cw-action-widget-link"> - <button @click="linkElement"> - <translate>Öffentlichen Link erzeugen</translate> - </button> - </li> - <li v-if="!isOwner" class="cw-action-widget-oer"> - <button @click="suggestOER"> - <translate>Material für %{oerTitle} vorschlagen</translate> - </button> - </li> - <li v-if="!isRoot && canEdit" class="cw-action-widget-trash"> - <button @click="deleteElement"> - <translate>Seite löschen</translate> - </button> - </li> - </ul> + <sidebar-widget :title="$gettext('Aktionen')" v-if="structuralElement"> + <template #content> + <ul class="widget-list widget-links cw-action-widget"> + <li class="cw-action-widget-show-toc"> + <button @click="toggleTOC"> + {{ tocText }} + </button> + </li> + <li class="cw-action-widget-show-consume-mode"> + <button @click="showConsumeMode"> + <translate>Vollbild einschalten</translate> + </button> + </li> + <li v-if="canEdit" class="cw-action-widget-edit"> + <button @click="editElement"> + <translate>Seite bearbeiten</translate> + </button> + </li> + <li v-if="canEdit" class="cw-action-widget-sort"> + <button @click="sortContainers"> + <translate>Abschnitte sortieren</translate> + </button> + </li> + <li v-if="canEdit" class="cw-action-widget-add"> + <button @click="addElement"> + <translate>Seite hinzufügen</translate> + </button> + </li> + <li class="cw-action-widget-info"> + <button @click="showElementInfo"> + <translate>Informationen anzeigen</translate> + </button> + </li> + <li class="cw-action-widget-star"> + <button @click="createBookmark"> + <translate>Lesezeichen setzen</translate> + </button> + </li> + <li v-if="context.type === 'users'" class="cw-action-widget-link"> + <button @click="linkElement"> + <translate>Öffentlichen Link erzeugen</translate> + </button> + </li> + <li v-if="!isOwner" class="cw-action-widget-oer"> + <button @click="suggestOER"> + <translate>Material für %{oerTitle} vorschlagen</translate> + </button> + </li> + <li v-if="!isRoot && canEdit" class="cw-action-widget-trash"> + <button @click="deleteElement"> + <translate>Seite löschen</translate> + </button> + </li> + </ul> + </template> + </sidebar-widget> </template> <script> import StudipIcon from './../StudipIcon.vue'; +import SidebarWidget from '../SidebarWidget.vue'; import CoursewareExport from '@/vue/mixins/courseware/export.js'; import { mapActions, mapGetters } from 'vuex'; @@ -63,6 +68,7 @@ export default { props: ['structuralElement', 'canVisit'], components: { StudipIcon, + SidebarWidget, }, mixins: [CoursewareExport], computed: { diff --git a/resources/vue/components/courseware/CoursewareExportWidget.vue b/resources/vue/components/courseware/CoursewareExportWidget.vue index 7b55a7898cb9a2cfb4ebf1dbaff89a6610f191bc..2c821b735cdf66da5b26295b6d17f42bdb9cdd50 100644 --- a/resources/vue/components/courseware/CoursewareExportWidget.vue +++ b/resources/vue/components/courseware/CoursewareExportWidget.vue @@ -1,33 +1,41 @@ <template> - <ul class="widget-list widget-links cw-export-widget" v-if="structuralElement"> - <li v-if="showExportArchiv" class="cw-export-widget-export"> - <button @click="exportElement"> - <translate>Seite exportieren</translate> - </button> - </li> - <li v-if="showExportPdf" class="cw-export-widget-export-pdf"> - <button @click="pdfElement"> - <translate>Seite als pdf-Dokument exportieren</translate> - </button> - </li> - <li v-if="showOer" class="cw-export-widget-oer"> - <button @click="oerElement"> - <translate>Seite auf %{oerTitle} veröffentlichen</translate> - </button> - </li> - <li v-if="!showExportArchiv && !showExportPdf && !showOer"> - <translate>Keine Exportoptionen verfügbar</translate> - </li> - </ul> + <sidebar-widget :title="$gettext('Export')" v-if="structuralElement"> + <template #content> + <ul class="widget-list widget-links cw-export-widget" v-if="structuralElement"> + <li v-if="showExportArchiv" class="cw-export-widget-export"> + <button @click="exportElement"> + <translate>Seite exportieren</translate> + </button> + </li> + <li v-if="showExportPdf" class="cw-export-widget-export-pdf"> + <button @click="pdfElement"> + <translate>Seite als pdf-Dokument exportieren</translate> + </button> + </li> + <li v-if="showOer" class="cw-export-widget-oer"> + <button @click="oerElement"> + <translate>Seite auf %{oerTitle} veröffentlichen</translate> + </button> + </li> + <li v-if="!showExportArchiv && !showExportPdf && !showOer"> + <translate>Keine Exportoptionen verfügbar</translate> + </li> + </ul> + </template> + </sidebar-widget> </template> <script> +import SidebarWidget from '../SidebarWidget.vue'; import CoursewareExport from '@/vue/mixins/courseware/export.js'; import { mapActions, mapGetters } from 'vuex'; export default { name: 'courseware-export-widget', props: ['structuralElement', 'canVisit'], + components: { + SidebarWidget + }, mixins: [CoursewareExport], computed: { ...mapGetters({ diff --git a/resources/vue/components/courseware/CoursewareRibbon.vue b/resources/vue/components/courseware/CoursewareRibbon.vue index 72a3a50983664a4ab5226531896a13fdfce5bff1..f6797fcd9a34500df6af4437b2b50a843015d43c 100644 --- a/resources/vue/components/courseware/CoursewareRibbon.vue +++ b/resources/vue/components/courseware/CoursewareRibbon.vue @@ -15,12 +15,14 @@ </div> <div class="cw-ribbon-wrapper-right"> <button + v-if="showToolbarButton" class="cw-ribbon-button cw-ribbon-button-menu" :title="textRibbon.toolbar" @click.prevent="activeToolbar" > </button> <button + v-if="showModeSwitchButton" ref="consumeModeSwitch" class="cw-ribbon-button" :class="[consumeMode ? 'cw-ribbon-button-zoom-out' : 'cw-ribbon-button-zoom']" diff --git a/resources/vue/components/courseware/CoursewareViewWidget.vue b/resources/vue/components/courseware/CoursewareViewWidget.vue index 86c157a1364e627d8b838aad766a4e134c2bc139..fb3de7441a2c90ad5387472c7228c5bf37089422 100644 --- a/resources/vue/components/courseware/CoursewareViewWidget.vue +++ b/resources/vue/components/courseware/CoursewareViewWidget.vue @@ -1,35 +1,43 @@ <template> - <ul class="widget-list widget-links sidebar-views cw-view-widget"> - <li :class="{ active: readView }"> - <button @click="setReadView"> - <translate>Lesen</translate> - </button> - </li> - <li - v-if="canEdit" - :class="{ active: editView }" - > - <button @click="setEditView"> - <translate>Bearbeiten</translate> - </button> - </li> - <li - v-if="context.type === 'courses' && canVisit" - :class="{ active: discussView }" - > - <button @click="setDiscussView"> - <translate>Kommentieren</translate> - </button> - </li> - </ul> + <sidebar-widget :title="$gettext('Ansichten')" v-if="structuralElement"> + <template #content> + <ul class="widget-list widget-links sidebar-views cw-view-widget"> + <li :class="{ active: readView }"> + <button @click="setReadView"> + <translate>Lesen</translate> + </button> + </li> + <li + v-if="canEdit" + :class="{ active: editView }" + > + <button @click="setEditView"> + <translate>Bearbeiten</translate> + </button> + </li> + <li + v-if="context.type === 'courses' && canVisit" + :class="{ active: discussView }" + > + <button @click="setDiscussView"> + <translate>Kommentieren</translate> + </button> + </li> + </ul> + </template> + </sidebar-widget> </template> <script> +import SidebarWidget from '../SidebarWidget.vue'; import { mapActions, mapGetters } from 'vuex'; export default { name: 'courseware-view-widget', props: ['structuralElement', 'canVisit'], + components: { + SidebarWidget + }, computed: { ...mapGetters({ viewMode: 'viewMode', diff --git a/resources/vue/components/courseware/IndexApp.vue b/resources/vue/components/courseware/IndexApp.vue index 5d9f1d202c1045fd5c15d21716c3f2e81c60d5eb..7c9c15304b14fce1e429664e86638471b356c736 100644 --- a/resources/vue/components/courseware/IndexApp.vue +++ b/resources/vue/components/courseware/IndexApp.vue @@ -10,16 +10,16 @@ @select="selectStructuralElement" ></courseware-structural-element> <MountingPortal mountTo="#courseware-action-widget" name="sidebar-actions"> - <courseware-action-widget :structural-element="selected" :canVisit="canVisit"></courseware-action-widget> + <courseware-action-widget :structural-element="selected" :canVisit="canVisit" v-if="!showSearchResults"></courseware-action-widget> </MountingPortal> <MountingPortal mountTo="#courseware-search-widget" name="sidebar-search"> <courseware-search-widget></courseware-search-widget> </MountingPortal> <MountingPortal mountTo="#courseware-view-widget" name="sidebar-views"> - <courseware-view-widget :structural-element="selected" :canVisit="canVisit"></courseware-view-widget> + <courseware-view-widget :structural-element="selected" :canVisit="canVisit" v-if="!showSearchResults"></courseware-view-widget> </MountingPortal> <MountingPortal mountTo="#courseware-export-widget" name="sidebar-export"> - <courseware-export-widget :structural-element="selected" :canVisit="canVisit"></courseware-export-widget> + <courseware-export-widget :structural-element="selected" :canVisit="canVisit" v-if="!showSearchResults"></courseware-export-widget> </MountingPortal> </div> <studip-progress-indicator diff --git a/templates/widgets/vue-widget.php b/templates/widgets/vue-widget.php new file mode 100644 index 0000000000000000000000000000000000000000..6c376613e8b0c846ed8309571b1f525794958153 --- /dev/null +++ b/templates/widgets/vue-widget.php @@ -0,0 +1 @@ +<div id="<?= htmlReady($id) ?>"></div>