Fix deep-selectors

This commit is contained in:
Ramon Wenger 2023-02-02 14:36:08 +01:00
parent 4477b7c5ed
commit 4b55f8952c
8 changed files with 896 additions and 951 deletions

View File

@ -1,38 +1,20 @@
<template> <template>
<div <div
:class="{'hideable-element--greyed-out': hidden}" :class="{ 'hideable-element--greyed-out': hidden }"
class="content-block__container hideable-element content-list__parent" class="content-block__container hideable-element content-list__parent"
> >
<div <div :class="specialClass" :style="instrumentStyle" class="content-block" data-cy="content-block">
:class="specialClass" <div class="block-actions" v-if="canEditModule && !isInstrumentBlock">
:style="instrumentStyle" <user-widget v-bind="me" class="block-actions__user-widget content-block__user-widget" v-if="isMine" />
class="content-block"
data-cy="content-block"
>
<div
class="block-actions"
v-if="canEditModule && !isInstrumentBlock"
>
<user-widget
v-bind="me"
class="block-actions__user-widget content-block__user-widget"
v-if="isMine"
/>
<more-options-widget> <more-options-widget>
<li <li class="popover-links__link" v-if="!isInstrumentBlock">
class="popover-links__link"
v-if="!isInstrumentBlock"
>
<popover-link <popover-link
data-cy="duplicate-content-block-link" data-cy="duplicate-content-block-link"
text="Duplizieren" text="Duplizieren"
@link-action="duplicateContentBlock(contentBlock)" @link-action="duplicateContentBlock(contentBlock)"
/> />
</li> </li>
<li <li class="popover-links__link" v-if="isMine">
class="popover-links__link"
v-if="isMine"
>
<popover-link <popover-link
data-cy="delete-content-block-link" data-cy="delete-content-block-link"
text="Löschen" text="Löschen"
@ -40,22 +22,13 @@
/> />
</li> </li>
<li <li class="popover-links__link" v-if="isMine">
class="popover-links__link" <popover-link text="Bearbeiten" @link-action="editContentBlock(contentBlock)" />
v-if="isMine"
>
<popover-link
text="Bearbeiten"
@link-action="editContentBlock(contentBlock)"
/>
</li> </li>
</more-options-widget> </more-options-widget>
</div> </div>
<div class="content-block__visibility"> <div class="content-block__visibility">
<visibility-action <visibility-action :block="contentBlock" v-if="canEditModule" />
:block="contentBlock"
v-if="canEditModule"
/>
</div> </div>
<h3 <h3
@ -66,10 +39,7 @@
> >
{{ instrumentLabel }} {{ instrumentLabel }}
</h3> </h3>
<h4 <h4 class="content-block__title" v-if="!contentBlock.indent">
class="content-block__title"
v-if="!contentBlock.indent"
>
{{ contentBlock.title }} {{ contentBlock.title }}
</h4> </h4>
@ -85,37 +55,35 @@
/> />
</div> </div>
<add-content-button <add-content-button :where="{ after: contentBlock }" v-if="canEditModule" />
:where="{after: contentBlock}"
v-if="canEditModule"
/>
</div> </div>
</template> </template>
<script> <script>
import AddContentButton from '@/components/AddContentButton'; import AddContentButton from '@/components/AddContentButton';
import MoreOptionsWidget from '@/components/MoreOptionsWidget'; import MoreOptionsWidget from '@/components/MoreOptionsWidget';
import UserWidget from '@/components/UserWidget'; import UserWidget from '@/components/UserWidget';
import VisibilityAction from '@/components/visibility/VisibilityAction'; import VisibilityAction from '@/components/visibility/VisibilityAction';
import CHAPTER_QUERY from '@/graphql/gql/queries/chapterQuery.gql'; import CHAPTER_QUERY from '@/graphql/gql/queries/chapterQuery.gql';
import DELETE_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/deleteContentBlock.gql'; import DELETE_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/deleteContentBlock.gql';
import DUPLICATE_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/duplicateContentBlock.gql'; import DUPLICATE_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/duplicateContentBlock.gql';
import me from '@/mixins/me'; import me from '@/mixins/me';
import {hidden} from '@/helpers/visibility'; import { hidden } from '@/helpers/visibility';
import {CONTENT_TYPE} from '@/consts/types'; import { CONTENT_TYPE } from '@/consts/types';
import PopoverLink from '@/components/ui/PopoverLink'; import PopoverLink from '@/components/ui/PopoverLink';
import {insertAtIndex, removeAtIndex} from '@/graphql/immutable-operations'; import { insertAtIndex, removeAtIndex } from '@/graphql/immutable-operations';
import {EDIT_CONTENT_BLOCK_PAGE} from '@/router/module.names'; import { EDIT_CONTENT_BLOCK_PAGE } from '@/router/module.names';
import {defineAsyncComponent} from 'vue'; import { defineAsyncComponent } from 'vue';
import {instrumentCategory} from '@/helpers/instrumentType'; import { instrumentCategory } from '@/helpers/instrumentType';
const ContentComponent = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/ContentComponent')); const ContentComponent = defineAsyncComponent(() =>
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/ContentComponent')
);
export default {
export default {
name: 'ContentBlock', name: 'ContentBlock',
props: { props: {
contentBlock: { contentBlock: {
@ -157,14 +125,15 @@
instrumentStyle() { instrumentStyle() {
if (this.isInstrumentBlock) { if (this.isInstrumentBlock) {
return { return {
backgroundColor: this.contentBlock.instrumentCategory.background backgroundColor: this.contentBlock.instrumentCategory.background,
}; };
} }
return {}; return {};
}, },
instrumentLabel() { instrumentLabel() {
const contentType = this.contentBlock.type.toLowerCase(); const contentType = this.contentBlock.type.toLowerCase();
if (contentType.startsWith('base')) { // all legacy instruments start with `base` if (contentType.startsWith('base')) {
// all legacy instruments start with `base`
return instrumentCategory(contentType); return instrumentCategory(contentType);
} }
if (this.isInstrumentBlock) { if (this.isInstrumentBlock) {
@ -176,7 +145,7 @@
instrumentLabelStyle() { instrumentLabelStyle() {
if (this.isInstrumentBlock) { if (this.isInstrumentBlock) {
return { return {
color: this.contentBlock.instrumentCategory.foreground color: this.contentBlock.instrumentCategory.foreground,
}; };
} }
return {}; return {};
@ -207,7 +176,8 @@
// collect content_list_items // collect content_list_items
if (content.type === 'content_list_item') { if (content.type === 'content_list_item') {
contentList = [...contentList, content]; contentList = [...contentList, content];
if (index === this.contentBlock.contents.length - 1) { // content is last element of contents array if (index === this.contentBlock.contents.length - 1) {
// content is last element of contents array
let updatedContent = [...newContents, ...this.createContentListOrBlocks(contentList)]; let updatedContent = [...newContents, ...this.createContentListOrBlocks(contentList)];
return updatedContent; return updatedContent;
} }
@ -240,7 +210,7 @@
}, },
}, },
methods: { methods: {
duplicateContentBlock({id}) { duplicateContentBlock({ id }) {
const parent = this.parent; const parent = this.parent;
this.$apollo.mutate({ this.$apollo.mutate({
mutation: DUPLICATE_CONTENT_BLOCK_MUTATION, mutation: DUPLICATE_CONTENT_BLOCK_MUTATION,
@ -249,14 +219,21 @@
id, id,
}, },
}, },
update(store, {data: {duplicateContentBlock: {contentBlock}}}) { update(
store,
{
data: {
duplicateContentBlock: { contentBlock },
},
}
) {
if (contentBlock) { if (contentBlock) {
const query = CHAPTER_QUERY; const query = CHAPTER_QUERY;
const variables = { const variables = {
id: parent.id, id: parent.id,
}; };
const {chapter} = store.readQuery({query, variables}); const { chapter } = store.readQuery({ query, variables });
const index = chapter.contentBlocks.findIndex(contentBlock => contentBlock.id === id); const index = chapter.contentBlocks.findIndex((contentBlock) => contentBlock.id === id);
const contentBlocks = insertAtIndex(chapter.contentBlocks, index, contentBlock); const contentBlocks = insertAtIndex(chapter.contentBlocks, index, contentBlock);
const data = { const data = {
chapter: { chapter: {
@ -264,11 +241,10 @@
contentBlocks, contentBlocks,
}, },
}; };
store.writeQuery({query, variables, data}); store.writeQuery({ query, variables, data });
} }
}, },
}); });
}, },
editContentBlock(contentBlock) { editContentBlock(contentBlock) {
const route = { const route = {
@ -280,7 +256,9 @@
this.$router.push(route); this.$router.push(route);
}, },
deleteContentBlock(contentBlock) { deleteContentBlock(contentBlock) {
this.$modal.open('confirm').then(() => { this.$modal
.open('confirm')
.then(() => {
this.doDeleteContentBlock(contentBlock); this.doDeleteContentBlock(contentBlock);
}) })
.catch(); .catch();
@ -295,14 +273,21 @@
id, id,
}, },
}, },
update(store, {data: {deleteContentBlock: {success}}}) { update(
store,
{
data: {
deleteContentBlock: { success },
},
}
) {
if (success) { if (success) {
const query = CHAPTER_QUERY; const query = CHAPTER_QUERY;
const variables = { const variables = {
id: parent.id, id: parent.id,
}; };
const {chapter} = store.readQuery({query, variables}); const { chapter } = store.readQuery({ query, variables });
const index = chapter.contentBlocks.findIndex(contentBlock => contentBlock.id === id); const index = chapter.contentBlocks.findIndex((contentBlock) => contentBlock.id === id);
const contentBlocks = removeAtIndex(chapter.contentBlocks, index); const contentBlocks = removeAtIndex(chapter.contentBlocks, index);
const data = { const data = {
chapter: { chapter: {
@ -310,26 +295,28 @@
contentBlocks, contentBlocks,
}, },
}; };
store.writeQuery({query, variables, data}); store.writeQuery({ query, variables, data });
} }
}, },
}); });
}, },
createContentListOrBlocks(contentList) { createContentListOrBlocks(contentList) {
return [{ return [
{
type: 'content_list', type: 'content_list',
contents: contentList, contents: contentList,
id: contentList[0].id, id: contentList[0].id,
}]; },
];
}, },
}, },
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "~styles/helpers"; @import '~styles/helpers';
.content-block { .content-block {
margin-bottom: $section-spacing; margin-bottom: $section-spacing;
position: relative; position: relative;
@ -398,7 +385,7 @@
@include content-box-base; @include content-box-base;
} }
/deep/ p { :deep(p) {
line-height: 1.5; line-height: 1.5;
margin-bottom: 1em; margin-bottom: 1em;
@ -407,7 +394,7 @@
} }
} }
/deep/ .text-block { :deep(.text-block) {
ul { ul {
@include list-parent; @include list-parent;
} }
@ -417,6 +404,5 @@
line-height: 1.5; line-height: 1.5;
} }
} }
}
}
</style> </style>

