From 936d1c00ea05bb0a5c56f441ff2eece6ccefada6 Mon Sep 17 00:00:00 2001 From: Thomas Hackl Date: Mon, 12 Dec 2022 15:20:27 +0000 Subject: Resolve "StEP00348: Responsive Navigation Stud.IP 5.x" Closes #32 Merge request studip/studip!65 --- app/controllers/oer/market.php | 9 +- app/views/profile/extern.php | 2 +- app/views/profile/index.php | 2 +- lib/classes/ContentBar.php | 34 +- lib/classes/ResponsiveHelper.php | 173 ++++- lib/classes/SkipLinks.php | 24 +- lib/classes/WidgetContainer.php | 20 +- lib/classes/sidebar/Sidebar.php | 6 +- lib/include/html_head.inc.php | 6 - lib/modules/ConsultationModule.class.php | 8 +- lib/modules/CoursewareModule.class.php | 1 + lib/navigation/FooterNavigation.php | 6 +- lib/wiki.inc.php | 20 +- public/assets/images/icons/black/focusmode-off.svg | 1 + public/assets/images/icons/blue/focusmode-off.svg | 1 + public/assets/images/icons/blue/fullscreen-off.svg | 2 +- .../assets/images/icons/blue/fullscreen-off2.svg | 1 + .../assets/images/icons/blue/fullscreen-off3.svg | 1 + public/assets/images/icons/blue/fullscreen-on.svg | 2 +- public/assets/images/icons/blue/fullscreen-on2.svg | 1 + public/assets/images/icons/blue/fullscreen-on3.svg | 1 + public/assets/images/icons/blue/fullscreen-on4.svg | 1 + public/assets/images/icons/blue/fullscreen-on5.svg | 1 + public/assets/images/icons/blue/maximise.svg | 1 + public/assets/images/icons/blue/sidebar-open.svg | 1 + public/assets/images/icons/blue/sidebar.svg | 1 + public/assets/images/icons/blue/sidebar3.svg | 1 + public/assets/images/icons/blue/zoom-in.svg | 2 +- public/assets/images/icons/blue/zoom-in2.svg | 2 +- public/assets/images/icons/blue/zoom-out.svg | 2 +- public/assets/images/icons/blue/zoom-out2.svg | 2 +- public/assets/images/icons/green/focusmode-off.svg | 1 + public/assets/images/icons/grey/focusmode-off.svg | 1 + public/assets/images/icons/red/focusmode-off.svg | 1 + public/assets/images/icons/white/focusmode-off.svg | 1 + .../assets/images/icons/white/fullscreen-off.svg | 2 +- .../assets/images/icons/white/fullscreen-off2.svg | 1 + .../assets/images/icons/white/fullscreen-off3.svg | 1 + public/assets/images/icons/white/fullscreen-on.svg | 2 +- .../assets/images/icons/white/fullscreen-on2.svg | 1 + .../assets/images/icons/white/fullscreen-on3.svg | 1 + .../assets/images/icons/white/fullscreen-on4.svg | 1 + .../assets/images/icons/yellow/focusmode-off.svg | 1 + .../javascripts/bootstrap/responsive-navigation.js | 10 + .../assets/javascripts/bootstrap/responsive.js | 5 + resources/assets/javascripts/entry-base.js | 1 + resources/assets/javascripts/lib/header_magic.js | 21 - resources/assets/javascripts/lib/responsive.js | 142 +--- resources/assets/stylesheets/highcontrast.scss | 8 +- resources/assets/stylesheets/less/breakpoints.less | 4 +- resources/assets/stylesheets/less/responsive.less | 493 ------------- resources/assets/stylesheets/less/visibility.less | 44 +- resources/assets/stylesheets/scss/breakpoints.scss | 7 +- resources/assets/stylesheets/scss/buttons.scss | 5 + resources/assets/stylesheets/scss/contentbar.scss | 188 +++-- resources/assets/stylesheets/scss/courseware.scss | 2 +- resources/assets/stylesheets/scss/header.scss | 29 +- resources/assets/stylesheets/scss/helpbar.scss | 3 +- resources/assets/stylesheets/scss/layouts.scss | 4 +- resources/assets/stylesheets/scss/navigation.scss | 41 +- resources/assets/stylesheets/scss/responsive.scss | 796 +++++++++++++++++++++ .../assets/stylesheets/scss/table_of_contents.scss | 25 +- resources/assets/stylesheets/scss/visibility.scss | 49 +- resources/assets/stylesheets/studip.less | 3 - resources/assets/stylesheets/studip.scss | 1 + resources/vue/components/BlubberThread.vue | 2 +- .../vue/components/courseware/CoursewareRibbon.vue | 10 +- .../courseware/CoursewareStructuralElement.vue | 2 +- .../vue/components/responsive/NavigationItem.vue | 83 +++ .../components/responsive/ResponsiveContentBar.vue | 206 ++++++ .../components/responsive/ResponsiveNavigation.vue | 525 ++++++++++++++ .../components/responsive/ResponsiveSkipLinks.vue | 49 ++ .../vue/components/responsive/ToggleFullscreen.vue | 51 ++ resources/vue/mixins/MyCoursesMixin.js | 4 +- templates/contentbar/contentbar.php | 57 +- templates/footer.php | 3 +- templates/header.php | 36 +- templates/layouts/base.php | 16 +- templates/skiplinks.php | 15 +- templates/tabs.php | 10 +- 80 files changed, 2356 insertions(+), 943 deletions(-) create mode 100644 public/assets/images/icons/black/focusmode-off.svg create mode 100644 public/assets/images/icons/blue/focusmode-off.svg create mode 100644 public/assets/images/icons/blue/fullscreen-off2.svg create mode 100644 public/assets/images/icons/blue/fullscreen-off3.svg create mode 100644 public/assets/images/icons/blue/fullscreen-on2.svg create mode 100644 public/assets/images/icons/blue/fullscreen-on3.svg create mode 100644 public/assets/images/icons/blue/fullscreen-on4.svg create mode 100644 public/assets/images/icons/blue/fullscreen-on5.svg create mode 100644 public/assets/images/icons/blue/maximise.svg create mode 100644 public/assets/images/icons/blue/sidebar-open.svg create mode 100644 public/assets/images/icons/blue/sidebar.svg create mode 100644 public/assets/images/icons/blue/sidebar3.svg create mode 100644 public/assets/images/icons/green/focusmode-off.svg create mode 100644 public/assets/images/icons/grey/focusmode-off.svg create mode 100644 public/assets/images/icons/red/focusmode-off.svg create mode 100644 public/assets/images/icons/white/focusmode-off.svg create mode 100644 public/assets/images/icons/white/fullscreen-off2.svg create mode 100644 public/assets/images/icons/white/fullscreen-off3.svg create mode 100644 public/assets/images/icons/white/fullscreen-on2.svg create mode 100644 public/assets/images/icons/white/fullscreen-on3.svg create mode 100644 public/assets/images/icons/white/fullscreen-on4.svg create mode 100644 public/assets/images/icons/yellow/focusmode-off.svg create mode 100644 resources/assets/javascripts/bootstrap/responsive-navigation.js delete mode 100644 resources/assets/stylesheets/less/responsive.less create mode 100644 resources/assets/stylesheets/scss/responsive.scss create mode 100644 resources/vue/components/responsive/NavigationItem.vue create mode 100644 resources/vue/components/responsive/ResponsiveContentBar.vue create mode 100644 resources/vue/components/responsive/ResponsiveNavigation.vue create mode 100644 resources/vue/components/responsive/ResponsiveSkipLinks.vue create mode 100644 resources/vue/components/responsive/ToggleFullscreen.vue diff --git a/app/controllers/oer/market.php b/app/controllers/oer/market.php index 23782a4..4071d07 100644 --- a/app/controllers/oer/market.php +++ b/app/controllers/oer/market.php @@ -271,11 +271,10 @@ class Oer_MarketController extends StudipController } } - $this->contentbar = new ContentBar( - new TOCItem($this->material['name']), - $infotext, - Icon::create('oer-campus') - ); + $this->contentbar = ContentBar::get() + ->setTOC(new TOCItem($this->material['name'])) + ->setInfo($infotext) + ->setIcon(Icon::create('oer-campus')); } public function embed_action($material_id) diff --git a/app/views/profile/extern.php b/app/views/profile/extern.php index 9524837..60ec961 100644 --- a/app/views/profile/extern.php +++ b/app/views/profile/extern.php @@ -1,4 +1,4 @@ -
+
diff --git a/app/views/profile/index.php b/app/views/profile/index.php index 1062f74..72e9c9f 100644 --- a/app/views/profile/index.php +++ b/app/views/profile/index.php @@ -1,4 +1,4 @@ -
+
user_id)->getImageTag(Avatar::NORMAL) ?>
diff --git a/lib/classes/ContentBar.php b/lib/classes/ContentBar.php index 043fe18..53b3dfc 100644 --- a/lib/classes/ContentBar.php +++ b/lib/classes/ContentBar.php @@ -15,25 +15,41 @@ class ContentBar public $infoText = ''; public $icon = ''; public $toc = null; + public $actionMenu = null; + /** - * ContentBar constructor. - * - * Note: An icon for consumer mode is always shown, this would have to be changed via template. + * The singleton instance of the container + */ + protected static $instance = null; + + /** + * Returns the instance of this container to ensure there is only one + * instance. * * @param TOCItem $toc Table of contents object. * @param string $info Some information to show, like creation date, author etc. * @param Icon|null $icon An icon to show in content bar. * @param ActionMenu|null $actionMenu Optional action menu for page actions. + * @return ContentBar + * @static */ - public function __construct(TOCItem $toc, string $info = '', Icon $icon = null, ActionMenu $actionMenu = null) + public static function get(): ContentBar { - $this->infoText = $info; - $this->icon = $icon; - $this->toc = $toc; - $this->actionMenu = $actionMenu; + if (static::$instance === null) { + static::$instance = new static; + } + return static::$instance; } - public $actionMenu = null; + /** + * Private constructor to ensure that the singleton Get() method is always + * used. + * + * @see ContentBar::get + */ + protected function __construct() + { + } /** * Provide some info text. diff --git a/lib/classes/ResponsiveHelper.php b/lib/classes/ResponsiveHelper.php index eb7f41c..c2b201e 100644 --- a/lib/classes/ResponsiveHelper.php +++ b/lib/classes/ResponsiveHelper.php @@ -24,27 +24,54 @@ class ResponsiveHelper $link_params = array_fill_keys(array_keys(URLHelper::getLinkParams()), null); foreach (Navigation::getItem('/')->getSubNavigation() as $path => $nav) { - if (!$nav->isVisible(true)) { - continue; + $image = $nav->getImage(); + + $forceVisibility = false; + /* + * Special treatment for "browse" navigation which is normally hidden + * when we are inside a course. + */ + if ($path === 'browse' && !$image) { + $image = Icon::create('seminar'); + $forceVisibility = true; + } + /* + * Special treatment for "footer" navigation because + * the real footer is hidden in responsive view. + */ + if ($path === 'footer' && !$image) { + $image = Icon::create('info'); + $nav->setTitle(_('Impressum & Information')); + $forceVisibility = true; } - $image = $nav->getImage(); $image_src = $image ? $image->copyWithRole('info_alt')->asImagePath() : false; $item = [ - 'icon' => $image_src ? self::getAssetsURL($image_src) : false, - 'title' => (string) $nav->getTitle(), - 'url' => self::getURL($nav->getURL(), $link_params), + 'icon' => $image_src ? self::getAssetsURL($image_src) : false, + 'title' => (string) $nav->getTitle(), + 'url' => URLHelper::getURL($nav->getURL(), $link_params, true), + 'parent' => '/', + 'path' => $path, + 'visible' => $forceVisibility ? true : $nav->isVisible(true), + 'active' => $nav->isActive() ]; if ($nav->isActive()) { - $activated[] = $path; + // course navigation is integrated in course sub-navigation items + if ($path === 'course') { + $activated[] = 'browse/my_courses/' . (Context::get()->getId()); + } else { + $activated[] = $path; + } } - if ($nav->getSubnavigation() && $path != 'start') { + if ($nav->getSubnavigation() && $path != 'start') { $item['children'] = self::getChildren($nav, $path, $activated); } - $navigation[$path] = $item; + if ($path !== 'course') { + $navigation[$path] = $item; + } } return [$navigation, $activated]; @@ -54,35 +81,50 @@ class ResponsiveHelper * Recursively build a navigation array from the subnavigation/children * of a navigation object. * - * @param Navigation $navigation The navigation object - * @param String $path Current path segment - * @param array $activated Activated items + * @param Navigation $navigation The navigation object + * @param String $path Current path segment + * @param array $activated Activated items + * @param String|null $cid Optional context ID * @return Array containing the children (+ grandchildren...) */ - protected static function getChildren(Navigation $navigation, $path, &$activated = []) + protected static function getChildren(Navigation $navigation, $path, &$activated = [], string $cid = null) { $children = []; foreach ($navigation->getSubNavigation() as $subpath => $subnav) { - if (!$subnav->isVisible()) { + /*if (!$subnav->isVisible()) { continue; - } + }*/ + $originalSubpath = $subpath; $subpath = "{$path}/{$subpath}"; $item = [ - 'title' => (string) $subnav->getTitle(), - 'url' => self::getURL($subnav->getURL()), + 'title' => (string) $subnav->getTitle(), + 'url' => URLHelper::getURL($subnav->getURL(), $cid ? ['cid' => $cid] : []), + 'parent' => $path, + 'path' => $subpath, + 'visible' => $subnav->isVisible(), + 'active' => $subnav->isActive() ]; if ($subnav->isActive()) { - $activated[] = $subpath; + // course navigation is integrated in course sub-navigation items + if ($path === 'course') { + $activated[] = 'browse/my_courses/' . Context::get()->getId() . '/' . $originalSubpath; + } else { + $activated[] = $subpath; + } } if ($subnav->getSubNavigation()) { $item['children'] = self::getChildren($subnav, $subpath); } + if ($subpath === 'browse/my_courses') { + $item['children'] = array_merge($item['children'] ?? [], static::getMyCoursesNavigation($activated)); + } + $children[$subpath] = $item; } @@ -113,4 +155,99 @@ class ResponsiveHelper { return str_replace($GLOBALS['ASSETS_URL'], '', $url); } + + /** + * Specialty for responsive navigation: build navigation items + * for my courses in current semester. + * + * @return array + */ + protected static function getMyCoursesNavigation($activated): array + { + if (!$GLOBALS['perm']->have_perm('admin')) { + $sem_data = Semester::getAllAsArray(); + + $currentIndex = -1; + + foreach ($sem_data as $index => $semester) { + if ($semester['current']) { + $currentIndex = $index; + break; + } + } + + $params = [ + 'deputies_enabled' => Config::get()->DEPUTIES_ENABLE + ]; + + $courses = MyRealmModel::getCourses($currentIndex, $currentIndex, $params); + } else { + $courses = []; + } + + $items = []; + + $standardIcon = Icon::create('seminar', Icon::ROLE_INFO_ALT)->asImagePath(); + + // Add current course to list. + if (Context::get() && Context::isCourse()) { + $courses[] = Context::get(); + } + + foreach ($courses as $course) { + $avatar = CourseAvatar::getAvatar($course->id); + if ($avatar->is_customized()) { + $icon = $avatar->getURL(Avatar::SMALL); + } else { + $icon = $standardIcon; + } + + $cnav = [ + 'icon' => $icon, + 'title' => $course->getFullname(), + 'url' => URLHelper::getURL('dispatch.php/course/details', ['cid' => $course->id]), + 'parent' => 'browse/my_courses', + 'path' => 'browse/my_courses/' . $course->id, + 'visible' => true, + 'active' => Course::findCurrent() ? Course::findCurrent()->id === $course->id : false, + 'children' => [] + ]; + + foreach ($course->tools as $tool) { + if (Seminar_Perm::get()->have_studip_perm($tool->getVisibilityPermission(), $course->id)) { + + $path = 'browse/my_courses/' . $course->id; + + $studip_module = $tool->getStudipModule(); + if ($studip_module instanceof StudipModule) { + $tool_nav = $studip_module->getTabNavigation($course->id) ?: []; + foreach ($tool_nav as $nav_name => $navigation) { + if ($nav_name && is_a($navigation, 'Navigation')) { + $cnav['children'][$path . '/' . $nav_name] = [ + 'icon' => $navigation->getImage() ? $navigation->getImage()->asImagePath() : '', + 'title' => $tool->getDisplayname(), + 'url' => URLHelper::getURL($navigation->getURL(), ['cid' => $course->id]), + 'parent' => 'browse/my_courses/' . $course->id, + 'path' => 'browse/my_courses/' . $course->id . '/' . $nav_name, + 'visible' => true, + 'active' => $navigation->isActive(), + 'children' => static::getChildren( + $navigation, + 'browse/my_courses/' . $course->id . '/' . $nav_name, + $activated, + $course->id + ), + ]; + } + } + } + } + } + + $items['browse/my_courses/' . $course->id] = $cnav; + + } + + return $items; + } } diff --git a/lib/classes/SkipLinks.php b/lib/classes/SkipLinks.php index 684ae42..796206d 100644 --- a/lib/classes/SkipLinks.php +++ b/lib/classes/SkipLinks.php @@ -60,27 +60,29 @@ class SkipLinks * @param string $url the url of the links * @param integer $position the position of the link in the list */ - public static function addLink(string $name, string $url, $position = null) + public static function addLink(string $name, string $url, $position = null, bool $inFullscreen = true) { $position = (!$position || $position < 1) ? count(self::$links) + 100 : (int) $position; self::$links[$url] = [ - 'name' => $name, - 'url' => $url, - 'position' => $position, + 'name' => $name, + 'url' => $url, + 'position' => $position, + 'fullscreen' => $inFullscreen ]; } /** * Adds a link to an anker on the same page to the list of skip links. * - * @param string $name the displayed name of the links - * @param string $id the id of the anker - * @param integer $position the position of the link in the list + * @param string $name the displayed name of the links + * @param string $id the id of the anker + * @param integer $position the position of the link in the list + * @param bool $inFullscreen is this link relevant in fullscreen mode? */ - public static function addIndex($name, $id, $position = null) + public static function addIndex($name, $id, $position = null, bool $inFullscreen = true) { $url = '#' . $id; - self::addLink($name, $url, $position); + self::addLink($name, $url, $position, $inFullscreen); } /** @@ -99,12 +101,14 @@ class SkipLinks }); $navigation = new Navigation(''); + $fullscreen = []; foreach (array_values(self::$links) as $index => $link) { $navigation->addSubNavigation( "/skiplinks/link-{$index}", new Navigation($link['name'], $link['url']) ); + $fullscreen['/skiplinks/link-' . $index] = $link['fullscreen']; } - return $GLOBALS['template_factory']->render('skiplinks', compact('navigation')); + return $GLOBALS['template_factory']->render('skiplinks', compact('navigation', 'fullscreen')); } } diff --git a/lib/classes/WidgetContainer.php b/lib/classes/WidgetContainer.php index 108477a..c702d06 100644 --- a/lib/classes/WidgetContainer.php +++ b/lib/classes/WidgetContainer.php @@ -160,6 +160,24 @@ abstract class WidgetContainer } /** + * Returns the number of widgets in this container. Optionally constrained + * to widgets of a specific class. + * + * @param string|null $widget_class + * @return int + */ + public function countWidgets(string $widget_class = null): int + { + $widgets = $this->widgets; + if ($widget_class !== null) { + $widgets = array_filter($widgets, function (Widget $widget) use ($widget_class) { + return is_a($widget, $widget_class); + }); + } + return count($widgets); + } + + /** * Returns whether this container has any widget. * * @return bool True if the container has at least one widget, false @@ -167,7 +185,7 @@ abstract class WidgetContainer */ public function hasWidgets() { - return count($this->widgets) > 0; + return $this->countWidgets() > 0; } /** diff --git a/lib/classes/sidebar/Sidebar.php b/lib/classes/sidebar/Sidebar.php index 7536a7f..00c3b8f 100644 --- a/lib/classes/sidebar/Sidebar.php +++ b/lib/classes/sidebar/Sidebar.php @@ -224,7 +224,8 @@ class Sidebar extends WidgetContainer SkipLinks::addIndex( _('Dritte Navigationsebene'), $widget->getId(), - 20 + 20, + false ); $navigation_widget_added = true; @@ -237,7 +238,8 @@ class Sidebar extends WidgetContainer SkipLinks::addIndex( _('Aktionen'), $widget->getId(), - 21 + 21, + false ); $actions_widget_added = true; diff --git a/lib/include/html_head.inc.php b/lib/include/html_head.inc.php index 4ab1c0e..a7f2c21 100644 --- a/lib/include/html_head.inc.php +++ b/lib/include/html_head.inc.php @@ -32,12 +32,6 @@ $lang_attr = str_replace('_', '-', $_SESSION['_language']); String.locale = ""; document.querySelector('html').className = 'js'; - setTimeout(() => { - // This needs to be put in a timeout since otherwise it will not match - if (window.matchMedia('(max-width: 767px)').matches) { - document.querySelector('html').classList.add('responsive-display'); - } - }, 0); window.STUDIP = { ABSOLUTE_URI_STUDIP: "", diff --git a/lib/modules/ConsultationModule.class.php b/lib/modules/ConsultationModule.class.php index acc2cb4..5671776 100644 --- a/lib/modules/ConsultationModule.class.php +++ b/lib/modules/ConsultationModule.class.php @@ -103,11 +103,13 @@ class ConsultationModule extends CorePlugin implements StudipModule, SystemPlugi */ public function getTabNavigation($course_id) { - if ($GLOBALS['user']->id === 'nobody') { - return []; + if ($GLOBALS['user']->id !== 'nobody') { + $navigation = new ConsultationNavigation(RangeFactory::find($course_id)); + $navigation->setImage(Icon::create('consultation', Icon::ROLE_INFO_ALT)); + return ['consultation' => $navigation]; } - return ['consultation' => new ConsultationNavigation(RangeFactory::find($course_id))]; + return []; } /** diff --git a/lib/modules/CoursewareModule.class.php b/lib/modules/CoursewareModule.class.php index 0d8dfe8..e07d5d2 100644 --- a/lib/modules/CoursewareModule.class.php +++ b/lib/modules/CoursewareModule.class.php @@ -39,6 +39,7 @@ class CoursewareModule extends CorePlugin implements SystemPlugin, StudipModule, _('Courseware'), URLHelper::getURL('dispatch.php/course/courseware/?cid='.$courseId) ); + $navigation->setImage(Icon::create('courseware', Icon::ROLE_INFO_ALT)); $navigation->addSubNavigation( 'content', new Navigation(_('Inhalt'), 'dispatch.php/course/courseware/?cid='.$courseId) diff --git a/lib/navigation/FooterNavigation.php b/lib/navigation/FooterNavigation.php index d3f8b83..a24dc11 100644 --- a/lib/navigation/FooterNavigation.php +++ b/lib/navigation/FooterNavigation.php @@ -27,6 +27,9 @@ class FooterNavigation extends Navigation { parent::initSubNavigation(); + // imprint + $this->addSubNavigation('siteinfo', new Navigation(_('Impressum'), 'dispatch.php/siteinfo/show?cancel_login=1')); + // sitemap if (is_object($GLOBALS['user']) && $GLOBALS['user']->id !== 'nobody') { $this->addSubNavigation('sitemap', new Navigation(_('Sitemap'), 'dispatch.php/sitemap/')); @@ -35,9 +38,6 @@ class FooterNavigation extends Navigation //studip $this->addSubNavigation('studip', new Navigation(_('Stud.IP'), 'http://www.studip.de/')); - // imprint - $this->addSubNavigation('siteinfo', new Navigation(_('Impressum'), 'dispatch.php/siteinfo/show?cancel_login=1')); - // Datenschutzerklärung //Check if the privacy url is one of the Stud.IP pages: diff --git a/lib/wiki.inc.php b/lib/wiki.inc.php index 29e50e4..6d37e54 100644 --- a/lib/wiki.inc.php +++ b/lib/wiki.inc.php @@ -1031,8 +1031,14 @@ function wikiEdit($keyword, $wikiData, $user_id, $backpage=NULL, $ancestor=NULL) } // Create content bar. - $contentBar = new ContentBar($toc, - $page_string, Icon::create('wiki'), $actionMenu); + $contentBar = ContentBar::get() + ->setTOC(CoreWiki::getTOC(WikiPage::getStartPage(Context::getId()))) + ->setInfo($page_string) + ->setIcon(Icon::create('wiki')); + + if ($actionMenu) { + $contentBar->setActionMenu($actionMenu); + } $template = $GLOBALS['template_factory']->open('wiki/edit.php'); $template->keyword = $keyword; @@ -1590,8 +1596,14 @@ function showWikiPage($keyword, $version, $special="", $show_comments="icon", $h } // Create content bar. - $contentBar = new ContentBar($toc, - $page_string, Icon::create('wiki'), $actionMenu); + $contentBar = ContentBar::get() + ->setTOC(CoreWiki::getTOC(WikiPage::getStartPage(Context::getId()))) + ->setInfo($page_string) + ->setIcon(Icon::create('wiki')); + + if ($actionMenu) { + $contentBar->setActionMenu($actionMenu); + } if ($hilight) { // Highlighting must only take place outside HTML tags, so diff --git a/public/assets/images/icons/black/focusmode-off.svg b/public/assets/images/icons/black/focusmode-off.svg new file mode 100644 index 0000000..d7fe2e4 --- /dev/null +++ b/public/assets/images/icons/black/focusmode-off.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/blue/focusmode-off.svg b/public/assets/images/icons/blue/focusmode-off.svg new file mode 100644 index 0000000..b7e965a --- /dev/null +++ b/public/assets/images/icons/blue/focusmode-off.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/blue/fullscreen-off.svg b/public/assets/images/icons/blue/fullscreen-off.svg index 9f60e1a..b7e965a 100644 --- a/public/assets/images/icons/blue/fullscreen-off.svg +++ b/public/assets/images/icons/blue/fullscreen-off.svg @@ -1 +1 @@ - + diff --git a/public/assets/images/icons/blue/fullscreen-off2.svg b/public/assets/images/icons/blue/fullscreen-off2.svg new file mode 100644 index 0000000..c10c1d1 --- /dev/null +++ b/public/assets/images/icons/blue/fullscreen-off2.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/blue/fullscreen-off3.svg b/public/assets/images/icons/blue/fullscreen-off3.svg new file mode 100644 index 0000000..6830b2e --- /dev/null +++ b/public/assets/images/icons/blue/fullscreen-off3.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/blue/fullscreen-on.svg b/public/assets/images/icons/blue/fullscreen-on.svg index 0ecc3e6..08c249c 100644 --- a/public/assets/images/icons/blue/fullscreen-on.svg +++ b/public/assets/images/icons/blue/fullscreen-on.svg @@ -1 +1 @@ - + diff --git a/public/assets/images/icons/blue/fullscreen-on2.svg b/public/assets/images/icons/blue/fullscreen-on2.svg new file mode 100644 index 0000000..16ba091 --- /dev/null +++ b/public/assets/images/icons/blue/fullscreen-on2.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/blue/fullscreen-on3.svg b/public/assets/images/icons/blue/fullscreen-on3.svg new file mode 100644 index 0000000..bdaad6d --- /dev/null +++ b/public/assets/images/icons/blue/fullscreen-on3.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/blue/fullscreen-on4.svg b/public/assets/images/icons/blue/fullscreen-on4.svg new file mode 100644 index 0000000..da6502e --- /dev/null +++ b/public/assets/images/icons/blue/fullscreen-on4.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/blue/fullscreen-on5.svg b/public/assets/images/icons/blue/fullscreen-on5.svg new file mode 100644 index 0000000..8566dec --- /dev/null +++ b/public/assets/images/icons/blue/fullscreen-on5.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/blue/maximise.svg b/public/assets/images/icons/blue/maximise.svg new file mode 100644 index 0000000..b096fc0 --- /dev/null +++ b/public/assets/images/icons/blue/maximise.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/blue/sidebar-open.svg b/public/assets/images/icons/blue/sidebar-open.svg new file mode 100644 index 0000000..3b7dff2 --- /dev/null +++ b/public/assets/images/icons/blue/sidebar-open.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/blue/sidebar.svg b/public/assets/images/icons/blue/sidebar.svg new file mode 100644 index 0000000..676661e --- /dev/null +++ b/public/assets/images/icons/blue/sidebar.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/blue/sidebar3.svg b/public/assets/images/icons/blue/sidebar3.svg new file mode 100644 index 0000000..ab4b9b3 --- /dev/null +++ b/public/assets/images/icons/blue/sidebar3.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/blue/zoom-in.svg b/public/assets/images/icons/blue/zoom-in.svg index 36f054e..bf307ed 100644 --- a/public/assets/images/icons/blue/zoom-in.svg +++ b/public/assets/images/icons/blue/zoom-in.svg @@ -1 +1 @@ - + diff --git a/public/assets/images/icons/blue/zoom-in2.svg b/public/assets/images/icons/blue/zoom-in2.svg index 3056bc4..65b590d 100644 --- a/public/assets/images/icons/blue/zoom-in2.svg +++ b/public/assets/images/icons/blue/zoom-in2.svg @@ -1 +1 @@ - + diff --git a/public/assets/images/icons/blue/zoom-out.svg b/public/assets/images/icons/blue/zoom-out.svg index ef38c35..3a0a413 100644 --- a/public/assets/images/icons/blue/zoom-out.svg +++ b/public/assets/images/icons/blue/zoom-out.svg @@ -1 +1 @@ - + diff --git a/public/assets/images/icons/blue/zoom-out2.svg b/public/assets/images/icons/blue/zoom-out2.svg index 67e11b3..d660c60 100644 --- a/public/assets/images/icons/blue/zoom-out2.svg +++ b/public/assets/images/icons/blue/zoom-out2.svg @@ -1 +1 @@ - + diff --git a/public/assets/images/icons/green/focusmode-off.svg b/public/assets/images/icons/green/focusmode-off.svg new file mode 100644 index 0000000..b5aa406 --- /dev/null +++ b/public/assets/images/icons/green/focusmode-off.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/grey/focusmode-off.svg b/public/assets/images/icons/grey/focusmode-off.svg new file mode 100644 index 0000000..6509d79 --- /dev/null +++ b/public/assets/images/icons/grey/focusmode-off.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/red/focusmode-off.svg b/public/assets/images/icons/red/focusmode-off.svg new file mode 100644 index 0000000..9767595 --- /dev/null +++ b/public/assets/images/icons/red/focusmode-off.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/white/focusmode-off.svg b/public/assets/images/icons/white/focusmode-off.svg new file mode 100644 index 0000000..f852c7f --- /dev/null +++ b/public/assets/images/icons/white/focusmode-off.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/white/fullscreen-off.svg b/public/assets/images/icons/white/fullscreen-off.svg index 2709d17..f852c7f 100644 --- a/public/assets/images/icons/white/fullscreen-off.svg +++ b/public/assets/images/icons/white/fullscreen-off.svg @@ -1 +1 @@ - + diff --git a/public/assets/images/icons/white/fullscreen-off2.svg b/public/assets/images/icons/white/fullscreen-off2.svg new file mode 100644 index 0000000..5c7b0c6 --- /dev/null +++ b/public/assets/images/icons/white/fullscreen-off2.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/white/fullscreen-off3.svg b/public/assets/images/icons/white/fullscreen-off3.svg new file mode 100644 index 0000000..d51bf9d --- /dev/null +++ b/public/assets/images/icons/white/fullscreen-off3.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/white/fullscreen-on.svg b/public/assets/images/icons/white/fullscreen-on.svg index a59f192..6c10665 100644 --- a/public/assets/images/icons/white/fullscreen-on.svg +++ b/public/assets/images/icons/white/fullscreen-on.svg @@ -1 +1 @@ - + diff --git a/public/assets/images/icons/white/fullscreen-on2.svg b/public/assets/images/icons/white/fullscreen-on2.svg new file mode 100644 index 0000000..bc25ed8 --- /dev/null +++ b/public/assets/images/icons/white/fullscreen-on2.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/white/fullscreen-on3.svg b/public/assets/images/icons/white/fullscreen-on3.svg new file mode 100644 index 0000000..0492439 --- /dev/null +++ b/public/assets/images/icons/white/fullscreen-on3.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/white/fullscreen-on4.svg b/public/assets/images/icons/white/fullscreen-on4.svg new file mode 100644 index 0000000..0e406ef --- /dev/null +++ b/public/assets/images/icons/white/fullscreen-on4.svg @@ -0,0 +1 @@ + diff --git a/public/assets/images/icons/yellow/focusmode-off.svg b/public/assets/images/icons/yellow/focusmode-off.svg new file mode 100644 index 0000000..a98b0e0 --- /dev/null +++ b/public/assets/images/icons/yellow/focusmode-off.svg @@ -0,0 +1 @@ + diff --git a/resources/assets/javascripts/bootstrap/responsive-navigation.js b/resources/assets/javascripts/bootstrap/responsive-navigation.js new file mode 100644 index 0000000..aa81107 --- /dev/null +++ b/resources/assets/javascripts/bootstrap/responsive-navigation.js @@ -0,0 +1,10 @@ +import ResponsiveNavigation from '../../../vue/components/responsive/ResponsiveNavigation.vue'; + +STUDIP.ready(() => { + STUDIP.Vue.load().then(({ createApp }) => { + createApp({ + el: '#responsive-menu', + components: { ResponsiveNavigation } + }); + }); +}); diff --git a/resources/assets/javascripts/bootstrap/responsive.js b/resources/assets/javascripts/bootstrap/responsive.js index e7c1aed..8e216d0 100644 --- a/resources/assets/javascripts/bootstrap/responsive.js +++ b/resources/assets/javascripts/bootstrap/responsive.js @@ -9,6 +9,11 @@ STUDIP.domReady(() => { } STUDIP.Responsive.engage(); + + if (STUDIP.Responsive.isFullscreen()) { + document.querySelector('html').classList.add('fullscreen-mode'); + } + }, true); // Trigger search in responsive display diff --git a/resources/assets/javascripts/entry-base.js b/resources/assets/javascripts/entry-base.js index 09779dd..b577ce4 100644 --- a/resources/assets/javascripts/entry-base.js +++ b/resources/assets/javascripts/entry-base.js @@ -87,6 +87,7 @@ import "./bootstrap/cache-admin.js" import "./bootstrap/oer.js" import "./bootstrap/courseware.js" import "./bootstrap/beforeunload-event-listener.js" +import "./bootstrap/responsive-navigation.js" import "./mvv_course_wizard.js" import "./mvv.js" diff --git a/resources/assets/javascripts/lib/header_magic.js b/resources/assets/javascripts/lib/header_magic.js index 410b754..f465e7e 100644 --- a/resources/assets/javascripts/lib/header_magic.js +++ b/resources/assets/javascripts/lib/header_magic.js @@ -10,27 +10,6 @@ const scroll = function(scrolltop) { if (is_below_the_fold !== was_below_the_fold) { $('body').toggleClass('fixed', is_below_the_fold); - menu = $('#navigation-level-1-items').remove(); - if (is_below_the_fold) { - menu.append( - $('.action-menu-list li', menu) - .remove() - .addClass('from-action-menu') - ); - menu.appendTo('#responsive-menu'); - } else { - $('.action-menu-list', menu).append( - $('.from-action-menu', menu) - .remove() - .removeClass('from-action-menu') - ); - menu.prependTo('#navigation-level-1'); - - NavigationShrinker(); - - $('#navigation-level-1-items-toggle').prop('checked', false); - } - was_below_the_fold = is_below_the_fold; } }; diff --git a/resources/assets/javascripts/lib/responsive.js b/resources/assets/javascripts/lib/responsive.js index 16e6354..a493e8d 100644 --- a/resources/assets/javascripts/lib/responsive.js +++ b/resources/assets/javascripts/lib/responsive.js @@ -4,127 +4,6 @@ import Sidebar from './sidebar.js'; const Responsive = { media_query: window.matchMedia('(max-width: 767px)'), - // Builds a dom element from a navigation object - buildMenu (navigation, id, activated) { - var list = $('