Toggle visibility by class / user group

This commit is contained in:
Ramon Wenger 2018-09-13 15:27:22 +02:00
parent 2db6464f8d
commit 7038721bfd
10 changed files with 188 additions and 52 deletions

View File

@ -1,6 +1,9 @@
<template>
<label class="checkbox-container">
<input type="checkbox" class="checkbox-container__input" v-model="checked">
<input type="checkbox"
class="checkbox-container__input"
:checked="checked"
v-on:input="$emit('input', $event.target.checked, item)">
<span class="checkbox-container__checkbox">
<tick></tick>
</span>
@ -16,9 +19,9 @@
props: {
label: String,
checked: {
type: Boolean,
default: false
}
type: Boolean
},
item: Object
},
components: {
@ -37,7 +40,7 @@
margin-right: 10px;
svg {
width: 12px;
width: 15px;
}
&__input {
@ -50,7 +53,7 @@
svg {
display: block;
fill: white;
fill: $color-white;
}
}

View File

@ -2,7 +2,10 @@
<div class="content-block__container">
<div class="content-block" :class="specialClass">
<div class="content-block__visibility-button">
<eye-icon class="content-block__visibility-icon"></eye-icon>
<a @click="toggleVisibility()">
<eye-icon class="content-block__visibility-icon"></eye-icon>
</a>
<visibility-popover :show="showVisibility" :content-block="contentBlock"></visibility-popover>
</div>
<h4 class="content-block__title">{{contentBlock.title}}</h4>
@ -31,6 +34,7 @@
import DocumentBlock from '@/components/content-blocks/DocumentBlock';
import StudentEntry from '@/components/content-blocks/StudentEntry';
import AddContentBlockButton from '@/components/AddContentBlockButton';
import VisibilityPopover from '@/components/VisibilityPopover';
import EyeIcon from '@/components/icons/EyeIcon';
export default {
@ -46,6 +50,7 @@
'document_block': DocumentBlock,
Task,
AddContentBlockButton,
VisibilityPopover,
EyeIcon
},
@ -53,6 +58,18 @@
specialClass() {
return `content-block--${this.contentBlock.type.toLowerCase()}`
}
},
methods: {
toggleVisibility() {
this.showVisibility = !this.showVisibility;
}
},
data() {
return {
showVisibility: false
}
}
}
</script>
@ -80,6 +97,9 @@
fill: $color-grey;
}
&__visibility-menu {
}
&--yellow {
background-color: rgba($color-accent-1, 0.15);
border: 1px solid $color-accent-1;

View File

@ -7,7 +7,7 @@
</template>
<script>
import USER_GROUPS_QUERY from '@/graphql/gql/userGroupsQuery.gql';
import {userGroupsQuery} from '@/helpers/user-groups'
import Checkbox from '@/components/Checkbox.vue';
@ -17,16 +17,7 @@
},
apollo: {
userGroupsQuery: {
query: USER_GROUPS_QUERY,
manual: true,
result({data, loading, networkStatus}) {
if (!loading) {
const cleanedData = this.$getRidOfEdges(data)
this.userGroups = cleanedData.userGroups || {};
}
}
}
userGroupsQuery: userGroupsQuery
},
data() {

View File

@ -0,0 +1,103 @@
<template>
<div class="visibility-menu" v-if="show">
<h3 class="visibility-menu__title">Sichtbarkeit</h3>
<div v-for="group in userGroupsWithVisibilityInfo" :key="group.id" class="visibility-menu__item">
<checkbox :checked="!group.hidden"
:item="group"
:label="group.name"
v-on:input="updateVisibility"
></checkbox>
</div>
</div>
</template>
<script>
import CHANGE_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/mutateContentBlock.gql';
import Checkbox from '@/components/Checkbox';
import {userGroupsQuery} from '@/helpers/user-groups'
export default {
props: ['show', 'content-block'],
components: {
Checkbox
},
apollo: {
userGroupsQuery: userGroupsQuery
},
data() {
return {
userGroups: []
}
},
methods: {
updateVisibility(checked, item) {
item.hidden = !checked;
this.$apollo.mutate({
mutation: CHANGE_CONTENT_BLOCK_MUTATION,
variables: {
input: {
id: this.contentBlock.id,
visibility: this.userGroupsWithVisibilityInfo.map(g => {
return {
userGroupId: g.id,
hidden: g.hidden || false
}
})
}
},
update: (store, {data: {mutateContentBlock: {contentBlock}}}) => {
this.$store.dispatch('updateContentBlocks');
}
});
}
},
computed: {
userGroupsWithVisibilityInfo() {
return this.userGroups.map(userGroup => {
return {
...userGroup,
hidden: !!this.contentBlock.hiddenFor.find(el => el.id === userGroup.id)
}
});
}
}
}
</script>
<style scoped lang="scss">
@import "@/styles/_variables.scss";
@import "@/styles/_functions.scss";
.visibility-menu {
border-radius: 13px;
border: 1px solid $color-lightgrey;
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.15);
width: 180px;
box-sizing: border-box;
padding: 19px;
left: -130px;
position: absolute;
z-index: 9;
background-color: $color-white;
&__title {
font-size: toRem(19px);
margin-bottom: 10px;
}
&__item {
margin-bottom: 18px;
&:last-of-type {
margin-bottom: 0;
}
}
}
</style>

