Save last topic and go there on topic navigation
This commit is contained in:
parent
a9b3dddd8b
commit
c6bdae3fd3
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="content-navigation__item">
|
<div class="content-navigation__item">
|
||||||
<router-link
|
<router-link
|
||||||
:class="{'content-navigation__link--active': isActive('book')}"
|
:class="{'content-navigation__link--active': isActive('book')}"
|
||||||
to="/book/topic/berufliche-grundbildung"
|
:to="topicRoute"
|
||||||
active-class="content-navigation__link--active"
|
active-class="content-navigation__link--active"
|
||||||
class="content-navigation__link"
|
class="content-navigation__link"
|
||||||
@click.native="close">Themen
|
@click.native="close">Themen
|
||||||
|
|
@ -73,6 +73,7 @@
|
||||||
import BookTopicNavigation from '@/components/book-navigation/BookTopicNavigation';
|
import BookTopicNavigation from '@/components/book-navigation/BookTopicNavigation';
|
||||||
|
|
||||||
import sidebarMixin from '@/mixins/sidebar';
|
import sidebarMixin from '@/mixins/sidebar';
|
||||||
|
import meMixin from '@/mixins/me';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -81,13 +82,27 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mixins: [sidebarMixin],
|
mixins: [sidebarMixin, meMixin],
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
BookTopicNavigation,
|
BookTopicNavigation,
|
||||||
Logo
|
Logo
|
||||||
},
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
topicRoute() {
|
||||||
|
if (this.me.lastTopic && this.me.lastTopic.slug) {
|
||||||
|
return {
|
||||||
|
name: 'topic',
|
||||||
|
params: {
|
||||||
|
topicSlug: this.me.lastTopic.slug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '/book/topic/berufliche-grundbildung'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
isActive(linkName) {
|
isActive(linkName) {
|
||||||
return linkName === 'book' && this.$route.path.indexOf('module') > -1;
|
return linkName === 'book' && this.$route.path.indexOf('module') > -1;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
#import "./moduleParts.gql"
|
||||||
|
fragment TopicParts on TopicNode {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
teaser
|
||||||
|
slug
|
||||||
|
description
|
||||||
|
vimeoId
|
||||||
|
instructions
|
||||||
|
modules {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
...ModuleParts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,10 @@ fragment UserParts on UserNode {
|
||||||
id
|
id
|
||||||
slug
|
slug
|
||||||
}
|
}
|
||||||
|
lastTopic {
|
||||||
|
id
|
||||||
|
slug
|
||||||
|
}
|
||||||
selectedClass {
|
selectedClass {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
#import "../fragments/topicParts.gql"
|
||||||
|
mutation UpdateLastTopic($input: UpdateLastTopicInput!) {
|
||||||
|
updateLastTopic(input: $input) {
|
||||||
|
topic {
|
||||||
|
...TopicParts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,18 +1,6 @@
|
||||||
#import "./fragments/moduleParts.gql"
|
#import "./fragments/topicParts.gql"
|
||||||
query Topic($slug: String!){
|
query Topic($slug: String!){
|
||||||
topic(slug: $slug) {
|
topic(slug: $slug) {
|
||||||
id
|
...TopicParts
|
||||||
title
|
|
||||||
teaser
|
|
||||||
description
|
|
||||||
vimeoId
|
|
||||||
instructions
|
|
||||||
modules {
|
|
||||||
edges {
|
|
||||||
node {
|
|
||||||
...ModuleParts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,10 +63,13 @@
|
||||||
import PortfolioIllustration from '@/components/illustrations/PortfolioIllustration';
|
import PortfolioIllustration from '@/components/illustrations/PortfolioIllustration';
|
||||||
import RoomsIllustration from '@/components/illustrations/RoomsIllustration';
|
import RoomsIllustration from '@/components/illustrations/RoomsIllustration';
|
||||||
|
|
||||||
import {meQuery} from '@/graphql/queries';
|
|
||||||
import MobileHeader from '@/components/MobileHeader';
|
import MobileHeader from '@/components/MobileHeader';
|
||||||
|
|
||||||
|
import meMixin from '@/mixins/me';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
||||||
|
mixins: [meMixin],
|
||||||
components: {
|
components: {
|
||||||
MobileHeader,
|
MobileHeader,
|
||||||
HeaderBar,
|
HeaderBar,
|
||||||
|
|
@ -77,12 +80,6 @@
|
||||||
RoomsIllustration
|
RoomsIllustration
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
me: {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
moduleRoute() {
|
moduleRoute() {
|
||||||
if (this.me.lastModule && this.me.lastModule.slug) {
|
if (this.me.lastModule && this.me.lastModule.slug) {
|
||||||
|
|
@ -98,9 +95,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
apollo: {
|
|
||||||
me: meQuery
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,9 @@
|
||||||
import me from '@/mixins/me';
|
import me from '@/mixins/me';
|
||||||
import BookTopicNavigation from '@/components/book-navigation/BookTopicNavigation';
|
import BookTopicNavigation from '@/components/book-navigation/BookTopicNavigation';
|
||||||
|
|
||||||
|
import UPDATE_LAST_TOPIC_MUTATION from '@/graphql/gql/mutations/updateLastTopic.gql';
|
||||||
|
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
||||||
mixins: [me],
|
mixins: [me],
|
||||||
|
|
@ -64,6 +67,12 @@
|
||||||
},
|
},
|
||||||
update(data) {
|
update(data) {
|
||||||
return this.$getRidOfEdges(data).topic || {};
|
return this.$getRidOfEdges(data).topic || {};
|
||||||
|
},
|
||||||
|
result(r, key) {
|
||||||
|
if (this.saveMe) {
|
||||||
|
this.saveMe = false;
|
||||||
|
this.updateLastVisitedTopic(this.topic.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -75,7 +84,8 @@
|
||||||
modules: {
|
modules: {
|
||||||
edges: []
|
edges: []
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
saveMe: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -85,9 +95,37 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
if (!this.topic.id) { // component was loaded before topic, apollo not ready yet
|
||||||
|
this.saveMe = true; // needs saving, apollo will do this
|
||||||
|
} else {
|
||||||
|
this.updateLastVisitedTopic(this.topic.id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
openVideo() {
|
openVideo() {
|
||||||
this.$store.dispatch('showFullscreenVideo', this.topic.vimeoId);
|
this.$store.dispatch('showFullscreenVideo', this.topic.vimeoId);
|
||||||
|
},
|
||||||
|
updateLastVisitedTopic(topicId) {
|
||||||
|
this.$apollo.mutate({
|
||||||
|
mutation: UPDATE_LAST_TOPIC_MUTATION,
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
id: topicId
|
||||||
|
}
|
||||||
|
},
|
||||||
|
update(store, {data: {updateLastTopic: {topic}}}) {
|
||||||
|
if (topic) {
|
||||||
|
let query = ME_QUERY;
|
||||||
|
const data = store.readQuery({query});
|
||||||
|
if (data) {
|
||||||
|
data.me.lastTopic = topic;
|
||||||
|
store.writeQuery({query, data})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from books.schema.mutations.contentblock import MutateContentBlock, AddContentBlock, DeleteContentBlock
|
from books.schema.mutations.contentblock import MutateContentBlock, AddContentBlock, DeleteContentBlock
|
||||||
from books.schema.mutations.module import UpdateSolutionVisibility, UpdateLastModule
|
from books.schema.mutations.module import UpdateSolutionVisibility, UpdateLastModule, UpdateLastTopic
|
||||||
|
|
||||||
|
|
||||||
class BookMutations(object):
|
class BookMutations(object):
|
||||||
|
|
@ -8,3 +8,4 @@ class BookMutations(object):
|
||||||
delete_content_block = DeleteContentBlock.Field()
|
delete_content_block = DeleteContentBlock.Field()
|
||||||
update_solution_visibility = UpdateSolutionVisibility.Field()
|
update_solution_visibility = UpdateSolutionVisibility.Field()
|
||||||
update_last_module = UpdateLastModule.Field()
|
update_last_module = UpdateLastModule.Field()
|
||||||
|
update_last_topic = UpdateLastTopic.Field()
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ import graphene
|
||||||
from graphene import relay
|
from graphene import relay
|
||||||
|
|
||||||
from api.utils import get_errors, get_object
|
from api.utils import get_errors, get_object
|
||||||
from books.models import Module
|
from books.models import Module, Topic
|
||||||
from books.schema.queries import ModuleNode
|
from books.schema.queries import ModuleNode, TopicNode
|
||||||
|
|
||||||
|
|
||||||
class UpdateSolutionVisibility(relay.ClientIDMutation):
|
class UpdateSolutionVisibility(relay.ClientIDMutation):
|
||||||
|
|
@ -71,3 +71,26 @@ class UpdateLastModule(relay.ClientIDMutation):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
errors = ['Error: {}'.format(e)]
|
errors = ['Error: {}'.format(e)]
|
||||||
return cls(errors=errors)
|
return cls(errors=errors)
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateLastTopic(relay.ClientIDMutation):
|
||||||
|
class Input:
|
||||||
|
# todo: use slug here too
|
||||||
|
id = graphene.ID()
|
||||||
|
|
||||||
|
topic = graphene.Field(TopicNode)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def mutate_and_get_payload(cls, root, info, **args):
|
||||||
|
user = info.context.user
|
||||||
|
id = args.get('id')
|
||||||
|
|
||||||
|
topic = get_object(Topic, id)
|
||||||
|
if not topic:
|
||||||
|
raise Topic.DoesNotExist
|
||||||
|
|
||||||
|
user.last_topic = topic
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
return cls(topic=topic)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Generated by Django 2.1.15 on 2020-06-15 14:24
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('books', '0021_auto_20200525_1447'),
|
||||||
|
('users', '0017_auto_20200430_1251'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='user',
|
||||||
|
name='last_topic',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='books.Topic'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -17,6 +17,7 @@ DEFAULT_SCHOOL_ID = 1
|
||||||
|
|
||||||
class User(AbstractUser):
|
class User(AbstractUser):
|
||||||
last_module = models.ForeignKey('books.Module', related_name='+', on_delete=models.SET_NULL, null=True)
|
last_module = models.ForeignKey('books.Module', related_name='+', on_delete=models.SET_NULL, null=True)
|
||||||
|
last_topic = models.ForeignKey('books.Topic', related_name='+', on_delete=models.SET_NULL, null=True)
|
||||||
avatar_url = models.CharField(max_length=254, blank=True, default='')
|
avatar_url = models.CharField(max_length=254, blank=True, default='')
|
||||||
email = models.EmailField(_('email address'), unique=True)
|
email = models.EmailField(_('email address'), unique=True)
|
||||||
hep_id = models.PositiveIntegerField(null=True, blank=False)
|
hep_id = models.PositiveIntegerField(null=True, blank=False)
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,8 @@ class UserNode(DjangoObjectType):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
filter_fields = ['username', 'email']
|
filter_fields = ['username', 'email']
|
||||||
only_fields = ['username', 'email', 'first_name', 'last_name', 'school_classes', 'last_module', 'avatar_url',
|
only_fields = ['username', 'email', 'first_name', 'last_name', 'school_classes', 'last_module',
|
||||||
|
'last_topic', 'avatar_url',
|
||||||
'selected_class', 'expiry_date']
|
'selected_class', 'expiry_date']
|
||||||
interfaces = (relay.Node,)
|
interfaces = (relay.Node,)
|
||||||
|
|
||||||
|
|
@ -64,7 +65,7 @@ class UserNode(DjangoObjectType):
|
||||||
return self.selected_class()
|
return self.selected_class()
|
||||||
|
|
||||||
def resolve_expiry_date(self, info):
|
def resolve_expiry_date(self, info):
|
||||||
if not self.hep_id: # concerns users that already have an (old) account
|
if not self.hep_id: # concerns users that already have an (old) account
|
||||||
return format(datetime(2020, 7, 31), 'U') # just set some expiry date
|
return format(datetime(2020, 7, 31), 'U') # just set some expiry date
|
||||||
else:
|
else:
|
||||||
return self.license_expiry_date
|
return self.license_expiry_date
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue