Merged in feature/subnavigation (pull request #23)

Feature/subnavigation

Approved-by: Christian Cueni <christian.cueni@iterativ.ch>
This commit is contained in:
Ramon Wenger 2019-07-17 07:04:47 +00:00 committed by Christian Cueni
commit 4c7dd96455
15 changed files with 257 additions and 213 deletions

View File

@ -1,7 +1,9 @@
<template>
<header class="header-bar">
<top-navigation></top-navigation>
<router-link to="/" class="header-bar__logo" data-cy="home-link"><logo></logo></router-link>
<router-link to="/" class="header-bar__logo" data-cy="home-link">
<logo></logo>
</router-link>
<div class="user-header">
<router-link to="/me/activity">
<user-widget v-bind="me"></user-widget>

View File

@ -1,48 +1,28 @@
<template>
<aside class="book-navigation">
<book-navigation-item title="Themen">
<aside class="sub-navigation">
<sub-navigation-item title="Themen">
<book-topic-navigation></book-topic-navigation>
</book-navigation-item>
<book-navigation-item title="Instrument">
<div>
<router-link to="/basic-knowledge">Sprache und Kommunikation</router-link>
</div>
<div>
<router-link to="/basic-knowledge">Gesellschaft</router-link>
</div>
</book-navigation-item>
<book-navigation-item title="News">
</sub-navigation-item>
<sub-navigation-item title="Instrument">
<router-link tag="div" class="book-subnavigation__item" to="/basic-knowledge">Sprache und Kommunikation</router-link>
<router-link tag="div" class="book-subnavigation__item" to="/basic-knowledge">Gesellschaft</router-link>
</sub-navigation-item>
<sub-navigation-item title="News">
<template slot="title">
<h2 class="book-navigation__title" slot="title">ABU News</h2>
<h2 class="sub-navigation__title" slot="title">ABU News</h2>
</template>
</book-navigation-item>
</sub-navigation-item>
</aside>
</template>
<script>
import BookNavigationItem from '@/components/book-navigation/BookNavigationItem';
import SubNavigationItem from '@/components/book-navigation/SubNavigationItem';
import BookTopicNavigation from '@/components/book-navigation/BookTopicNavigation';
export default {
components: {
BookNavigationItem,
SubNavigationItem,
BookTopicNavigation
}
}
</script>
<style scoped lang="scss">
@import "@/styles/_functions.scss";
@import "@/styles/_variables.scss";
@import "@/styles/_mixins.scss";
.book-navigation {
display: none;
@include desktop {
display: flex;
}
padding: $medium-spacing;
}
</style>

View File

@ -1,92 +0,0 @@
<template>
<div class="book-navigation-item" :class="{ 'book-navigation-item--active': show}">
<div class="book-navigation-item__title" @click="show = !show">
{{title}}
<chevron-down class="book-navigation-item__icon book-navigation-item__chevron-down"></chevron-down>
<chevron-up class="book-navigation-item__icon book-navigation-item__chevron-up"></chevron-up>
</div>
<div class="book-navigation-item__nav-items" v-if="show">
<slot></slot>
</div>
</div>
</template>
<script>
import ChevronDown from '@/components/icons/ChevronDown';
import ChevronUp from '@/components/icons/ChevronUp';
export default {
props: ['title'],
components: {
ChevronDown,
ChevronUp
},
data() {
return {
show: false
}
}
}
</script>
<style scoped lang="scss">
@import "@/styles/_variables.scss";
@import "@/styles/_mixins.scss";
.book-navigation-item {
z-index: 10;
margin-right: $large-spacing;
&__title {
@include small-text;
display: grid;
grid-template-columns: 1fr auto;
grid-column-gap: $small-spacing;
align-items: center;
cursor: pointer;
}
&__icon {
width: 12px;
height: 12px;
}
&__chevron-up {
display: none;
}
&__nav-items {
box-shadow: 0 4px 7px 0 rgba(0, 0, 0, 0.12);
position: absolute;
left: 0;
margin-top: 17px;
background-color: $color-white;
padding: $small-spacing $medium-spacing;
width: 100%;
box-sizing: border-box;
&:empty {
display: none;
}
}
&--active &__title {
color: $color-brand;
}
&--active &__icon {
fill: $color-brand;
}
&--active &__chevron-up {
display: block;
}
&--active &__chevron-down {
display: none;
}
}
</style>

View File

@ -1,24 +1,44 @@
<template>
<nav class="book-topics">
<div class="book-topics__topic"
<router-link :to="{name: 'topic', params: {topicSlug: topic.slug}}"
tag="div"
class="book-topics__topic book-subnavigation__item"
:class="{'book-topics__topic--active': topic.active}"
v-for="topic in topics"
:key="topic.id">{{topic.id}}. {{topic.title}}
</div>
:key="topic.id">
{{topic.order}}.
{{topic.title}}
</router-link>
</nav>
</template>
<script>
import ALL_TOPICS_QUERY from '@/graphql/gql/allTopicsQuery.gql';
export default {
data() {
return {
topics: [
{id: 2, title: 'Geld und Kauf', active: true},
{id: 3, title: 'Geld und Kauf', active: false},
{id: 4, title: 'Geld und Kauf', active: false},
{id: 5, title: 'Geld und Kauf', active: false},
]
}
},
methods: {
topicId(id) {
return atob(id)
}
},
apollo: {
topics: {
query: ALL_TOPICS_QUERY,
manual: true,
result({data, loading, networkStatus}) {
if (!loading) {
this.topics = this.$getRidOfEdges(data).topics
}
}
}
}
}
</script>
@ -27,18 +47,7 @@
@import "@/styles/_variables.scss";
.book-topics {
padding-left: 24px;
margin-bottom: 25px;
&__topic {
font-family: $sans-serif-font-family;
font-size: toRem(14px);
margin-bottom: 20px;
color: $color-silver-dark;
&--active {
color: $color-brand;
}
}
}
</style>

View File

@ -0,0 +1,61 @@
<template>
<div class="sub-navigation-item" :class="{ 'sub-navigation-item--active': show}" v-click-outside="close">
<div class="sub-navigation-item__title" @click="show = !show">
{{title}}
<chevron-down class="sub-navigation-item__icon sub-navigation-item__chevron-down"></chevron-down>
<chevron-up class="sub-navigation-item__icon sub-navigation-item__chevron-up"></chevron-up>
</div>
<div class="sub-navigation-item__nav-items book-subnavigation" v-if="show">
<slot></slot>
</div>
</div>
</template>
<script>
import ChevronDown from '@/components/icons/ChevronDown';
import ChevronUp from '@/components/icons/ChevronUp';
export default {
props: ['title'],
components: {
ChevronDown,
ChevronUp
},
data() {
return {
show: false
}
},
methods: {
close() {
this.show = false;
}
}
}
</script>
<style lang="scss">
@import "@/styles/_variables.scss";
@import "@/styles/_mixins.scss";
.book-subnavigation {
&__item {
font-family: $sans-serif-font-family;
font-size: toRem(14px);
margin-bottom: $medium-spacing;
color: $color-silver-dark;
cursor: pointer;
&:last-of-type {
margin-bottom: 0;
}
&--active {
color: $color-brand;
}
}
}
</style>

View File

@ -1,12 +1,5 @@
<template>
<div class="module">
<toggle-solutions-for-module
:module="module.id"
:enabled="module.solutionsEnabled"
class="module__solution-toggle"
data-cy="toggle-enable-solutions"></toggle-solutions-for-module>
<h2 class="module__meta-title" id="meta-title">{{module.metaTitle}}</h2>
<h1 class="module__title" data-cy="module-title">{{module.title}}</h1>
<img
@ -33,7 +26,6 @@
import ObjectiveGroupControl from '@/components/objective-groups/ObjectiveGroupControl.vue';
import AddObjectiveGroupButton from '@/components/AddObjectiveGroupButton';
import Chapter from '@/components/Chapter.vue';
import ToggleSolutionsForModule from '@/components/ToggleSolutionsForModule.vue';
import UPDATE_OBJECTIVE_PROGRESS_MUTATION from '@/graphql/gql/mutations/updateObjectiveProgress.gql';
import UPDATE_LAST_MODULE_MUTATION from '@/graphql/gql/mutations/updateLastModule.gql';
@ -47,8 +39,7 @@
ObjectiveGroups,
ObjectiveGroupControl,
AddObjectiveGroupButton,
Chapter,
ToggleSolutionsForModule
Chapter
},
props: {
@ -155,10 +146,6 @@
-moz-box-sizing: border-box;
box-sizing: border-box;
&__solution-toggle {
margin-bottom: $large-spacing;
}
&__hero {
margin-bottom: 35px;
border-radius: 12px;

View File

@ -1,49 +1,53 @@
<template>
<div>
<nav v-if="false" class="module-navigation">
<div class="module-navigation__module-content">
<router-link
tag="h3"
:to="moduleContentLink"
class="module-navigation__heading"
>Inhalte: {{module.metaTitle}}
</router-link>
<div class="module-navigation__anchors" v-if="onModulePage">
<a href="#" v-scroll-to="'#meta-title'" class="module-navigation__anchor">Einleitung</a>
<a href="#" v-scroll-to="'#objectives'" class="module-navigation__anchor">Lernziele</a>
<nav class="module-navigation sub-navigation">
<div class="sub-navigation-item">
<router-link class="sub-navigation-item__title" :to="moduleContentLink">Modul</router-link>
</div>
<sub-navigation-item title="Ergebnisse">
<router-link
:to="submissionsLink(assignment)"
v-for="assignment in assignments"
:key="assignment.id"
class="module-navigation__anchor"
exact-active-class="module-navigation__anchor--active"
>{{assignmentTitle(assignment)}}
</router-link>
</sub-navigation-item>
<div class="module-navigation__module-content" v-if="false">
<router-link
tag="h3"
:to="moduleContentLink"
class="module-navigation__heading"
>Inhalte: {{module.metaTitle}}
</router-link>
<div class="module-navigation__anchors" v-if="onModulePage">
<a href="#" v-scroll-to="'#meta-title'" class="module-navigation__anchor">Einleitung</a>
<a href="#" v-scroll-to="'#objectives'" class="module-navigation__anchor">Lernziele</a>
<a href="#" class="module-navigation__anchor"
v-scroll-to="chapterId(index)"
v-for="(chapter, index) in module.chapters"
:key="chapter.id">{{chapter.title}}</a>
<a href="#" v-scroll-to="'#objectives-confirm'" class="module-navigation__anchor">Lernzielkontrolle</a>
</div>
<a href="#" class="module-navigation__anchor"
v-scroll-to="chapterId(index)"
v-for="(chapter, index) in module.chapters"
:key="chapter.id">{{chapter.title}}</a>
<a href="#" v-scroll-to="'#objectives-confirm'" class="module-navigation__anchor">Lernzielkontrolle</a>
</div>
</div>
<div class="module-navigation__module-submissions" v-if="showResults">
<router-link tag="h3" to="/module/submissions" class="module-navigation__heading">Ergebnisse:
{{module.metaTitle}}
</router-link>
<div class="module-navigation__anchors">
<router-link
:to="submissionsLink(assignment)"
v-for="assignment in assignments"
:key="assignment.id"
class="module-navigation__anchor"
exact-active-class="module-navigation__anchor--active"
>{{assignmentTitle(assignment)}}
</router-link>
</div>
</div>
</nav>
</div>
<toggle-solutions-for-module
v-if="onModulePage && module.id"
:module="module.id"
:enabled="module.solutionsEnabled"
class="module-navigation__solution-toggle"
data-cy="toggle-enable-solutions"></toggle-solutions-for-module>
</nav>
</template>
<script>
import {moduleQuery} from '@/graphql/queries';
import ME_QUERY from '@/graphql/gql/meQuery.gql';
// import ASSIGNMENTS_QUERY from '@/graphql/gql/assignmentsQuery.gql';
import SubNavigationItem from '@/components/book-navigation/SubNavigationItem';
import ToggleSolutionsForModule from '@/components/ToggleSolutionsForModule';
export default {
apollo: {
@ -53,6 +57,11 @@
}
},
components: {
SubNavigationItem,
ToggleSolutionsForModule
},
computed: {
onModulePage() {
return this.$route.name === 'module';
@ -110,9 +119,11 @@
position: sticky;
top: 75px;
display: none;
width: 100%;
box-sizing: border-box;
@include desktop {
display: block;
display: flex;
}
&__module-content {
@ -140,5 +151,9 @@
color: $color-brand;
}
}
&__solution-toggle {
margin-left: auto;
}
}
</style>

View File

@ -0,0 +1,12 @@
query TopicsQuery {
topics {
edges {
node {
id
order
title
slug
}
}
}
}

View File

@ -1,7 +1,7 @@
<template>
<div class="book">
<main class="book__content">
<router-view></router-view>
<router-view :key="$route.fullPath"></router-view>
</main>
</div>

View File

@ -74,7 +74,7 @@ const routes = [
subnavigation: true
},
children: [
{path: 'topic/:topicSlug', component: topic, meta: {subnavigation: true}}
{path: 'topic/:topicSlug', name: 'topic', component: topic, meta: {subnavigation: true}}
]
},
{

View File

@ -0,0 +1,79 @@
.top-navigation {
display: flex;
&__link {
font-size: 1.0625rem;
padding: 0 24px;
font-family: $sans-serif-font-family;
font-weight: $font-weight-regular;
color: $color-silver-dark;
&--active {
color: $color-brand;
}
}
}
.sub-navigation {
display: none;
@include desktop {
display: flex;
}
padding: $medium-spacing;
}
.sub-navigation-item {
z-index: 10;
margin-right: $large-spacing;
&__title {
@include small-text;
display: grid;
grid-template-columns: 1fr auto;
grid-column-gap: $small-spacing;
align-items: center;
cursor: pointer;
}
&__icon {
width: 12px;
height: 12px;
}
&__chevron-up {
display: none;
}
&__nav-items {
box-shadow: 0 4px 7px 0 rgba(0, 0, 0, 0.12);
position: absolute;
left: 0;
background-color: $color-white;
padding: $large-spacing;
width: 100%;
box-sizing: border-box;
&:empty {
display: none;
}
}
&--active &__title {
color: $color-brand;
}
&--active &__icon {
fill: $color-brand;
}
&--active &__chevron-up {
display: block;
}
&--active &__chevron-down {
display: none;
}
}

View File

@ -1,15 +0,0 @@
.top-navigation {
display: flex;
&__link {
font-size: 1.0625rem;
padding: 0 24px;
font-family: $sans-serif-font-family;
font-weight: $font-weight-regular;
color: $color-silver-dark;
&--active {
color: $color-brand;
}
}
}

View File

@ -13,5 +13,5 @@
@import "objective-group";
@import "article";
@import "actions";
@import "top-navigation";
@import "navigation";
@import "survey";

View File

@ -123,7 +123,7 @@ class TopicNode(DjangoObjectType):
class Meta:
model = Topic
only_fields = [
'slug', 'title', 'meta_title', 'teaser', 'description', 'vimeo_id'
'slug', 'title', 'meta_title', 'teaser', 'description', 'vimeo_id', 'order'
]
filter_fields = {
'slug': ['exact', 'icontains', 'in'],

View File

@ -677,6 +677,12 @@ data = [
'title': 'Geld und Kauf',
'teaser': 'Die berufliche Grundbildung lehrt Sie, den Arbeitsalltag erfolgreich zu bewältigen, Ihre Fähigkeiten zu entwickeln und beruflich flexibel zu sein. Ebenso wichtig ist der Umgang mit verschiedensten Mitmenschen. Eine angemessene mündliche Kommunikation erleichtert das Zusammenleben und Zusammenarbeiten.',
'modules': modules
},
{
'order': 2,
'title': 'Berufliche Grundbildung',
'teaser': 'Yada yada bla bla',
'modules': ''
}
]
}]