View File

@ -1,46 +1,27 @@
<template> <template>
<!-- eslint-disable vue/no-v-html --> <!-- eslint-disable vue/no-v-html -->
<div <div class="solution" data-cy="solution">
class="solution" <a class="solution__toggle" data-cy="show-solution" @click="toggle"
data-cy="solution"
>
<a
class="solution__toggle"
data-cy="show-solution"
@click="toggle"
>Lösung >Lösung
<template v-if="!visible">anzeigen</template> <template v-if="!visible">anzeigen</template>
<template v-else>ausblenden</template> <template v-else>ausblenden</template>
</a> </a>
<transition name="fade"> <transition name="fade">
<div <div class="solution__hidden fade" v-if="visible">
class="solution__hidden fade" <p class="solution__text solution-text" data-cy="solution-text" v-html="sanitizedText" />
v-if="visible" <cms-document-block :solution="true" class="solution__document" :value="value.document" v-if="value.document" />
>
<p
class="solution__text solution-text"
data-cy="solution-text"
v-html="sanitizedText"
/>
<cms-document-block
:solution="true"
class="solution__document"
:value="value.document"
v-if="value.document"
/>
</div> </div>
</transition> </transition>
</div> </div>
</template> </template>
<script> <script>
import {sanitizeAsHtml} from '@/helpers/text'; import { sanitizeAsHtml } from '@/helpers/text';
import CmsDocumentBlock from '@/components/content-blocks/CmsDocumentBlock'; import CmsDocumentBlock from '@/components/content-blocks/CmsDocumentBlock';
export default { export default {
props: ['value'], props: ['value'],
components: {CmsDocumentBlock}, components: { CmsDocumentBlock },
data() { data() {
return { return {
@ -59,13 +40,13 @@
this.visible = !this.visible; this.visible = !this.visible;
}, },
}, },
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "~styles/helpers"; @import '~styles/helpers';
.solution { .solution {
display: grid; display: grid;
grid-auto-rows: auto; grid-auto-rows: auto;
grid-row-gap: 15px; grid-row-gap: 15px;
@ -86,12 +67,12 @@
font-size: toRem(18px); font-size: toRem(18px);
color: $color-silver-dark; color: $color-silver-dark;
/deep/ p { :deep(p) {
font-size: toRem(18px); font-size: toRem(18px);
color: $color-silver-dark; color: $color-silver-dark;
} }
/deep/ ul { :deep(ul) {
padding-left: $medium-spacing; padding-left: $medium-spacing;
> li { > li {
@ -100,15 +81,15 @@
} }
} }
} }
} }
.fade-enter-active, .fade-enter-active,
.fade-leave-active { .fade-leave-active {
transition: opacity .3s; transition: opacity 0.3s;
} }
.fade-enter-from, .fade-enter-from,
.fade-leave-active { .fade-leave-active {
opacity: 0; opacity: 0;
} }
</style> </style>