View File

@ -0,0 +1,40 @@
mutation MutateContentBlock($input: MutateContentBlockInput!) {
mutateContentBlock(input: $input) {
contentBlock {
id
title
slug
hiddenFor {
edges {
node {
id
name
}
}
}
}
errors
}
}
#// input
#
#{
# "input": {
# "id": "Q29udGVudEJsb2NrTm9kZToyMQ==",
# "type": "plain",
# "title": "Hallo Daniel"
# }
#}
#
#
#{
# "input": {
# "id": "Q29udGVudEJsb2NrTm9kZToyMQ==",
# "type": "plain",
# "title": "Hallo Daniel",
# "contents": "[{\"type\":\"text_block\",\"value\":{\"text\": \"<p>Beatae odio</p>\"}}]"
# }
#}

View File

@ -1,32 +0,0 @@
mutation MutateContentBlock($input: MutateContentBlockInput!) {
mutateContentBlock(input: $input) {
contentBlock {
id
title
slug
}
errors
}
}
// input
{
"input": {
"id": "Q29udGVudEJsb2NrTm9kZToyMQ==",
"type": "plain",
"title": "Hallo Daniel"
}
}
{
"input": {
"id": "Q29udGVudEJsb2NrTm9kZToyMQ==",
"type": "plain",
"title": "Hallo Daniel",
"contents": "[{\"type\":\"text_block\",\"value\":{\"text\": \"<p>Beatae odio</p>\"}}]"
}
}

View File

@ -0,0 +1,12 @@
import USER_GROUPS_QUERY from '@/graphql/gql/userGroupsQuery.gql';
export const userGroupsQuery = {
query: USER_GROUPS_QUERY,
manual: true,
result({data, loading, networkStatus}) {
if (!loading) {
const cleanedData = this.$getRidOfEdges(data)
this.userGroups = cleanedData.userGroups || {};
}
}
};

View File

@ -10,7 +10,6 @@ export default new Vuex.Store({
specialContainerClass: '',
showFilter: true,
showModal: false,
showNewContentBlockModal: false,
contentBlockPosition: {},
scrollPosition: 0,
moduleSlug: 'mein-neues-umfeld',

View File

@ -120,7 +120,6 @@ class MutateContentBlock(relay.ClientIDMutation):
class AddContentBlock(relay.ClientIDMutation):
class Input:
content_block = graphene.Argument(ContentBlockInput)
# todo: handle both of these differently, one for a new chapter maybe
parent = graphene.ID() # ID of chapter node; new content block will be inserted at the start of it
after = graphene.ID() # ID of content block node; new content block will be inserted after this content block node

View File

@ -51,6 +51,7 @@ class BookQuery(object):
topic = relay.Node.Field(TopicNode)
module = relay.Node.Field(ModuleNode)
chapter = relay.Node.Field(FilteredChapterNode)
content_block = relay.Node.Field(ContentBlockNode)
books = DjangoFilterConnectionField(BookNode)
topics = DjangoFilterConnectionField(TopicNode)