Refactor chapter component
This commit is contained in:
parent
a629f6a5e6
commit
04d06b3332
|
|
@ -2,6 +2,11 @@ export type numberOrUndefined = number | undefined;
|
||||||
|
|
||||||
type types = 'task' | 'normal' | 'base_communication' | 'base_society' | 'base_interdisciplinary';
|
type types = 'task' | 'normal' | 'base_communication' | 'base_society' | 'base_interdisciplinary';
|
||||||
|
|
||||||
|
export interface Page {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface InstrumentCategory {
|
export interface InstrumentCategory {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
|
@ -10,10 +15,17 @@ export interface InstrumentCategory {
|
||||||
types: any[];
|
types: any[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ContentBlock {
|
export interface Hideable {
|
||||||
title: string;
|
userCreated: boolean;
|
||||||
|
hiddenFor: any[];
|
||||||
|
visibleFor: any[];
|
||||||
|
titleHiddenFor: any[];
|
||||||
|
descriptionHiddenFor: any[];
|
||||||
|
hidden: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ContentBlock extends Hideable, Page {
|
||||||
contents: any[];
|
contents: any[];
|
||||||
id: string;
|
|
||||||
isAssignment: boolean;
|
isAssignment: boolean;
|
||||||
type: types;
|
type: types;
|
||||||
notes: any[];
|
notes: any[];
|
||||||
|
|
@ -21,13 +33,15 @@ export interface ContentBlock {
|
||||||
indent?: boolean;
|
indent?: boolean;
|
||||||
instrumentCategory: InstrumentCategory;
|
instrumentCategory: InstrumentCategory;
|
||||||
mine: boolean;
|
mine: boolean;
|
||||||
userCreated: boolean;
|
|
||||||
hiddenFor: any[];
|
|
||||||
visibleFor: any[];
|
|
||||||
root: string;
|
root: string;
|
||||||
titleHiddenFor: any[];
|
}
|
||||||
descriptionHiddenFor: any[];
|
|
||||||
hidden: boolean;
|
export interface Chapter extends Hideable, Page {
|
||||||
|
contentBlocks: ContentBlock[];
|
||||||
|
bookmark: any;
|
||||||
|
titleHidden: boolean;
|
||||||
|
descriptionHidden: boolean;
|
||||||
|
description: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ActionOptions {
|
export interface ActionOptions {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
data-cy="chapter-bookmark-actions"
|
data-cy="chapter-bookmark-actions"
|
||||||
@add-note="addNote"
|
@add-note="addNote"
|
||||||
@edit-note="editNote"
|
@edit-note="editNote"
|
||||||
@bookmark="bookmark(!chapter.bookmark)"
|
@bookmark="bookmark()"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
:class="{ 'hideable-element--greyed-out': descriptionGreyedOut }"
|
:class="{ 'hideable-element--greyed-out': descriptionGreyedOut }"
|
||||||
|
|
@ -65,164 +65,154 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import ContentBlock from '@/components/ContentBlock';
|
import { computed } from 'vue';
|
||||||
import AddContentButton from '@/components/AddContentButton';
|
import ContentBlock from '@/components/ContentBlock.vue';
|
||||||
import BookmarkActions from '@/components/notes/BookmarkActions';
|
import AddContentButton from '@/components/AddContentButton.vue';
|
||||||
import VisibilityAction from '@/components/visibility/VisibilityAction';
|
import BookmarkActions from '@/components/notes/BookmarkActions.vue';
|
||||||
|
import VisibilityAction from '@/components/visibility/VisibilityAction.vue';
|
||||||
import CopyLink from '@/components/CopyLink.vue';
|
import CopyLink from '@/components/CopyLink.vue';
|
||||||
|
import type { Chapter } from '@/@types';
|
||||||
import { hidden } from '@/helpers/visibility';
|
import { hidden } from '@/helpers/visibility';
|
||||||
import { CHAPTER_DESCRIPTION_TYPE, CHAPTER_TITLE_TYPE, CONTENT_TYPE } from '@/consts/types';
|
import { CHAPTER_DESCRIPTION_TYPE, CHAPTER_TITLE_TYPE, CONTENT_TYPE } from '@/consts/types';
|
||||||
|
import { useStore } from 'vuex';
|
||||||
|
|
||||||
import UPDATE_CHAPTER_BOOKMARK_MUTATION from '@/graphql/gql/mutations/updateChapterBookmark.gql';
|
import UPDATE_CHAPTER_BOOKMARK_MUTATION from '@/graphql/gql/mutations/updateChapterBookmark.gql';
|
||||||
import CHAPTER_QUERY from '@/graphql/gql/queries/chapterQuery.gql';
|
import CHAPTER_QUERY from '@/graphql/gql/queries/chapterQuery.gql';
|
||||||
|
import { getMe } from '@/mixins/me';
|
||||||
|
import { useMutation } from '@vue/apollo-composable';
|
||||||
|
|
||||||
import me from '@/mixins/me';
|
export interface Props {
|
||||||
|
chapter: Chapter;
|
||||||
|
index: number;
|
||||||
|
editMode: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
const { schoolClass } = getMe();
|
||||||
props: {
|
|
||||||
chapter: {
|
const store = useStore();
|
||||||
type: Object,
|
|
||||||
default: () => ({}),
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
index: 0,
|
||||||
|
editMode: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const filteredContentBlocks = computed(() => {
|
||||||
|
if (!(props.chapter && props.chapter.contentBlocks)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if (props.editMode) {
|
||||||
|
return props.chapter.contentBlocks;
|
||||||
|
}
|
||||||
|
return props.chapter.contentBlocks.filter(
|
||||||
|
(contentBlock) =>
|
||||||
|
!hidden({
|
||||||
|
block: contentBlock,
|
||||||
|
schoolClass: schoolClass,
|
||||||
|
type: CONTENT_TYPE,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
const note = computed(() => {
|
||||||
|
if (props.chapter && props.chapter.bookmark) {
|
||||||
|
return props.chapter.bookmark.note;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
const titleGreyedOut = computed(() => {
|
||||||
|
return textHidden(CHAPTER_TITLE_TYPE) && props.editMode;
|
||||||
|
});
|
||||||
|
const titleHidden = computed(() => {
|
||||||
|
// never hidden when editing the module
|
||||||
|
if (props.chapter.titleHidden === true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return textHidden(CHAPTER_TITLE_TYPE) && !props.editMode;
|
||||||
|
});
|
||||||
|
const descriptionGreyedOut = computed(() => {
|
||||||
|
return textHidden(CHAPTER_DESCRIPTION_TYPE) && props.editMode;
|
||||||
|
});
|
||||||
|
const descriptionHidden = computed(() => {
|
||||||
|
// never hidden when editing the module
|
||||||
|
if (props.chapter.descriptionHidden === true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return textHidden(CHAPTER_DESCRIPTION_TYPE) && !props.editMode;
|
||||||
|
});
|
||||||
|
|
||||||
|
const { mutate: bookmark } = useMutation(UPDATE_CHAPTER_BOOKMARK_MUTATION, () => {
|
||||||
|
const bookmarked = !props.chapter.bookmark;
|
||||||
|
const id = props.chapter.id;
|
||||||
|
return {
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
chapter: id,
|
||||||
|
bookmarked,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
index: {
|
update: (store: any) => {
|
||||||
type: Number,
|
const query = CHAPTER_QUERY;
|
||||||
default: 0,
|
const variables = { id };
|
||||||
},
|
const { chapter } = store.readQuery({
|
||||||
editMode: {
|
query,
|
||||||
type: Boolean,
|
variables,
|
||||||
default: false,
|
});
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
mixins: [me],
|
let bookmark;
|
||||||
|
|
||||||
components: {
|
if (bookmarked) {
|
||||||
BookmarkActions,
|
bookmark = {
|
||||||
VisibilityAction,
|
__typename: 'ChapterBookmarkNode',
|
||||||
ContentBlock,
|
note: null,
|
||||||
AddContentButton,
|
};
|
||||||
CopyLink,
|
} else {
|
||||||
},
|
bookmark = null;
|
||||||
|
|
||||||
computed: {
|
|
||||||
filteredContentBlocks() {
|
|
||||||
if (!(this.chapter && this.chapter.contentBlocks)) {
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
if (this.editMode) {
|
|
||||||
return this.chapter.contentBlocks;
|
|
||||||
}
|
|
||||||
return this.chapter.contentBlocks.filter(
|
|
||||||
(contentBlock) =>
|
|
||||||
!hidden({
|
|
||||||
block: contentBlock,
|
|
||||||
schoolClass: this.schoolClass,
|
|
||||||
type: CONTENT_TYPE,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
},
|
|
||||||
note() {
|
|
||||||
if (this.chapter && this.chapter.bookmark) {
|
|
||||||
return this.chapter.bookmark.note;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
titleGreyedOut() {
|
|
||||||
return this.textHidden(CHAPTER_TITLE_TYPE) && this.editMode;
|
|
||||||
},
|
|
||||||
// never hidden when editing the module
|
|
||||||
titleHidden() {
|
|
||||||
if (this.chapter.titleHidden === true) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return this.textHidden(CHAPTER_TITLE_TYPE) && !this.editMode;
|
|
||||||
},
|
|
||||||
descriptionGreyedOut() {
|
|
||||||
return this.textHidden(CHAPTER_DESCRIPTION_TYPE) && this.editMode;
|
|
||||||
},
|
|
||||||
// never hidden when editing the module
|
|
||||||
descriptionHidden() {
|
|
||||||
if (this.chapter.descriptionHidden === true) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return this.textHidden(CHAPTER_DESCRIPTION_TYPE) && !this.editMode;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
const data = {
|
||||||
bookmark(bookmarked) {
|
chapter: {
|
||||||
const id = this.chapter.id;
|
...chapter,
|
||||||
this.$apollo.mutate({
|
bookmark,
|
||||||
mutation: UPDATE_CHAPTER_BOOKMARK_MUTATION,
|
|
||||||
variables: {
|
|
||||||
input: {
|
|
||||||
chapter: id,
|
|
||||||
bookmarked,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
update: (store) => {
|
};
|
||||||
const query = CHAPTER_QUERY;
|
|
||||||
const variables = { id };
|
|
||||||
const { chapter } = store.readQuery({
|
|
||||||
query,
|
|
||||||
variables,
|
|
||||||
});
|
|
||||||
|
|
||||||
let bookmark;
|
store.writeQuery({
|
||||||
|
data,
|
||||||
if (bookmarked) {
|
query,
|
||||||
bookmark = {
|
variables,
|
||||||
__typename: 'ChapterBookmarkNode',
|
|
||||||
note: null,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
bookmark = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
chapter: {
|
|
||||||
...chapter,
|
|
||||||
bookmark,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
store.writeQuery({
|
|
||||||
data,
|
|
||||||
query,
|
|
||||||
variables,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
optimisticResponse: {
|
|
||||||
__typename: 'Mutation',
|
|
||||||
updateChapterBookmark: {
|
|
||||||
__typename: 'UpdateChapterBookmarkPayload',
|
|
||||||
success: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
addNote(id) {
|
|
||||||
this.$store.dispatch('addNote', {
|
optimisticResponse: {
|
||||||
content: id,
|
__typename: 'Mutation',
|
||||||
parent: this.chapter.id,
|
updateChapterBookmark: {
|
||||||
});
|
__typename: 'UpdateChapterBookmarkPayload',
|
||||||
|
success: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
editNote() {
|
};
|
||||||
this.$store.dispatch('editNote', this.chapter.bookmark.note);
|
});
|
||||||
},
|
|
||||||
textHidden(type) {
|
const addNote = (id: string) => {
|
||||||
return hidden({
|
store.dispatch('addNote', {
|
||||||
block: this.chapter,
|
content: id,
|
||||||
schoolClass: this.schoolClass,
|
parent: props.chapter.id,
|
||||||
type,
|
});
|
||||||
});
|
};
|
||||||
},
|
const editNote = () => {
|
||||||
},
|
store.dispatch('editNote', props.chapter.bookmark.note);
|
||||||
|
};
|
||||||
|
const textHidden = (type: string) => {
|
||||||
|
return hidden({
|
||||||
|
block: props.chapter,
|
||||||
|
schoolClass: schoolClass,
|
||||||
|
type,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script></script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import '~styles/helpers';
|
@import '~styles/helpers';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ import type { Modal } from '@/plugins/modal.types';
|
||||||
export interface Props {
|
export interface Props {
|
||||||
contentBlock: ContentBlock;
|
contentBlock: ContentBlock;
|
||||||
parent?: any;
|
parent?: any;
|
||||||
editMode: boolean;
|
editMode?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ContentComponent = defineAsyncComponent(
|
const ContentComponent = defineAsyncComponent(
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import UPDATE_OBJECTIVE_VISIBILITY_MUTATION from '@/graphql/gql/mutations/update
|
||||||
import UPDATE_OBJECTIVE_GROUP_VISIBILITY_MUTATION from '@/graphql/gql/mutations/updateObjectiveGroupVisibility.gql';
|
import UPDATE_OBJECTIVE_GROUP_VISIBILITY_MUTATION from '@/graphql/gql/mutations/updateObjectiveGroupVisibility.gql';
|
||||||
import UPDATE_CHAPTER_VISIBILITY_MUTATION from '@/graphql/gql/mutations/updateChapterVisibility.gql';
|
import UPDATE_CHAPTER_VISIBILITY_MUTATION from '@/graphql/gql/mutations/updateChapterVisibility.gql';
|
||||||
|
|
||||||
export const createVisibilityMutation = (type, id, visibility) => {
|
export const createVisibilityMutation = (type: string, id: string, visibility: string) => {
|
||||||
let mutation, variables;
|
let mutation, variables;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CONTENT_TYPE:
|
case CONTENT_TYPE:
|
||||||
|
|
@ -61,32 +61,43 @@ export const createVisibilityMutation = (type, id, visibility) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const containsClass = (arr = [], schoolClass) => arr.map((entry) => entry.id).includes(schoolClass.id);
|
const containsClass = (arr: any[] = [], schoolClass: any) => arr.map((entry) => entry.id).includes(schoolClass.id);
|
||||||
|
|
||||||
export const hidden = ({
|
export const hidden: (options: {
|
||||||
|
type: string;
|
||||||
|
block: {
|
||||||
|
userCreated: boolean;
|
||||||
|
visibleFor: any[];
|
||||||
|
hiddenFor: any[];
|
||||||
|
titleHiddenFor: any[];
|
||||||
|
descriptionHiddenFor: any[];
|
||||||
|
hidden: boolean;
|
||||||
|
};
|
||||||
|
schoolClass: any;
|
||||||
|
}) => boolean = ({
|
||||||
type,
|
type,
|
||||||
block: { userCreated, visibleFor, hiddenFor, titleHiddenFor, descriptionHiddenFor, hidden },
|
block: { userCreated, visibleFor, hiddenFor, titleHiddenFor, descriptionHiddenFor, hidden },
|
||||||
schoolClass,
|
schoolClass,
|
||||||
}) => {
|
}) => {
|
||||||
if (hidden === true) {
|
if (hidden === true) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CONTENT_TYPE:
|
case CONTENT_TYPE:
|
||||||
case OBJECTIVE_TYPE:
|
case OBJECTIVE_TYPE:
|
||||||
// is this content block / objective group user created?
|
// is this content block / objective group user created?
|
||||||
return userCreated
|
return userCreated
|
||||||
? // if so, is visibility not explicitly set for this school class?
|
? // if so, is visibility not explicitly set for this school class?
|
||||||
!containsClass(visibleFor, schoolClass)
|
!containsClass(visibleFor, schoolClass)
|
||||||
: // otherwise, is it explicitly hidden for this school class?
|
: // otherwise, is it explicitly hidden for this school class?
|
||||||
containsClass(hiddenFor, schoolClass);
|
containsClass(hiddenFor, schoolClass);
|
||||||
case OBJECTIVE_GROUP_TYPE:
|
case OBJECTIVE_GROUP_TYPE:
|
||||||
return containsClass(hiddenFor, schoolClass);
|
return containsClass(hiddenFor, schoolClass);
|
||||||
case CHAPTER_TITLE_TYPE:
|
case CHAPTER_TITLE_TYPE:
|
||||||
return containsClass(titleHiddenFor, schoolClass);
|
return containsClass(titleHiddenFor, schoolClass);
|
||||||
case CHAPTER_DESCRIPTION_TYPE:
|
case CHAPTER_DESCRIPTION_TYPE:
|
||||||
return containsClass(descriptionHiddenFor, schoolClass);
|
return containsClass(descriptionHiddenFor, schoolClass);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Loading…
Reference in New Issue