View File

@ -1,19 +1,9 @@
<template> <template>
<!-- eslint-disable vue/no-v-html --> <!-- eslint-disable vue/no-v-html -->
<div <div :data-scrollto="value.id" class="assignment">
:data-scrollto="value.id" <p class="assignment__main-text" data-cy="assignment-main-text" v-html="assignment.assignment" />
class="assignment"
>
<p
class="assignment__main-text"
data-cy="assignment-main-text"
v-html="assignment.assignment"
/>
<solution <solution :value="solution" v-if="assignment.solution" />
:value="solution"
v-if="assignment.solution"
/>
<template v-if="isStudent"> <template v-if="isStudent">
<submission-form <submission-form
@ -33,46 +23,41 @@
@spellcheck="spellcheck" @spellcheck="spellcheck"
/> />
<spell-check <spell-check :corrections="corrections" :text="submission.text" />
:corrections="corrections"
:text="submission.text"
/>
<p <p class="assignment__feedback" v-if="assignment.submission.submissionFeedback" v-html="feedbackText" />
class="assignment__feedback"
v-if="assignment.submission.submissionFeedback"
v-html="feedbackText"
/>
</template> </template>
<template v-if="!isStudent"> <template v-if="!isStudent">
<router-link <router-link :to="{ name: 'submissions', params: { id: assignment.id } }" class="button button--primary">
:to="{name: 'submissions', params: { id: assignment.id }}" Zu den Ergebnissen
class="button button--primary"
>
Zu den
Ergebnissen
</router-link> </router-link>
</template> </template>
</div> </div>
</template> </template>
<script> <script>
import {mapActions, mapGetters} from 'vuex'; import { mapActions, mapGetters } from 'vuex';
import ASSIGNMENT_QUERY from '@/graphql/gql/queries/assignmentQuery.gql'; import ASSIGNMENT_QUERY from '@/graphql/gql/queries/assignmentQuery.gql';
import ME_QUERY from '@/graphql/gql/queries/meQuery.gql'; import ME_QUERY from '@/graphql/gql/queries/meQuery.gql';
import UPDATE_ASSIGNMENT_MUTATION from '@/graphql/gql/mutations/updateAssignmentMutation.gql'; import UPDATE_ASSIGNMENT_MUTATION from '@/graphql/gql/mutations/updateAssignmentMutation.gql';
import UPDATE_ASSIGNMENT_MUTATION_WITH_SUCCESS from '@/graphql/gql/mutations/updateAssignmentMutationWithSuccess.gql'; import UPDATE_ASSIGNMENT_MUTATION_WITH_SUCCESS from '@/graphql/gql/mutations/updateAssignmentMutationWithSuccess.gql';
import SPELL_CHECK_MUTATION from '@/graphql/gql/mutations/spellCheck.gql'; import SPELL_CHECK_MUTATION from '@/graphql/gql/mutations/spellCheck.gql';
import debounce from 'lodash/debounce'; import debounce from 'lodash/debounce';
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import {sanitize} from '@/helpers/text'; import { sanitize } from '@/helpers/text';
import {defineAsyncComponent} from 'vue'; import { defineAsyncComponent } from 'vue';
const SubmissionForm = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/assignment/SubmissionForm')); const SubmissionForm = defineAsyncComponent(() =>
const Solution = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/Solution')); import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/assignment/SubmissionForm')
const SpellCheck = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/assignment/SpellCheck')); );
const Solution = defineAsyncComponent(() =>
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/Solution')
);
const SpellCheck = defineAsyncComponent(() =>
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/assignment/SpellCheck')
);
export default { export default {
props: ['value'], props: ['value'],
components: { components: {
@ -127,7 +112,8 @@
...mapActions(['scrollToAssignmentReady']), ...mapActions(['scrollToAssignmentReady']),
_save: debounce(function (submission) { _save: debounce(function (submission) {
this.saving++; this.saving++;
this.$apollo.mutate({ this.$apollo
.mutate({
mutation: UPDATE_ASSIGNMENT_MUTATION_WITH_SUCCESS, mutation: UPDATE_ASSIGNMENT_MUTATION_WITH_SUCCESS,
variables: { variables: {
input: { input: {
@ -138,7 +124,14 @@
}, },
}, },
}, },
update(store, {data: {updateAssignment: {successful, updatedAssignment}}}) { update(
store,
{
data: {
updateAssignment: { successful, updatedAssignment },
},
}
) {
try { try {
if (successful) { if (successful) {
const query = ASSIGNMENT_QUERY; const query = ASSIGNMENT_QUERY;
@ -149,16 +142,17 @@
submission, submission,
}); });
const data = { const data = {
assignment assignment,
}; };
store.writeQuery({query, variables, data}); store.writeQuery({ query, variables, data });
} }
} catch (e) { } catch (e) {
console.error(e); console.error(e);
// Query did not exist in the cache, and apollo throws a generic Error. Do nothing // Query did not exist in the cache, and apollo throws a generic Error. Do nothing
} }
}, },
}).then(() => { })
.then(() => {
this.saving--; this.saving--;
if (this.saving === 0) { if (this.saving === 0) {
this.unsaved = false; this.unsaved = false;
@ -222,7 +216,8 @@
spellcheck() { spellcheck() {
let self = this; let self = this;
this.spellcheckLoading = true; this.spellcheckLoading = true;
this.$apollo.mutate({ this.$apollo
.mutate({
mutation: SPELL_CHECK_MUTATION, mutation: SPELL_CHECK_MUTATION,
variables: { variables: {
input: { input: {
@ -230,10 +225,18 @@
text: this.assignment.submission.text, text: this.assignment.submission.text,
}, },
}, },
update(store, {data: {spellCheck: {results}}}) { update(
store,
{
data: {
spellCheck: { results },
},
}
) {
self.corrections = results; self.corrections = results;
}, },
}).then(() => { })
.then(() => {
this.spellcheckLoading = false; this.spellcheckLoading = false;
}); });
}, },
@ -260,15 +263,15 @@
query: ME_QUERY, query: ME_QUERY,
}, },
}, },
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import '@/styles/_variables.scss'; @import '@/styles/_variables.scss';
@import '@/styles/_functions.scss'; @import '@/styles/_functions.scss';
@import '@/styles/_mixins.scss'; @import '@/styles/_mixins.scss';
.assignment { .assignment {
margin-bottom: 3rem; margin-bottom: 3rem;
position: relative; position: relative;
@ -278,11 +281,11 @@
} }
&__main-text { &__main-text {
/deep/ ul{ :deep(ul) {
@include list-parent @include list-parent;
} }
/deep/ li { :deep(li) {
@include list-child; @include list-child;
} }
} }
@ -313,7 +316,5 @@
&__feedback { &__feedback {
@include regular-text; @include regular-text;
} }
}
}
</style> </style>

View File

@ -1,37 +1,29 @@
<template> <template>
<div class="tip-tap"> <div class="tip-tap">
<editor-content <editor-content class="tip-tap__editor-wrapper" :editor="editor" />
class="tip-tap__editor-wrapper"
:editor="editor"
/>
<toggle <toggle :bordered="false" :checked="isList" label="Als Liste formatieren" @input="toggleList" />
:bordered="false"
:checked="isList"
label="Als Liste formatieren"
@input="toggleList"
/>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import {PropType, defineComponent} from 'vue'; import { PropType, defineComponent } from 'vue';
import {Editor, EditorContent} from "@tiptap/vue-3"; import { Editor, EditorContent } from '@tiptap/vue-3';
import Document from '@tiptap/extension-document'; import Document from '@tiptap/extension-document';
import Paragraph from '@tiptap/extension-paragraph'; import Paragraph from '@tiptap/extension-paragraph';
import Text from '@tiptap/extension-text'; import Text from '@tiptap/extension-text';
import BulletList from '@tiptap/extension-bullet-list'; import BulletList from '@tiptap/extension-bullet-list';
import ListItem from '@tiptap/extension-list-item'; import ListItem from '@tiptap/extension-list-item';
import Toggle from "@/components/ui/Toggle.vue"; import Toggle from '@/components/ui/Toggle.vue';
interface Data { interface Data {
editor: Editor | undefined; editor: Editor | undefined;
} }
interface Value { interface Value {
text: string; text: string;
} }
export default defineComponent({ export default defineComponent({
props: { props: {
value: { value: {
type: Object as PropType<Value>, type: Object as PropType<Value>,
@ -43,7 +35,7 @@
components: { components: {
Toggle, Toggle,
EditorContent EditorContent,
}, },
data(): Data { data(): Data {
@ -58,11 +50,11 @@
}, },
text(): string { text(): string {
return this.value?.text || ''; return this.value?.text || '';
} },
}, },
watch: { watch: {
value({text}: Value) { value({ text }: Value) {
const editor = this.editor as Editor; // editor is always initialized on mount, cast it const editor = this.editor as Editor; // editor is always initialized on mount, cast it
const isSame = editor.getHTML() === text; const isSame = editor.getHTML() === text;
@ -71,29 +63,23 @@
} }
editor.commands.setContent(text, false); editor.commands.setContent(text, false);
} },
}, },
mounted() { mounted() {
this.editor = new Editor({ this.editor = new Editor({
editorProps: { editorProps: {
attributes: { attributes: {
class: 'tip-tap__editor' class: 'tip-tap__editor',
} },
}, },
content: this.text, content: this.text,
extensions: [ extensions: [Document, Paragraph, Text, BulletList, ListItem],
Document,
Paragraph,
Text,
BulletList,
ListItem
],
onUpdate: () => { onUpdate: () => {
const text=(this.editor as Editor).getHTML(); const text = (this.editor as Editor).getHTML();
this.$emit('input', text); this.$emit('input', text);
this.$emit('change-text', text); this.$emit('change-text', text);
} },
}); });
}, },
@ -106,42 +92,39 @@
const editor = this.editor as Editor; const editor = this.editor as Editor;
editor.chain().selectAll().toggleBulletList().run(); editor.chain().selectAll().toggleBulletList().run();
}, },
} },
}); });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import '~styles/helpers'; @import '~styles/helpers';
.tip-tap {
.tip-tap {
&__editor-wrapper { &__editor-wrapper {
margin-bottom: $medium-spacing; margin-bottom: $medium-spacing;
} }
/deep/ &__editor { :deep(.tip-tap__editor) {
@include inputstyle; @include inputstyle;
flex-direction: column; flex-direction: column;
min-height: 150px; min-height: 150px;
} }
/deep/ ul { :deep(ul) {
padding-left: $medium-spacing; padding-left: $medium-spacing;
list-style: initial; list-style: initial;
} }
/deep/ li { :deep(li) {
@include inputfont; @include inputfont;
} }
/deep/ div { :deep(div) {
@include inputfont; @include inputfont;
} }
/deep/ p { :deep(p) {
@include inputfont; @include inputfont;
} }
} }
</style> </style>

View File

@ -7,33 +7,32 @@
<slot /> <slot />
</div> </div>
<div <div class="activity-entry__link" @click="$emit('link')">
class="activity-entry__link"
@click="$emit('link')"
>
<chevron-right class="activity-entry__icon" /> <chevron-right class="activity-entry__icon" />
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import {defineAsyncComponent} from 'vue'; import { defineAsyncComponent } from 'vue';
const ChevronRight = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/ChevronRight')); const ChevronRight = defineAsyncComponent(() =>
import(/* webpackChunkName: "icons" */ '@/components/icons/ChevronRight')
);
export default { export default {
props: ['title'], props: ['title'],
components: { components: {
ChevronRight ChevronRight,
} },
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/styles/_variables.scss"; @import '@/styles/_variables.scss';
@import "@/styles/_mixins.scss"; @import '@/styles/_mixins.scss';
.activity-entry { .activity-entry {
padding: $small-spacing 0; padding: $small-spacing 0;
border-bottom: 1px solid $color-silver; border-bottom: 1px solid $color-silver;
display: flex; display: flex;
@ -63,8 +62,8 @@
width: 30px; width: 30px;
} }
/deep/ p { :deep(p) {
@include regular-text; @include regular-text;
} }
} }
</style> </style>

View File

@ -1,43 +1,46 @@
<template> <template>
<div class="simple-file-upload"> <div class="simple-file-upload">
<component <component :is="button" @click="clickUploadCare" />
:is="button"
@click="clickUploadCare"
/>
<simple-file-upload-hidden-input @link-change-url="$emit('link-change-url', $event)" /> <simple-file-upload-hidden-input @link-change-url="$emit('link-change-url', $event)" />
</div> </div>
</template> </template>
<script> <script>
import {defineAsyncComponent} from 'vue'; import { defineAsyncComponent } from 'vue';
const SimpleFileUploadHiddenInput = defineAsyncComponent(() => import('@/components/ui/file-upload/SimpleFileUploadHiddenInput')); const SimpleFileUploadHiddenInput = defineAsyncComponent(() =>
const SimpleFileUploadIcon = defineAsyncComponent(() => import('@/components/ui/file-upload/SimpleFileUploadIcon')); import('@/components/ui/file-upload/SimpleFileUploadHiddenInput')
const SimpleFileUploadIconAndText = defineAsyncComponent(() => import('@/components/ui/file-upload/SimpleFileUploadIconAndText')); );
const DocumentIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/DocumentIcon')); const SimpleFileUploadIcon = defineAsyncComponent(() => import('@/components/ui/file-upload/SimpleFileUploadIcon'));
const SimpleFileUploadIconAndText = defineAsyncComponent(() =>
import('@/components/ui/file-upload/SimpleFileUploadIconAndText')
);
const DocumentIcon = defineAsyncComponent(() =>
import(/* webpackChunkName: "icons" */ '@/components/icons/DocumentIcon')
);
export default { export default {
props: { props: {
value: { value: {
type: String, type: String,
default: '' default: '',
}, },
withText: { withText: {
type: Boolean, type: Boolean,
default: false default: false,
} },
}, },
components: { components: {
SimpleFileUploadHiddenInput, SimpleFileUploadHiddenInput,
DocumentIcon, DocumentIcon,
SimpleFileUploadIcon, SimpleFileUploadIcon,
SimpleFileUploadIconAndText SimpleFileUploadIconAndText,
}, },
computed: { computed: {
button() { button() {
return this.withText ? 'simple-file-upload-icon-and-text' : 'simple-file-upload-icon'; return this.withText ? 'simple-file-upload-icon-and-text' : 'simple-file-upload-icon';
} },
}, },
methods: { methods: {
@ -45,15 +48,15 @@
// workaround for styling the uploadcare widget // workaround for styling the uploadcare widget
let button = this.$el.querySelector('.uploadcare--widget__button'); let button = this.$el.querySelector('.uploadcare--widget__button');
button.click(); button.click();
}
}, },
}; },
};
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "~styles/_helpers"; @import '~styles/_helpers';
.simple-file-upload { .simple-file-upload {
height: 25px; height: 25px;
overflow: hidden; overflow: hidden;
cursor: pointer; cursor: pointer;
@ -64,9 +67,9 @@
width: 25px; width: 25px;
height: 25px; height: 25px;
} }
} }
/deep/ .uploadcare--widget { :deep(.uploadcare--widget) {
display: none; display: none;
} }
</style> </style>

View File

@ -1,22 +1,19 @@
<template> <template>
<div class="simple-file-upload"> <div class="simple-file-upload">
<button-with-icon-and-text <button-with-icon-and-text icon="document-icon" text="Dokument hochladen" v-if="!value" @click="clickUploadCare" />
icon="document-icon"
text="Dokument hochladen"
v-if="!value"
@click="clickUploadCare"
/>
<simple-file-upload-hidden-input @link-change-url="$emit('link-change-url', $event)" /> <simple-file-upload-hidden-input @link-change-url="$emit('link-change-url', $event)" />
</div> </div>
</template> </template>
<script> <script>
import {defineAsyncComponent} from 'vue'; import { defineAsyncComponent } from 'vue';
const SimpleFileUploadHiddenInput = defineAsyncComponent(() => import('@/components/ui/file-upload/SimpleFileUploadHiddenInput')); const SimpleFileUploadHiddenInput = defineAsyncComponent(() =>
const ButtonWithIconAndText = defineAsyncComponent(() => import('@/components/ui/ButtonWithIconAndText')); import('@/components/ui/file-upload/SimpleFileUploadHiddenInput')
);
const ButtonWithIconAndText = defineAsyncComponent(() => import('@/components/ui/ButtonWithIconAndText'));
export default { export default {
props: ['value'], props: ['value'],
components: { components: {
@ -31,13 +28,13 @@
button.click(); button.click();
}, },
}, },
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "~styles/_helpers"; @import '~styles/_helpers';
.simple-file-upload { .simple-file-upload {
width: 25px; width: 25px;
height: 25px; height: 25px;
overflow: hidden; overflow: hidden;
@ -53,9 +50,9 @@
width: 25px; width: 25px;
height: 25px; height: 25px;
} }
} }
/deep/ .uploadcare--widget { :deep(.uploadcare--widget) {
display: none; display: none;
} }
</style> </style>

View File

@ -1,18 +1,11 @@
<template> <template>
<div class="instrument"> <div class="instrument">
<h1 <h1 class="instrument__title" data-cy="instrument-title">
class="instrument__title"
data-cy="instrument-title"
>
{{ instrument.title }} {{ instrument.title }}
</h1> </h1>
<!-- eslint-disable vue/no-v-html --> <!-- eslint-disable vue/no-v-html -->
<div <div class="instrument__intro intro" data-cy="instrument-intro" v-html="instrument.intro" />
class="instrument__intro intro"
data-cy="instrument-intro"
v-html="instrument.intro"
/>
<content-component <content-component
:component="component" :component="component"
@ -27,46 +20,48 @@
</template> </template>
<script> <script>
import INSTRUMENT_QUERY from '@/graphql/gql/queries/instrumentQuery.gql'; import INSTRUMENT_QUERY from '@/graphql/gql/queries/instrumentQuery.gql';
import {defineAsyncComponent} from 'vue'; import { defineAsyncComponent } from 'vue';
const ContentComponent = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/ContentComponent')); const ContentComponent = defineAsyncComponent(() =>
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/ContentComponent')
);
export default { export default {
apollo: { apollo: {
instrument() { instrument() {
return { return {
query: INSTRUMENT_QUERY, query: INSTRUMENT_QUERY,
variables: { variables: {
slug: this.$route.params.slug slug: this.$route.params.slug,
} },
}; };
} },
}, },
components: { components: {
ContentComponent ContentComponent,
}, },
data() { data() {
return { return {
instrument: {} instrument: {},
};
}
}; };
},
};
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "~styles/helpers"; @import '~styles/helpers';
.instrument { .instrument {
&__title { &__title {
font-size: toRem(35px); font-size: toRem(35px);
margin-bottom: $large-spacing; margin-bottom: $large-spacing;
line-height: $default-heading-line-height; line-height: $default-heading-line-height;
} }
& /deep/ { & :deep() {
& p { & p {
margin-bottom: $large-spacing; margin-bottom: $large-spacing;
} }
@ -102,5 +97,5 @@
font-weight: 600; font-weight: 600;
} }
} }
} }
</style> </style>