Upgrade code according to migration guide for Vue 3
Update npm dependencies Update vue router version Disable validation temporarily Specify property Update dependencies Update store to v4 Update async component definitions Update some event emitters Update tiptap vue version Implement some router changes for v4 Remove obsolete tag attributes Update dependencies Fix some cypress tests Fix most jest tests Fix some more cypress tests Fix school class cypress test Fix another cypress test Disable failing test temporarily Fix validation Fix error messages for validation Fix e2e test for beta login page Apply prettier
This commit is contained in:
parent
4b55f8952c
commit
a52671fd40
|
|
@ -1 +1,3 @@
|
|||
bundle-analysis
|
||||
dist
|
||||
node_modules
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import module from '../../../fixtures/module.minimal';
|
||||
import {getMinimalMe} from '../../../support/helpers';
|
||||
import {hasOperationName} from '../../../support/graphql';
|
||||
import { getMinimalMe } from '../../../support/helpers';
|
||||
import { hasOperationName } from '../../../support/graphql';
|
||||
|
||||
let snapshotTitle;
|
||||
let deleteSuccess;
|
||||
|
|
@ -133,7 +133,7 @@ describe('Snapshot', () => {
|
|||
},
|
||||
},
|
||||
},
|
||||
MeQuery: getMinimalMe({isTeacher}),
|
||||
MeQuery: getMinimalMe({ isTeacher }),
|
||||
ModuleDetailsQuery: {
|
||||
module,
|
||||
},
|
||||
|
|
@ -219,7 +219,9 @@ describe('Snapshot', () => {
|
|||
cy.getByDataCy('module-snapshots-button').click();
|
||||
cy.getByDataCy('create-snapshot-button').click();
|
||||
cy.getByDataCy('show-all-snapshots-button').click();
|
||||
cy.getByDataCy('snapshot-list').should('exist').within(() => {
|
||||
cy.getByDataCy('snapshot-list')
|
||||
.should('exist')
|
||||
.within(() => {
|
||||
cy.get('.snapshots__snapshot').should('have.length', 1);
|
||||
});
|
||||
waitNTimes(7);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
describe('Room Team Management - Read only', () => {
|
||||
const SELECTED_CLASS_ID = 'selectedClassId';
|
||||
|
||||
const getOperations = ({readOnly, classReadOnly}) => ({
|
||||
const getOperations = ({ readOnly, classReadOnly }) => ({
|
||||
MeQuery: {
|
||||
me: {
|
||||
readOnly,
|
||||
|
|
@ -13,7 +13,8 @@ describe('Room Team Management - Read only', () => {
|
|||
},
|
||||
},
|
||||
RoomsQuery: {
|
||||
rooms: [{
|
||||
rooms: [
|
||||
{
|
||||
id: '',
|
||||
slug: 'some-room',
|
||||
title: 'some room',
|
||||
|
|
@ -24,12 +25,13 @@ describe('Room Team Management - Read only', () => {
|
|||
id: SELECTED_CLASS_ID,
|
||||
name: 'bla',
|
||||
},
|
||||
}],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const checkRoomsReadOnly = ({editable, readOnly, classReadOnly = false}) => {
|
||||
const operations = getOperations({readOnly, classReadOnly});
|
||||
const checkRoomsReadOnly = ({ editable, readOnly, classReadOnly = false }) => {
|
||||
const operations = getOperations({ readOnly, classReadOnly });
|
||||
|
||||
cy.mockGraphqlOps({
|
||||
operations,
|
||||
|
|
@ -48,14 +50,14 @@ describe('Room Team Management - Read only', () => {
|
|||
});
|
||||
|
||||
it('can edit room', () => {
|
||||
checkRoomsReadOnly({editable: true, readOnly: false});
|
||||
checkRoomsReadOnly({ editable: true, readOnly: false });
|
||||
});
|
||||
|
||||
it('can not edit room', () => {
|
||||
checkRoomsReadOnly({editable: false, readOnly: true});
|
||||
checkRoomsReadOnly({ editable: false, readOnly: true });
|
||||
});
|
||||
|
||||
it('can not edit room of inactive class', () => {
|
||||
checkRoomsReadOnly({editable: false, readOnly: false, classReadOnly: true});
|
||||
checkRoomsReadOnly({ editable: false, readOnly: false, classReadOnly: true });
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,11 +1,5 @@
|
|||
module.exports = {
|
||||
moduleFileExtensions: [
|
||||
'js',
|
||||
'jsx',
|
||||
'ts',
|
||||
'json',
|
||||
'vue',
|
||||
],
|
||||
moduleFileExtensions: ['js', 'jsx', 'ts', 'json', 'vue'],
|
||||
transform: {
|
||||
'\\.(gql|graphql)$': '@graphql-tools/jest-transform',
|
||||
'^.+\\.js$': 'babel-jest',
|
||||
|
|
@ -13,20 +7,13 @@ module.exports = {
|
|||
'^.+\\.vue$': '@vue/vue3-jest',
|
||||
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
|
||||
},
|
||||
modulePaths: [
|
||||
'<rootDir>/src',
|
||||
'<rootDir>/node_modules',
|
||||
],
|
||||
transformIgnorePatterns: [
|
||||
'/node_modules/',
|
||||
],
|
||||
modulePaths: ['<rootDir>/src', '<rootDir>/node_modules'],
|
||||
transformIgnorePatterns: ['/node_modules/'],
|
||||
moduleNameMapper: {
|
||||
'^@/(.*)$': '<rootDir>/src/$1',
|
||||
'^gql/(.*)$': '<rootDir>/src/graphql/gql/$1',
|
||||
},
|
||||
snapshotSerializers: [
|
||||
'<rootDir>/node_modules/jest-serializer-vue',
|
||||
],
|
||||
snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
|
||||
testEnvironment: 'jsdom',
|
||||
testEnvironmentOptions: {
|
||||
url: 'http://localhost/',
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
"version": "1.0.0",
|
||||
"description": "skillbox vue client",
|
||||
"author": "ramon / chrigu",
|
||||
"prettier": {
|
||||
"singleQuote": true
|
||||
},
|
||||
"private": true,
|
||||
"prettier": {
|
||||
"singleQuote": true
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
<template>
|
||||
<div class="add-content">
|
||||
<a
|
||||
class="add-content__button"
|
||||
@click="addContent"
|
||||
>
|
||||
<a class="add-content__button" @click="addContent">
|
||||
<add-pointer class="add-content__icon" />
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -18,19 +15,20 @@
|
|||
|
||||
const AddPointer = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/AddPointer'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
where: {
|
||||
type: Object,
|
||||
validator(prop) {
|
||||
return Object.prototype.hasOwnProperty.call(prop, 'after' )
|
||||
|| Object.prototype.hasOwnProperty.call(prop, 'parent');
|
||||
}
|
||||
return (
|
||||
Object.prototype.hasOwnProperty.call(prop, 'after') || Object.prototype.hasOwnProperty.call(prop, 'parent')
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
AddPointer
|
||||
AddPointer,
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
|
@ -45,14 +43,13 @@
|
|||
},
|
||||
slug() {
|
||||
return this.$route.params.slug;
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
addContent() {
|
||||
if (this.isObjectiveGroup) {
|
||||
this.$modal.open('new-objective-wizard', {parent: this.parent.id});
|
||||
this.$modal.open('new-objective-wizard', { parent: this.parent.id });
|
||||
} else {
|
||||
let route;
|
||||
if (this.after && this.after.id) {
|
||||
|
|
@ -60,28 +57,28 @@
|
|||
name: CREATE_CONTENT_BLOCK_AFTER_PAGE,
|
||||
params: {
|
||||
after: this.after.id,
|
||||
slug: this.slug
|
||||
}
|
||||
slug: this.slug,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
route = {
|
||||
name: CREATE_CONTENT_BLOCK_UNDER_PARENT_PAGE,
|
||||
params: {
|
||||
parent: this.parent.id
|
||||
}
|
||||
parent: this.parent.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
this.$router.push(route);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.add-content {
|
||||
.add-content {
|
||||
display: none;
|
||||
position: relative;
|
||||
@include desktop {
|
||||
|
|
@ -101,5 +98,5 @@
|
|||
width: 40px;
|
||||
fill: $color-silver-dark;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
<template>
|
||||
<div
|
||||
class="add-content-element"
|
||||
@click="$emit('add-element', index)"
|
||||
>
|
||||
<div class="add-content-element" @click="$emit('add-element', index)">
|
||||
<add-icon class="add-content-element__icon" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -11,19 +8,19 @@
|
|||
import {defineAsyncComponent} from 'vue';
|
||||
const AddIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/AddIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: ['index'],
|
||||
|
||||
components: {
|
||||
AddIcon
|
||||
}
|
||||
};
|
||||
AddIcon,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import '@/styles/_variables.scss';
|
||||
|
||||
.add-content-element {
|
||||
.add-content-element {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
border-bottom: 2px solid $color-silver-dark;
|
||||
|
|
@ -38,5 +35,5 @@
|
|||
background-color: $color-white;
|
||||
border-radius: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -14,24 +14,25 @@
|
|||
import {defineAsyncComponent} from 'vue';
|
||||
const AddIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/AddIcon.vue'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
route: {
|
||||
type: String,
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
reverse: { // use reverse colors
|
||||
reverse: {
|
||||
// use reverse colors
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
click: {
|
||||
type: Function,
|
||||
default: null
|
||||
}
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
AddIcon
|
||||
AddIcon,
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
|
@ -40,19 +41,21 @@
|
|||
return this.route ? 'router-link' : 'a';
|
||||
},
|
||||
properties() {
|
||||
return this.route ? {
|
||||
return this.route
|
||||
? {
|
||||
to: this.route,
|
||||
tag: 'div'
|
||||
} : {};
|
||||
tag: 'div',
|
||||
}
|
||||
: {};
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.add-widget {
|
||||
.add-widget {
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
|
@ -75,5 +78,5 @@
|
|||
&--reverse &__add {
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
<template>
|
||||
<router-link
|
||||
:to="to"
|
||||
class="sub-navigation-item back-link"
|
||||
>
|
||||
<router-link :to="to" class="sub-navigation-item back-link">
|
||||
<chevron-left class="back-link__icon sub-navigation-item__icon" />
|
||||
{{ fullTitle }}
|
||||
</router-link>
|
||||
|
|
@ -16,7 +13,7 @@
|
|||
|
||||
const ChevronLeft = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/ChevronLeft'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
|
|
@ -68,9 +65,9 @@
|
|||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
@import '~styles/helpers';
|
||||
|
||||
.back-link {
|
||||
.back-link {
|
||||
@include regular-text;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,15 @@
|
|||
<template>
|
||||
<div class="color-chooser">
|
||||
<div
|
||||
:class="{'color-chooser__color-wrapper--selected': selectedColor === color.name}"
|
||||
:class="{ 'color-chooser__color-wrapper--selected': selectedColor === color.name }"
|
||||
class="color-chooser__color-wrapper"
|
||||
data-cy="color-select"
|
||||
v-for="(color, index) in colors"
|
||||
:key="index"
|
||||
@click="$emit('input', color.name)"
|
||||
>
|
||||
<div
|
||||
:class="'color-chooser__color--' + color.name"
|
||||
class="color-chooser__color"
|
||||
>
|
||||
<tick
|
||||
class="color-chooser__selected-icon"
|
||||
v-if="selectedColor === color.name"
|
||||
/>
|
||||
<div :class="'color-chooser__color--' + color.name" class="color-chooser__color">
|
||||
<tick class="color-chooser__selected-icon" v-if="selectedColor === color.name" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -25,39 +19,39 @@
|
|||
import {defineAsyncComponent} from 'vue';
|
||||
const Tick = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/Tick'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: ['selectedColor'],
|
||||
|
||||
components: {
|
||||
Tick
|
||||
Tick,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
colors: [
|
||||
{
|
||||
name: 'yellow'
|
||||
name: 'yellow',
|
||||
},
|
||||
{
|
||||
name: 'blue'
|
||||
name: 'blue',
|
||||
},
|
||||
{
|
||||
name: 'red'
|
||||
name: 'red',
|
||||
},
|
||||
{
|
||||
name: 'green'
|
||||
}
|
||||
]
|
||||
name: 'green',
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
@import '@/styles/_variables.scss';
|
||||
@import '@/styles/_mixins.scss';
|
||||
|
||||
.color-chooser {
|
||||
.color-chooser {
|
||||
display: flex;
|
||||
|
||||
&__color-wrapper {
|
||||
|
|
@ -82,12 +76,12 @@
|
|||
display: flex;
|
||||
justify-content: center;
|
||||
@supports (display: grid) {
|
||||
display: grid
|
||||
display: grid;
|
||||
}
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
|
||||
@include skillbox-colors;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,23 +1,24 @@
|
|||
<template>
|
||||
<modal :fullscreen="true">
|
||||
<component
|
||||
:value="value"
|
||||
:is="type"
|
||||
/>
|
||||
<component :value="value" :is="type" />
|
||||
</modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from '@/components/Modal';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const InfogramBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/InfogramBlock'));
|
||||
const GeniallyBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/GeniallyBlock'));
|
||||
import Modal from '@/components/Modal';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const InfogramBlock = defineAsyncComponent(() =>
|
||||
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/InfogramBlock')
|
||||
);
|
||||
const GeniallyBlock = defineAsyncComponent(() =>
|
||||
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/GeniallyBlock')
|
||||
);
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
Modal,
|
||||
InfogramBlock,
|
||||
GeniallyBlock
|
||||
GeniallyBlock,
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
|
@ -29,9 +30,9 @@
|
|||
},
|
||||
value() {
|
||||
return {
|
||||
id: this.id
|
||||
};
|
||||
}
|
||||
}
|
||||
id: this.id,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,44 +1,31 @@
|
|||
<template>
|
||||
<header class="header-bar">
|
||||
<a
|
||||
class="header-bar__sidebar-link"
|
||||
data-cy="open-sidebar-link"
|
||||
@click.stop="openSidebar('navigation')"
|
||||
>
|
||||
<a class="header-bar__sidebar-link" data-cy="open-sidebar-link" @click.stop="openSidebar('navigation')">
|
||||
<hamburger class="header-bar__sidebar-icon" />
|
||||
</a>
|
||||
<content-navigation class="header-bar__content-navigation" />
|
||||
<div class="user-header">
|
||||
<a
|
||||
class="user-header__sidebar-link"
|
||||
>
|
||||
<current-class
|
||||
class="user-header__current-class"
|
||||
@click="openSidebar('profile')"
|
||||
/>
|
||||
<a class="user-header__sidebar-link">
|
||||
<current-class class="user-header__current-class" @click="openSidebar('profile')" />
|
||||
</a>
|
||||
|
||||
<user-widget
|
||||
:avatar-url="me.avatarUrl"
|
||||
data-cy="header-user-widget"
|
||||
@click="openSidebar('profile')"
|
||||
/>
|
||||
<user-widget :avatar-url="me.avatarUrl" data-cy="header-user-widget" @click="openSidebar('profile')" />
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ContentNavigation from '@/components/book-navigation/ContentNavigation.vue';
|
||||
import UserWidget from '@/components/UserWidget.vue';
|
||||
import CurrentClass from '@/components/school-class/CurrentClass';
|
||||
import ContentNavigation from '@/components/book-navigation/ContentNavigation.vue';
|
||||
import UserWidget from '@/components/UserWidget.vue';
|
||||
import CurrentClass from '@/components/school-class/CurrentClass';
|
||||
|
||||
import openSidebar from '@/mixins/open-sidebar';
|
||||
import me from '@/mixins/me';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
import openSidebar from '@/mixins/open-sidebar';
|
||||
import me from '@/mixins/me';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
|
||||
const Hamburger = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/Hamburger'));
|
||||
const Hamburger = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/Hamburger'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
mixins: [openSidebar, me],
|
||||
|
||||
components: {
|
||||
|
|
@ -47,13 +34,13 @@
|
|||
CurrentClass,
|
||||
Hamburger,
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.header-bar {
|
||||
.header-bar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@supports (display: grid) {
|
||||
|
|
@ -119,9 +106,9 @@
|
|||
-ms-grid-column: 1;
|
||||
-ms-grid-column-span: 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user-header {
|
||||
.user-header {
|
||||
display: flex;
|
||||
|
||||
&__current-class {
|
||||
|
|
@ -136,5 +123,5 @@
|
|||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -10,23 +10,23 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const InfoIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/InfoIcon'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const InfoIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/InfoIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: ['text'],
|
||||
|
||||
components: {
|
||||
InfoIcon
|
||||
}
|
||||
};
|
||||
InfoIcon,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
@import '@/styles/_variables.scss';
|
||||
@import '@/styles/_mixins.scss';
|
||||
|
||||
.helpful-tooltip {
|
||||
.helpful-tooltip {
|
||||
position: relative;
|
||||
|
||||
&__icon {
|
||||
|
|
@ -66,11 +66,10 @@
|
|||
height: 10px;
|
||||
transform: rotate(-45deg) translateY(-50%);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&:hover &__tooltip {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,47 +1,43 @@
|
|||
<template>
|
||||
<button
|
||||
:disabled="loading || disabled"
|
||||
class="loading-button button button--primary button--big"
|
||||
>
|
||||
<button :disabled="loading || disabled" class="loading-button button button--primary button--big">
|
||||
<template v-if="!loading">
|
||||
{{ label }}
|
||||
</template>
|
||||
<loading-icon
|
||||
class="loading-button__icon"
|
||||
v-else
|
||||
/>
|
||||
<loading-icon class="loading-button__icon" v-else />
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const LoadingIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/LoadingIcon'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const LoadingIcon = defineAsyncComponent(() =>
|
||||
import(/* webpackChunkName: "icons" */ '@/components/icons/LoadingIcon')
|
||||
);
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
components: {
|
||||
LoadingIcon
|
||||
}
|
||||
};
|
||||
LoadingIcon,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.loading-button {
|
||||
.loading-button {
|
||||
height: 52px;
|
||||
min-width: 100px;
|
||||
display: inline-flex;
|
||||
|
|
@ -54,5 +50,5 @@
|
|||
@include spin;
|
||||
fill: $color-brand;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -4,31 +4,25 @@
|
|||
<hamburger class="mobile-header__hamburger" />
|
||||
</a>
|
||||
|
||||
<router-link
|
||||
to="/"
|
||||
data-cy="mobile-home-link"
|
||||
>
|
||||
<router-link to="/" data-cy="mobile-home-link">
|
||||
<logo />
|
||||
</router-link>
|
||||
|
||||
<user-widget
|
||||
v-bind="me"
|
||||
@click.stop="openSidebar('profile')"
|
||||
/>
|
||||
<user-widget v-bind="me" @click.stop="openSidebar('profile')" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UserWidget from '@/components/UserWidget';
|
||||
import UserWidget from '@/components/UserWidget';
|
||||
|
||||
import me from '@/mixins/me';
|
||||
import openSidebar from '@/mixins/open-sidebar';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
import me from '@/mixins/me';
|
||||
import openSidebar from '@/mixins/open-sidebar';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
|
||||
const Logo = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/Logo'));
|
||||
const Hamburger = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/Hamburger'));
|
||||
const Logo = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/Logo'));
|
||||
const Hamburger = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/Hamburger'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
mixins: [me, openSidebar],
|
||||
|
||||
components: {
|
||||
|
|
@ -42,13 +36,13 @@
|
|||
this.$store.dispatch('showMobileNavigation', true);
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.mobile-header {
|
||||
.mobile-header {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
|
|
@ -65,5 +59,5 @@
|
|||
height: 30px;
|
||||
fill: $color-silver-dark;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
<template>
|
||||
<div class="modal__backdrop">
|
||||
<div
|
||||
:class="{'modal--hide-header': hideHeader || fullscreen, 'modal--fullscreen': fullscreen, 'modal--small': small}"
|
||||
:class="{
|
||||
'modal--hide-header': hideHeader || fullscreen,
|
||||
'modal--fullscreen': fullscreen,
|
||||
'modal--small': small,
|
||||
}"
|
||||
class="modal"
|
||||
>
|
||||
<div class="modal__header">
|
||||
|
|
@ -9,20 +13,14 @@
|
|||
</div>
|
||||
<div class="modal__body">
|
||||
<slot />
|
||||
<div
|
||||
class="modal__close-button"
|
||||
@click="hideModal"
|
||||
>
|
||||
<div class="modal__close-button" @click="hideModal">
|
||||
<cross class="modal__close-icon" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal__footer">
|
||||
<slot name="footer">
|
||||
<!--<a class="button button--active">Speichern</a>-->
|
||||
<a
|
||||
class="button"
|
||||
@click="hideModal"
|
||||
>Abbrechen</a>
|
||||
<a class="button" @click="hideModal">Abbrechen</a>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -30,41 +28,41 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const Cross = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/CrossIcon'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const Cross = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/CrossIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
hideHeader: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
fullscreen: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
small: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
Cross
|
||||
Cross,
|
||||
},
|
||||
|
||||
methods: {
|
||||
hideModal() {
|
||||
this.$store.dispatch('hideModal');
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import '@/styles/_variables.scss';
|
||||
|
||||
.modal {
|
||||
.modal {
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
width: 700px;
|
||||
|
|
@ -78,7 +76,7 @@
|
|||
display: grid;
|
||||
}
|
||||
grid-template-rows: auto 1fr 65px;
|
||||
grid-template-areas: "header" "body" "footer";
|
||||
grid-template-areas: 'header' 'body' 'footer';
|
||||
-ms-grid-rows: auto 1fr 65px;
|
||||
position: relative;
|
||||
|
||||
|
|
@ -136,7 +134,7 @@
|
|||
|
||||
&--hide-header {
|
||||
grid-template-rows: 1fr 65px;
|
||||
grid-template-areas: "body" "footer";
|
||||
grid-template-areas: 'body' 'footer';
|
||||
|
||||
#{$parent}__header {
|
||||
display: none;
|
||||
|
|
@ -145,7 +143,6 @@
|
|||
#{$parent}__body {
|
||||
padding: $default-padding;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&--fullscreen {
|
||||
|
|
@ -153,7 +150,7 @@
|
|||
height: auto;
|
||||
grid-template-rows: 1fr;
|
||||
-ms-grid-rows: 1fr;
|
||||
grid-template-areas: "body";
|
||||
grid-template-areas: 'body';
|
||||
overflow: hidden;
|
||||
|
||||
#{$parent}__footer {
|
||||
|
|
@ -185,5 +182,5 @@
|
|||
min-height: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,46 +1,38 @@
|
|||
<template>
|
||||
<div class="more-options">
|
||||
<a
|
||||
class="more-options__more-link"
|
||||
data-cy="more-options-link"
|
||||
@click.stop="showMenu = !showMenu"
|
||||
>
|
||||
<a class="more-options__more-link" data-cy="more-options-link" @click.stop="showMenu = !showMenu">
|
||||
<ellipses class="more-options__ellipses" />
|
||||
</a>
|
||||
<widget-popover
|
||||
class="more-options__popover"
|
||||
v-if="showMenu"
|
||||
@hide-me="showMenu = false"
|
||||
>
|
||||
<widget-popover class="more-options__popover" v-if="showMenu" @hide-me="showMenu = false">
|
||||
<slot />
|
||||
</widget-popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WidgetPopover from '@/components/ui/WidgetPopover';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
import WidgetPopover from '@/components/ui/WidgetPopover';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
|
||||
const Ellipses = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/Ellipses.vue'));
|
||||
const Ellipses = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/Ellipses.vue'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
WidgetPopover,
|
||||
Ellipses
|
||||
Ellipses,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
showMenu: false
|
||||
};
|
||||
}
|
||||
showMenu: false,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.more-options {
|
||||
.more-options {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
|
|
@ -64,5 +56,5 @@
|
|||
min-width: 200px;
|
||||
@include popover-defaults();
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,27 +1,23 @@
|
|||
<template>
|
||||
<transition name="fade">
|
||||
<a
|
||||
class="scroll-up"
|
||||
v-if="scroll>200"
|
||||
@click="scrollTop"
|
||||
>
|
||||
<a class="scroll-up" v-if="scroll > 200" @click="scrollTop">
|
||||
<arrow-up class="scroll-up__icon" />
|
||||
</a>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const ArrowUp = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/ArrowUp'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const ArrowUp = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/ArrowUp'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
ArrowUp
|
||||
ArrowUp,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
scroll: 0
|
||||
scroll: 0,
|
||||
};
|
||||
},
|
||||
|
||||
|
|
@ -39,16 +35,16 @@
|
|||
methods: {
|
||||
scrollTop() {
|
||||
document.scrollingElement.scrollTop = 0;
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@/styles/_variables.scss';
|
||||
@import '@/styles/_mixins.scss';
|
||||
@import '@/styles/_variables.scss';
|
||||
@import '@/styles/_mixins.scss';
|
||||
|
||||
.scroll-up {
|
||||
.scroll-up {
|
||||
position: fixed;
|
||||
right: $large-spacing;
|
||||
bottom: $large-spacing;
|
||||
|
|
@ -65,15 +61,14 @@
|
|||
height: 50px;
|
||||
fill: $color-brand;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.fade-enter-active, .fade-leave-active {
|
||||
transition: opacity .3s;
|
||||
}
|
||||
|
||||
.fade-enter-from, .fade-leave-to /* .fade-leave-active below version 2.1.8 */
|
||||
{
|
||||
.fade-enter-from, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
<template>
|
||||
<div class="submission-document">
|
||||
<p
|
||||
class="submission-document__content content"
|
||||
v-if="document && document.length > 0"
|
||||
>
|
||||
<p class="submission-document__content content" v-if="document && document.length > 0">
|
||||
<document-icon class="content__icon" /><span class="content__text">{{ filename }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
import filenameFromUrl from '@/helpers/urls';
|
||||
const DocumentIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/DocumentIcon'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
import filenameFromUrl from '@/helpers/urls';
|
||||
const DocumentIcon = defineAsyncComponent(() =>
|
||||
import(/* webpackChunkName: "icons" */ '@/components/icons/DocumentIcon')
|
||||
);
|
||||
|
||||
export default {
|
||||
export default {
|
||||
name: 'StudentSubmissionDocument',
|
||||
props: ['document'],
|
||||
components: { DocumentIcon },
|
||||
|
|
@ -22,13 +21,13 @@
|
|||
computed: {
|
||||
filename() {
|
||||
return filenameFromUrl(this.document);
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
.content {
|
||||
display: flex;
|
||||
|
||||
&__icon {
|
||||
|
|
@ -40,5 +39,5 @@
|
|||
align-self: center;
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,48 +1,38 @@
|
|||
<template>
|
||||
<div
|
||||
:class="{'user-widget--is-profile': isProfile}"
|
||||
class="user-widget"
|
||||
@click.stop="$emit('click', $event)"
|
||||
>
|
||||
<div
|
||||
class="user-widget__avatar"
|
||||
data-cy="user-widget-avatar"
|
||||
>
|
||||
<avatar
|
||||
:avatar-url="avatarUrl"
|
||||
:icon-highlighted="isProfile"
|
||||
/>
|
||||
<div :class="{ 'user-widget--is-profile': isProfile }" class="user-widget" @click.stop="$emit('click', $event)">
|
||||
<div class="user-widget__avatar" data-cy="user-widget-avatar">
|
||||
<avatar :avatar-url="avatarUrl" :icon-highlighted="isProfile" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Avatar from '@/components/profile/Avatar';
|
||||
import Avatar from '@/components/profile/Avatar';
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
avatarUrl: {
|
||||
type: String
|
||||
}
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
|
||||
emits: ['click'],
|
||||
|
||||
components: {
|
||||
Avatar
|
||||
emits: ['click'],components: {
|
||||
Avatar,
|
||||
},
|
||||
computed: {
|
||||
isProfile() {
|
||||
return this.$route.meta.isProfile;
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.user-widget {
|
||||
.user-widget {
|
||||
color: $color-silver-dark;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
|
@ -78,5 +68,5 @@
|
|||
color: $color-brand;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
<template>
|
||||
<nav
|
||||
:class="{'content-navigation--sidebar': isSidebar}"
|
||||
class="content-navigation"
|
||||
>
|
||||
<nav :class="{ 'content-navigation--sidebar': isSidebar }" class="content-navigation">
|
||||
<div class="content-navigation__primary">
|
||||
<div class="content-navigation__item">
|
||||
<router-link
|
||||
:class="{'content-navigation__link--active': isActive('book')}"
|
||||
:class="{ 'content-navigation__link--active': isActive('book') }"
|
||||
:to="topicRoute"
|
||||
active-class="content-navigation__link--active"
|
||||
class="content-navigation__link"
|
||||
|
|
@ -15,9 +12,7 @@
|
|||
{{ $flavor.textTopics }}
|
||||
</router-link>
|
||||
|
||||
<topic-navigation
|
||||
v-if="isSidebar"
|
||||
/>
|
||||
<topic-navigation v-if="isSidebar" />
|
||||
</div>
|
||||
|
||||
<div class="content-navigation__item">
|
||||
|
|
@ -33,7 +28,7 @@
|
|||
|
||||
<div class="content-navigation__item">
|
||||
<router-link
|
||||
:to="{name: 'news'}"
|
||||
:to="{ name: 'news' }"
|
||||
active-class="content-navigation__link--active"
|
||||
class="content-navigation__link"
|
||||
data-cy="news-navigation-link"
|
||||
|
|
@ -45,19 +40,14 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<router-link
|
||||
to="/"
|
||||
class="content-navigation__logo"
|
||||
data-cy="home-link"
|
||||
v-if="!isSidebar"
|
||||
>
|
||||
<router-link to="/" class="content-navigation__logo" data-cy="home-link" v-if="!isSidebar">
|
||||
<logo class="content-navigation__logo-icon" />
|
||||
</router-link>
|
||||
|
||||
<div class="content-navigation__secondary">
|
||||
<div class="content-navigation__item content-navigation__item--secondary">
|
||||
<router-link
|
||||
:class="{'content-navigation__link--active': isRoomUrl()}"
|
||||
:class="{ 'content-navigation__link--active': isRoomUrl() }"
|
||||
to="/rooms"
|
||||
active-class="content-navigation__link--active"
|
||||
class="content-navigation__link content-navigation__link--secondary"
|
||||
|
|
@ -67,10 +57,7 @@
|
|||
</router-link>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="content-navigation__item content-navigation__item--secondary"
|
||||
v-if="showPortfolio"
|
||||
>
|
||||
<div class="content-navigation__item content-navigation__item--secondary" v-if="showPortfolio">
|
||||
<router-link
|
||||
to="/portfolio"
|
||||
active-class="content-navigation__link--active"
|
||||
|
|
@ -80,10 +67,7 @@
|
|||
Portfolio
|
||||
</router-link>
|
||||
</div>
|
||||
<div
|
||||
class="content-navigation__item content-navigation__item--secondary"
|
||||
v-if="isSidebar"
|
||||
>
|
||||
<div class="content-navigation__item content-navigation__item--secondary" v-if="isSidebar">
|
||||
<a
|
||||
:href="$flavor.supportLink"
|
||||
target="_blank"
|
||||
|
|
@ -97,7 +81,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import TopicNavigation from '@/components/book-navigation/TopicNavigation';
|
||||
import TopicNavigation from '@/components/book-navigation/TopicNavigation';
|
||||
|
||||
import sidebarMixin from '@/mixins/sidebar';
|
||||
import meMixin from '@/mixins/me';
|
||||
|
|
@ -105,24 +89,24 @@
|
|||
|
||||
const Logo = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/Logo'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
isSidebar: {
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
mixins: [sidebarMixin, meMixin],
|
||||
|
||||
components: {
|
||||
TopicNavigation,
|
||||
Logo
|
||||
Logo,
|
||||
},
|
||||
|
||||
computed: {
|
||||
showPortfolio() {
|
||||
return this.$flavor.showPortfolio;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
@ -134,16 +118,16 @@
|
|||
},
|
||||
close() {
|
||||
this.closeSidebar('navigation');
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
@import '@/styles/_variables.scss';
|
||||
@import '@/styles/_mixins.scss';
|
||||
|
||||
.content-navigation {
|
||||
.content-navigation {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
|
|
@ -152,7 +136,8 @@
|
|||
@include navigation-link;
|
||||
}
|
||||
|
||||
&__primary, &__secondary {
|
||||
&__primary,
|
||||
&__secondary {
|
||||
display: none;
|
||||
flex-direction: row;
|
||||
|
||||
|
|
@ -162,7 +147,7 @@
|
|||
}
|
||||
|
||||
&__logo {
|
||||
color: #17A887;
|
||||
color: #17a887;
|
||||
font-size: 36px;
|
||||
font-weight: 800;
|
||||
font-family: $sans-serif-font-family;
|
||||
|
|
@ -197,7 +182,8 @@
|
|||
&--sidebar {
|
||||
flex-direction: column;
|
||||
|
||||
#{$parent}__primary, #{$parent}__secondary {
|
||||
#{$parent}__primary,
|
||||
#{$parent}__secondary {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
|
|
@ -208,12 +194,11 @@
|
|||
line-height: 2.5em;
|
||||
padding: 0;
|
||||
display: block;
|
||||
margin-bottom: 0.5*$small-spacing;
|
||||
margin-bottom: 0.5 * $small-spacing;
|
||||
|
||||
&:only-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#{$parent}__item {
|
||||
|
|
@ -234,5 +219,5 @@
|
|||
/*}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,8 @@
|
|||
<template>
|
||||
<transition name="slide">
|
||||
<div
|
||||
class="navigation-sidebar"
|
||||
v-if="sidebar.navigation"
|
||||
v-click-outside="close"
|
||||
>
|
||||
<content-navigation
|
||||
:is-sidebar="true"
|
||||
class="navigation-sidebar__main"
|
||||
/>
|
||||
<div
|
||||
class="navigation-sidebar__close-button"
|
||||
@click="close"
|
||||
>
|
||||
<div class="navigation-sidebar" v-if="sidebar.navigation" v-click-outside="close">
|
||||
<content-navigation :is-sidebar="true" class="navigation-sidebar__main" />
|
||||
<div class="navigation-sidebar__close-button" @click="close">
|
||||
<cross class="navigation-sidebar__close-icon" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -20,37 +10,36 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import ContentNavigation from '@/components/book-navigation/ContentNavigation';
|
||||
import ContentNavigation from '@/components/book-navigation/ContentNavigation';
|
||||
|
||||
import sidebarMixin from '@/mixins/sidebar';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
import sidebarMixin from '@/mixins/sidebar';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
|
||||
const Cross = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/CrossIcon'));
|
||||
const Cross = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/CrossIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
mixins: [sidebarMixin],
|
||||
|
||||
components: {
|
||||
ContentNavigation,
|
||||
Cross
|
||||
Cross,
|
||||
},
|
||||
|
||||
methods: {
|
||||
close() {
|
||||
this.closeSidebar('navigation');
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
@import '@/styles/_variables.scss';
|
||||
@import '@/styles/_mixins.scss';
|
||||
|
||||
$desktop-width: 285px;
|
||||
$desktop-width: 285px;
|
||||
|
||||
.navigation-sidebar {
|
||||
.navigation-sidebar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
|
@ -68,10 +57,10 @@
|
|||
grid-template-columns: 1fr 50px;
|
||||
grid-template-rows: 50px max-content auto 100px;
|
||||
|
||||
grid-template-areas: "m m" "m m" "s s" "s s";
|
||||
grid-template-areas: 'm m' 'm m' 's s' 's s';
|
||||
|
||||
&--with-subnavigation {
|
||||
grid-template-areas: "m m" "m m" "sub sub" "s s";
|
||||
grid-template-areas: 'm m' 'm m' 'sub sub' 's s';
|
||||
}
|
||||
|
||||
height: 100vh;
|
||||
|
|
@ -96,18 +85,20 @@
|
|||
justify-self: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.slide {
|
||||
&-enter-active, &-leave-active {
|
||||
.slide {
|
||||
&-enter-active,
|
||||
&-leave-active {
|
||||
transition: left 0.2s;
|
||||
}
|
||||
|
||||
&-enter-from, &-leave-to {
|
||||
&-enter-from,
|
||||
&-leave-to {
|
||||
left: -100vw;
|
||||
@include desktop {
|
||||
left: -$desktop-width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,11 @@
|
|||
<template>
|
||||
<div
|
||||
:class="{ 'sub-navigation-item--active': show}"
|
||||
class="sub-navigation-item"
|
||||
v-click-outside="close"
|
||||
>
|
||||
<div
|
||||
class="sub-navigation-item__title"
|
||||
@click="show = !show"
|
||||
>
|
||||
<div :class="{ 'sub-navigation-item--active': show }" class="sub-navigation-item" 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-up class="sub-navigation-item__icon sub-navigation-item__chevron-up" />
|
||||
</div>
|
||||
<div
|
||||
class="sub-navigation-item__nav-items book-subnavigation"
|
||||
v-if="show"
|
||||
>
|
||||
<div class="sub-navigation-item__nav-items book-subnavigation" v-if="show">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -26,30 +16,30 @@
|
|||
const ChevronDown = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/ChevronDown'));
|
||||
const ChevronUp = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/ChevronUp'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: ['title'],
|
||||
|
||||
components: {
|
||||
ChevronDown,
|
||||
ChevronUp
|
||||
ChevronUp,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
show: false
|
||||
show: false,
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
$route() {
|
||||
this.show = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
close() {
|
||||
this.show = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<nav class="topic-navigation">
|
||||
<router-link
|
||||
:to="{name: 'topic', params: {topicSlug: topic.slug}}"
|
||||
:class="{'topic-navigation__topic--active': topic.active, 'book-subnavigation__item--mobile': mobile}"
|
||||
:to="{ name: 'topic', params: { topicSlug: topic.slug } }"
|
||||
:class="{ 'topic-navigation__topic--active': topic.active, 'book-subnavigation__item--mobile': mobile }"
|
||||
tag="div"
|
||||
active-class="book-subnavigation__item--active"
|
||||
class="topic-navigation__topic book-subnavigation__item"
|
||||
|
|
@ -17,8 +17,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import ALL_TOPICS_QUERY from '@/graphql/gql/queries/allTopicsQuery.gql';
|
||||
import sidebarMixin from '@/mixins/sidebar';
|
||||
import ALL_TOPICS_QUERY from '@/graphql/gql/queries/allTopicsQuery.gql';
|
||||
import sidebarMixin from '@/mixins/sidebar';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
default: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
mixins: [sidebarMixin],
|
||||
|
||||
|
|
@ -40,26 +41,27 @@
|
|||
return atob(id);
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
apollo: {
|
||||
topics: {
|
||||
query: ALL_TOPICS_QUERY,
|
||||
manual: true,
|
||||
result({data, loading}) {
|
||||
result({ data, loading }) {
|
||||
if (!loading) {
|
||||
this.topics = this.$getRidOfEdges(data).topics;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
|
||||
.topic-navigation {
|
||||
.topic-navigation {
|
||||
&__topic {
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -26,14 +26,10 @@
|
|||
:class="['content-element__component']"
|
||||
v-bind="element"
|
||||
:is="component"
|
||||
|
||||
@change-text="changeText"
|
||||
|
||||
@link-change-url="changeUrl"
|
||||
@change-url="changeUrl"
|
||||
|
||||
@switch-to-document="switchToDocument"
|
||||
|
||||
@assignment-change-title="changeAssignmentTitle"
|
||||
@assignment-change-assignment="changeAssignmentAssignment"
|
||||
/>
|
||||
|
|
@ -67,9 +63,9 @@
|
|||
const ThinglinkBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-forms" */'@/components/content-blocks/ThinglinkBlock'));
|
||||
const InfogramBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-forms" */'@/components/content-blocks/InfogramBlock'));
|
||||
|
||||
const CHOOSER = 'content-block-element-chooser-widget';
|
||||
const CHOOSER = 'content-block-element-chooser-widget';
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
element: {
|
||||
type: Object,
|
||||
|
|
@ -110,7 +106,7 @@
|
|||
CmsDocumentBlock,
|
||||
InfogramBlock,
|
||||
ThinglinkBlock,
|
||||
Assignment
|
||||
Assignment,
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
|
@ -216,12 +212,12 @@
|
|||
case 'thinglink_block':
|
||||
return {
|
||||
component: 'thinglink-block',
|
||||
title: 'Interaktive Grafik'
|
||||
title: 'Interaktive Grafik',
|
||||
};
|
||||
case 'infogram_block':
|
||||
return {
|
||||
component: 'infogram-block',
|
||||
title: 'Interaktive Grafik'
|
||||
title: 'Interaktive Grafik',
|
||||
};
|
||||
}
|
||||
return {
|
||||
|
|
@ -253,7 +249,7 @@
|
|||
changeAssignmentAssignment(value) {
|
||||
this._updateProperty(value, 'assignment');
|
||||
},
|
||||
changeType({type, convertToList}, value) {
|
||||
changeType({ type, convertToList }, value) {
|
||||
let el = {
|
||||
type: type,
|
||||
value: Object.assign({}, value),
|
||||
|
|
@ -295,9 +291,12 @@
|
|||
case 'document_block':
|
||||
el = {
|
||||
...el,
|
||||
value: Object.assign({
|
||||
value: Object.assign(
|
||||
{
|
||||
url: '',
|
||||
}, value),
|
||||
},
|
||||
value
|
||||
),
|
||||
};
|
||||
break;
|
||||
case 'image_url_block':
|
||||
|
|
@ -325,13 +324,13 @@
|
|||
this.changeType('document_block', value);
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
@import '~styles/helpers';
|
||||
|
||||
.content-element {
|
||||
.content-element {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
|
|
@ -351,5 +350,5 @@
|
|||
&__chooser {
|
||||
grid-column: 1 / span 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,8 @@
|
|||
<template>
|
||||
<div class="content-form-section">
|
||||
<h2 class="content-form-section__heading">
|
||||
<component
|
||||
class="content-form-section__icon"
|
||||
:is="icon"
|
||||
/> <span
|
||||
class="content-form-section__title"
|
||||
data-cy="content-form-section-title"
|
||||
>{{ title }}</span>
|
||||
<component class="content-form-section__icon" :is="icon" />
|
||||
<span class="content-form-section__title" data-cy="content-form-section-title">{{ title }}</span>
|
||||
</h2>
|
||||
|
||||
<content-element-actions
|
||||
|
|
@ -55,9 +50,9 @@
|
|||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
@import '~styles/helpers';
|
||||
|
||||
.content-form-section {
|
||||
.content-form-section {
|
||||
@include default-box-shadow;
|
||||
border-radius: $default-border-radius;
|
||||
padding: $small-spacing $medium-spacing;
|
||||
|
|
@ -96,5 +91,5 @@
|
|||
&__content {
|
||||
grid-area: c;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -18,41 +18,23 @@
|
|||
/>
|
||||
</template>
|
||||
|
||||
<add-content-element
|
||||
:index="-1"
|
||||
class="contents-form__add"
|
||||
@add-element="addElement"
|
||||
/>
|
||||
<div
|
||||
class="contents-form__element"
|
||||
v-for="(element, index) in localContentBlock.contents"
|
||||
:key="index"
|
||||
>
|
||||
<content-element
|
||||
:element="element"
|
||||
@update="update(index, $event)"
|
||||
@remove="remove(index)"
|
||||
/>
|
||||
<add-content-element :index="-1" class="contents-form__add" @add-element="addElement" />
|
||||
<div class="contents-form__element" v-for="(element, index) in localContentBlock.contents" :key="index">
|
||||
<content-element :element="element" @update="update(index, $event)" @remove="remove(index)" />
|
||||
|
||||
<add-content-element
|
||||
:index="index"
|
||||
class="contents-form__add"
|
||||
@add-element="addElement"
|
||||
/>
|
||||
<add-content-element :index="index" class="contents-form__add" @add-element="addElement" />
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<div>
|
||||
<a
|
||||
:class="{'button--disabled': disableSave}"
|
||||
:class="{ 'button--disabled': disableSave }"
|
||||
class="button button--primary"
|
||||
data-cy="modal-save-button"
|
||||
@click="save"
|
||||
>Speichern</a>
|
||||
<a
|
||||
class="button"
|
||||
@click="$emit('hide')"
|
||||
>Abbrechen</a>
|
||||
>Speichern</a
|
||||
>
|
||||
<a class="button" @click="$emit('hide')">Abbrechen</a>
|
||||
</div>
|
||||
</template>
|
||||
</modal>
|
||||
|
|
@ -69,7 +51,7 @@
|
|||
const Modal = defineAsyncComponent(() => import('@/components/Modal'));
|
||||
const Checkbox = defineAsyncComponent(() => import('@/components/ui/Checkbox'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
contentBlock: Object,
|
||||
blockType: {
|
||||
|
|
@ -97,12 +79,15 @@
|
|||
data() {
|
||||
return {
|
||||
error: false,
|
||||
localContentBlock: Object.assign({}, {
|
||||
localContentBlock: Object.assign(
|
||||
{},
|
||||
{
|
||||
title: this.contentBlock.title,
|
||||
contents: [...this.contentBlock.contents],
|
||||
id: this.contentBlock.id || undefined,
|
||||
isAssignment: this.contentBlock.type && this.contentBlock.type.toLowerCase() === 'task',
|
||||
}),
|
||||
}
|
||||
),
|
||||
me: {},
|
||||
};
|
||||
},
|
||||
|
|
@ -148,19 +133,17 @@
|
|||
remove(index) {
|
||||
this.localContentBlock.contents.splice(index, 1);
|
||||
},
|
||||
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.contents-form {
|
||||
.contents-form {
|
||||
/* top level does not exist, because of the modal */
|
||||
|
||||
&__element {
|
||||
|
||||
}
|
||||
|
||||
&__element-component {
|
||||
|
|
@ -180,5 +163,5 @@
|
|||
&__task {
|
||||
margin: 15px 0 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,9 @@
|
|||
<template>
|
||||
<contents-form
|
||||
:content-block="contentBlock"
|
||||
:show-task-selection="true"
|
||||
@save="saveContentBlock"
|
||||
@hide="hideModal"
|
||||
/>
|
||||
<contents-form :content-block="contentBlock" :show-task-selection="true" @save="saveContentBlock" @hide="hideModal" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ContentsForm from '@/components/content-block-form/ContentsForm';
|
||||
import ContentsForm from '@/components/content-block-form/ContentsForm';
|
||||
|
||||
import {store} from '@/store';
|
||||
|
||||
|
|
@ -38,7 +33,8 @@
|
|||
this.$store.dispatch('hideModal');
|
||||
},
|
||||
saveContentBlock(contentBlock) {
|
||||
this.$apollo.mutate({
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: EDIT_CONTENT_BLOCK_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
|
|
@ -61,6 +57,7 @@
|
|||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
apollo: {
|
||||
contentBlock() {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
<template>
|
||||
<div
|
||||
:class="componentClass"
|
||||
:data-scrollto="component.id"
|
||||
data-cy="content-component"
|
||||
>
|
||||
<div :class="componentClass" :data-scrollto="component.id" data-cy="content-component">
|
||||
<bookmark-actions
|
||||
:bookmarked="bookmarked"
|
||||
:note="note"
|
||||
|
|
@ -13,11 +9,7 @@
|
|||
@edit-note="editNote"
|
||||
@bookmark="bookmarkContent(component.id, !bookmarked)"
|
||||
/>
|
||||
<component
|
||||
v-bind="component"
|
||||
:parent="parent"
|
||||
:is="component.type"
|
||||
/>
|
||||
<component v-bind="component" :parent="parent" :is="component.type" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -50,60 +42,60 @@ export default {
|
|||
props: {
|
||||
component: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
default: () => ({}),
|
||||
},
|
||||
parent: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
default: () => ({}),
|
||||
},
|
||||
bookmarks: {
|
||||
type: Array,
|
||||
default: () => ([])
|
||||
default: () => [],
|
||||
},
|
||||
notes: {
|
||||
type: Array,
|
||||
default: () => ([])
|
||||
default: () => [],
|
||||
},
|
||||
root: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
'text_block': TextBlock,
|
||||
'basic_knowledge': InstrumentWidget, // for legacy
|
||||
'instrument': InstrumentWidget,
|
||||
'image_block': ImageBlock,
|
||||
'image_url_block': ImageUrlBlock,
|
||||
'video_block': VideoBlock,
|
||||
'link_block': LinkBlock,
|
||||
'document_block': DocumentBlock,
|
||||
'infogram_block': InfogramBlock,
|
||||
'genially_block': GeniallyBlock,
|
||||
'subtitle': SubtitleBlock,
|
||||
'section_title': SectionTitleBlock,
|
||||
'content_list': ContentListBlock,
|
||||
'module_room_slug': ModuleRoomSlug,
|
||||
'thinglink_block': ThinglinkBlock,
|
||||
'cms_document_block': CmsDocumentBlock,
|
||||
text_block: TextBlock,
|
||||
basic_knowledge: InstrumentWidget, // for legacy
|
||||
instrument: InstrumentWidget,
|
||||
image_block: ImageBlock,
|
||||
image_url_block: ImageUrlBlock,
|
||||
video_block: VideoBlock,
|
||||
link_block: LinkBlock,
|
||||
document_block: DocumentBlock,
|
||||
infogram_block: InfogramBlock,
|
||||
genially_block: GeniallyBlock,
|
||||
subtitle: SubtitleBlock,
|
||||
section_title: SectionTitleBlock,
|
||||
content_list: ContentListBlock,
|
||||
module_room_slug: ModuleRoomSlug,
|
||||
thinglink_block: ThinglinkBlock,
|
||||
cms_document_block: CmsDocumentBlock,
|
||||
Survey,
|
||||
Solution,
|
||||
Instruction,
|
||||
Assignment,
|
||||
BookmarkActions
|
||||
BookmarkActions,
|
||||
},
|
||||
|
||||
computed: {
|
||||
bookmarked() {
|
||||
return this.bookmarks && !!this.bookmarks.find(bookmark => bookmark.uuid === this.component.id);
|
||||
return this.bookmarks && !!this.bookmarks.find((bookmark) => bookmark.uuid === this.component.id);
|
||||
},
|
||||
note() {
|
||||
const bookmark = this.bookmarks && this.bookmarks.find(bookmark => bookmark.uuid === this.component.id);
|
||||
const bookmark = this.bookmarks && this.bookmarks.find((bookmark) => bookmark.uuid === this.component.id);
|
||||
return bookmark && bookmark.note;
|
||||
},
|
||||
showBookmarkActions() {
|
||||
|
|
@ -115,18 +107,19 @@ export default {
|
|||
classes.push('content-component--bookmarked');
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
addNote(id) {
|
||||
const type = Object.prototype.hasOwnProperty.call(this.parent, '__typename')
|
||||
? this.parent.__typename : 'ContentBlockNode';
|
||||
? this.parent.__typename
|
||||
: 'ContentBlockNode';
|
||||
|
||||
this.$store.dispatch('addNote', {
|
||||
content: id,
|
||||
type,
|
||||
block: this.root
|
||||
block: this.root,
|
||||
});
|
||||
},
|
||||
editNote() {
|
||||
|
|
@ -134,19 +127,18 @@ export default {
|
|||
},
|
||||
bookmarkContent(uuid, bookmarked) {
|
||||
this.$apollo.mutate(constructContentComponentBookmarkMutation(uuid, bookmarked, this.parent, this.root));
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.content-component {
|
||||
.content-component {
|
||||
position: relative;
|
||||
|
||||
&--bookmarked {
|
||||
|
||||
}
|
||||
|
||||
&--subtitle {
|
||||
|
|
@ -166,5 +158,5 @@ export default {
|
|||
&--document_block {
|
||||
margin-bottom: $large-spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,7 @@
|
|||
<template>
|
||||
<content-list
|
||||
:items="contentBlocks"
|
||||
>
|
||||
<content-list :items="contentBlocks">
|
||||
<template #default="{ item }">
|
||||
<content-block
|
||||
:content-block="item"
|
||||
:parent="parent"
|
||||
/>
|
||||
<content-block :content-block="item" :parent="parent" />
|
||||
</template>
|
||||
</content-list>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,8 @@
|
|||
<template>
|
||||
<div class="document-block">
|
||||
<document-icon class="document-block__icon" />
|
||||
<a
|
||||
:href="value.url"
|
||||
class="document-block__link"
|
||||
target="_blank"
|
||||
>{{ urlName }}</a>
|
||||
<a
|
||||
class="document-block__remove"
|
||||
v-if="showTrashIcon"
|
||||
@click="$emit('trash')"
|
||||
>
|
||||
<a :href="value.url" class="document-block__link" target="_blank">{{ urlName }}</a>
|
||||
<a class="document-block__remove" v-if="showTrashIcon" @click="$emit('trash')">
|
||||
<trash-icon class="document-block__trash-icon" />
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -21,7 +13,7 @@
|
|||
const DocumentIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/DocumentIcon'));
|
||||
const TrashIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/TrashIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
value: Object,
|
||||
showTrashIcon: Boolean,
|
||||
|
|
@ -33,21 +25,21 @@
|
|||
},
|
||||
|
||||
computed: {
|
||||
urlName: function() {
|
||||
urlName: function () {
|
||||
if (this.value && this.value.url) {
|
||||
const parts = this.value.url.split('/');
|
||||
return parts[parts.length - 1];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.document-block {
|
||||
.document-block {
|
||||
display: grid;
|
||||
grid-template-columns: 50px 1fr 50px;
|
||||
align-items: center;
|
||||
|
|
@ -76,5 +68,5 @@
|
|||
cursor: pointer;
|
||||
justify-self: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,28 +1,22 @@
|
|||
<template>
|
||||
<div
|
||||
class="instruction"
|
||||
v-if="me.isTeacher"
|
||||
>
|
||||
<div class="instruction" v-if="me.isTeacher">
|
||||
<bulb-icon class="instruction__icon" />
|
||||
<a
|
||||
:href="url"
|
||||
class="instruction__link"
|
||||
>{{ text }}</a>
|
||||
<a :href="url" class="instruction__link">{{ text }}</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import me from '@/mixins/me';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const BulbIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/BulbIcon'));
|
||||
import me from '@/mixins/me';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const BulbIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/BulbIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: ['value'],
|
||||
|
||||
mixins: [me],
|
||||
|
||||
components: {
|
||||
BulbIcon
|
||||
BulbIcon,
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
|
@ -31,15 +25,15 @@
|
|||
},
|
||||
url() {
|
||||
return this.value.document ? this.value.document.url : this.value.url;
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_mixins.scss";
|
||||
@import '@/styles/_mixins.scss';
|
||||
|
||||
.instruction {
|
||||
.instruction {
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -53,5 +47,5 @@
|
|||
&__link {
|
||||
@include heading-3;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,44 +1,37 @@
|
|||
<template>
|
||||
<div
|
||||
:class="{ 'link-block--no-margin': noMargin}"
|
||||
class="link-block"
|
||||
>
|
||||
<div :class="{ 'link-block--no-margin': noMargin }" class="link-block">
|
||||
<link-icon class="link-block__icon" />
|
||||
<a
|
||||
:href="href"
|
||||
class="link-block__link"
|
||||
target="_blank"
|
||||
>{{ value.text }}</a>
|
||||
<a :href="href" class="link-block__link" target="_blank">{{ value.text }}</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const LinkIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/LinkIcon'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const LinkIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/LinkIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
value: Object,
|
||||
noMargin: {
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
LinkIcon
|
||||
LinkIcon,
|
||||
},
|
||||
|
||||
computed: {
|
||||
href() {
|
||||
const url = this.value.url;
|
||||
return url.startsWith('http') ? this.value.url : `http://${this.value.url}`;
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.link-block {
|
||||
.link-block {
|
||||
margin-bottom: 30px;
|
||||
display: grid;
|
||||
grid-template-columns: 50px 1fr;
|
||||
|
|
@ -56,5 +49,5 @@
|
|||
&__link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,47 +1,39 @@
|
|||
<template>
|
||||
<div
|
||||
class="final-submission"
|
||||
data-cy="final-submission"
|
||||
>
|
||||
<document-block
|
||||
:value="{url: userInput.document}"
|
||||
class="final-submission__document"
|
||||
v-if="userInput.document"
|
||||
/>
|
||||
<div class="final-submission" data-cy="final-submission">
|
||||
<document-block :value="{ url: userInput.document }" class="final-submission__document" v-if="userInput.document" />
|
||||
<div class="final-submission__explanation">
|
||||
<info-icon class="final-submission__explanation-icon" />
|
||||
<span class="final-submission__explanation-text">{{ sharedMsg }}</span>
|
||||
<a
|
||||
class="final-submission__reopen"
|
||||
data-cy="final-submission-reopen"
|
||||
v-if="showReopen"
|
||||
@click="$emit('reopen')"
|
||||
>Bearbeiten</a>
|
||||
<a class="final-submission__reopen" data-cy="final-submission-reopen" v-if="showReopen" @click="$emit('reopen')"
|
||||
>Bearbeiten</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {newLineToParagraph} from '@/helpers/text';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const DocumentBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/DocumentBlock'));
|
||||
import { newLineToParagraph } from '@/helpers/text';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const DocumentBlock = defineAsyncComponent(() =>
|
||||
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/DocumentBlock')
|
||||
);
|
||||
|
||||
const InfoIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/InfoIcon'));
|
||||
const InfoIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/InfoIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
userInput: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
default: () => ({}),
|
||||
},
|
||||
showReopen: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
default: true,
|
||||
},
|
||||
sharedMsg: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
|
|
@ -52,15 +44,15 @@
|
|||
computed: {
|
||||
text() {
|
||||
return newLineToParagraph(this.userInput.text);
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.final-submission {
|
||||
.final-submission {
|
||||
&__text {
|
||||
background-color: $color-white;
|
||||
@include input-box-shadow;
|
||||
|
|
@ -105,5 +97,5 @@
|
|||
cursor: pointer;
|
||||
color: $color-charcoal-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -10,10 +10,7 @@
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="submission-form-container__actions"
|
||||
v-if="!isFinalOrReadOnly"
|
||||
>
|
||||
<div class="submission-form-container__actions" v-if="!isFinalOrReadOnly">
|
||||
<button
|
||||
class="submission-form-container__submit button button--primary button--white-bg"
|
||||
data-cy="submission-form-submit"
|
||||
|
|
@ -29,11 +26,7 @@
|
|||
>
|
||||
{{ spellcheckText }}
|
||||
</button>
|
||||
<file-upload
|
||||
:document="userInput.document"
|
||||
v-if="allowsDocuments"
|
||||
@change-document-url="changeDocumentUrl"
|
||||
/>
|
||||
<file-upload :document="userInput.document" v-if="allowsDocuments" @change-document-url="changeDocumentUrl" />
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
|
|
@ -48,13 +41,12 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const SubmissionInput = defineAsyncComponent(() => import('@/components/content-blocks/assignment/SubmissionInput'));
|
||||
const FinalSubmission = defineAsyncComponent(() => import('@/components/content-blocks/assignment/FinalSubmission'));
|
||||
const FileUpload = defineAsyncComponent(() => import('@/components/ui/file-upload/FileUpload'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const SubmissionInput = defineAsyncComponent(() => import('@/components/content-blocks/assignment/SubmissionInput'));
|
||||
const FinalSubmission = defineAsyncComponent(() => import('@/components/content-blocks/assignment/FinalSubmission'));
|
||||
const FileUpload = defineAsyncComponent(() => import('@/components/ui/file-upload/FileUpload'));
|
||||
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
userInput: Object,
|
||||
saved: Boolean,
|
||||
|
|
@ -116,14 +108,13 @@
|
|||
this.$emit('changeDocumentUrl', documentUrl);
|
||||
},
|
||||
},
|
||||
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
@import '~styles/helpers';
|
||||
|
||||
.submission-form-container {
|
||||
.submission-form-container {
|
||||
@include form-with-border;
|
||||
|
||||
margin-bottom: $medium-spacing;
|
||||
|
|
@ -158,6 +149,5 @@
|
|||
text-align: center;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -4,54 +4,52 @@
|
|||
:placeholder="placeholder"
|
||||
:readonly="readonly"
|
||||
:value="inputText"
|
||||
:class="{'submission-form__textarea--readonly': readonly}"
|
||||
:class="{ 'submission-form__textarea--readonly': readonly }"
|
||||
data-cy="submission-textarea"
|
||||
rows="1"
|
||||
class="submission-form__textarea"
|
||||
v-auto-grow
|
||||
@input="$emit('input', $event.target.value)"
|
||||
/>
|
||||
<div
|
||||
class="submission-form__save-status submission-form__save-status--saved"
|
||||
v-if="saved"
|
||||
>
|
||||
<div class="submission-form__save-status submission-form__save-status--saved" v-if="saved">
|
||||
<tick-circle-icon class="submission-form__save-status-icon" />
|
||||
</div>
|
||||
<div
|
||||
class="submission-form__save-status submission-form__save-status--unsaved"
|
||||
v-if="!saved"
|
||||
>
|
||||
<div class="submission-form__save-status submission-form__save-status--unsaved" v-if="!saved">
|
||||
<loading-icon class="submission-form__save-status-icon submission-form__saving-icon" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const TickCircleIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/TickCircleIcon'));
|
||||
const LoadingIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/LoadingIcon'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const TickCircleIcon = defineAsyncComponent(() =>
|
||||
import(/* webpackChunkName: "icons" */ '@/components/icons/TickCircleIcon')
|
||||
);
|
||||
const LoadingIcon = defineAsyncComponent(() =>
|
||||
import(/* webpackChunkName: "icons" */ '@/components/icons/LoadingIcon')
|
||||
);
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
inputText: String,
|
||||
saved: Boolean,
|
||||
readonly: Boolean,
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: 'Ergebnis erfassen'
|
||||
}
|
||||
default: 'Ergebnis erfassen',
|
||||
},
|
||||
},
|
||||
components: {
|
||||
TickCircleIcon,
|
||||
LoadingIcon
|
||||
}
|
||||
};
|
||||
LoadingIcon,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.submission-form {
|
||||
.submission-form {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
|
@ -74,5 +72,5 @@
|
|||
&__saving-icon {
|
||||
@include spin;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
class="assignment-form__title skillbox-input"
|
||||
placeholder="Aufgabentitel"
|
||||
@input="$emit('assignment-change-title', $event.target.value, index)"
|
||||
>
|
||||
/>
|
||||
<textarea
|
||||
:value="value.assignment"
|
||||
class="assignment-form__exercise-text skillbox-textarea"
|
||||
|
|
@ -23,18 +23,18 @@
|
|||
import {defineAsyncComponent} from 'vue';
|
||||
const InfoIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/InfoIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: ['value', 'index'],
|
||||
|
||||
components: {
|
||||
InfoIcon
|
||||
}
|
||||
};
|
||||
InfoIcon,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.assignment-form {
|
||||
.assignment-form {
|
||||
display: grid;
|
||||
grid-auto-rows: auto;
|
||||
grid-row-gap: 13px;
|
||||
|
|
@ -59,5 +59,5 @@
|
|||
|
||||
&__help-description {
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,28 +1,12 @@
|
|||
<template>
|
||||
<div
|
||||
class="document-form"
|
||||
ref="documentform"
|
||||
>
|
||||
<div
|
||||
v-if="!value.url"
|
||||
ref="uploadcare-panel"
|
||||
/>
|
||||
<div
|
||||
class="document-form__spinner"
|
||||
v-if="loading"
|
||||
>
|
||||
<div class="document-form" ref="documentform">
|
||||
<div v-if="!value.url" ref="uploadcare-panel" />
|
||||
<div class="document-form__spinner" v-if="loading">
|
||||
<loading-icon class="document-form__loading-icon" />
|
||||
</div>
|
||||
<div
|
||||
class="document-form__uploaded"
|
||||
v-if="value.url"
|
||||
>
|
||||
<div class="document-form__uploaded" v-if="value.url">
|
||||
<document-icon class="document-form__icon" />
|
||||
<a
|
||||
:href="previewUrl"
|
||||
class="document-form__link"
|
||||
target="_blank"
|
||||
>{{ previewLink }}</a>
|
||||
<a :href="previewUrl" class="document-form__link" target="_blank">{{ previewLink }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -34,7 +18,7 @@
|
|||
|
||||
const DocumentIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/DocumentIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: ['value', 'index'],
|
||||
|
||||
components: {
|
||||
|
|
@ -65,21 +49,24 @@
|
|||
},
|
||||
|
||||
mounted() {
|
||||
uploadcare(this, url => {
|
||||
uploadcare(
|
||||
this,
|
||||
(url) => {
|
||||
this.$emit('change-url', url, this.index);
|
||||
this.loading = false;
|
||||
}, () => {
|
||||
this.loading = true;
|
||||
|
||||
});
|
||||
},
|
||||
};
|
||||
() => {
|
||||
this.loading = true;
|
||||
}
|
||||
);
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.document-form {
|
||||
.document-form {
|
||||
&__uploaded {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -129,5 +116,5 @@
|
|||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,11 @@
|
|||
<template>
|
||||
<div>
|
||||
<div
|
||||
class="video-form"
|
||||
v-if="!isVimeo && !isYoutube && !isSrf"
|
||||
>
|
||||
<div class="video-form" v-if="!isVimeo && !isYoutube && !isSrf">
|
||||
<info-icon class="video-form__help-icon help-text__icon" />
|
||||
<p class="video-form__help-description help-text__description">
|
||||
Sie können Videos auf <a
|
||||
class="video-form__platform-link help-text__link"
|
||||
href="https://youtube.com/"
|
||||
target="_blank"
|
||||
>Youtube</a>
|
||||
oder <a
|
||||
class="video-form__platform-link help-text__link"
|
||||
href="https://vimeo.com/"
|
||||
target="_blank"
|
||||
>Vimeo</a>
|
||||
Sie können Videos auf
|
||||
<a class="video-form__platform-link help-text__link" href="https://youtube.com/" target="_blank">Youtube</a>
|
||||
oder <a class="video-form__platform-link help-text__link" href="https://vimeo.com/" target="_blank">Vimeo</a>
|
||||
hochladen und anschliessen einen Link hier einfügen.
|
||||
</p>
|
||||
|
||||
|
|
@ -24,7 +14,7 @@
|
|||
class="video-form__video-link skillbox-input"
|
||||
placeholder="Bsp: https://www.youtube.com/watch?v=dQw4w9WgXcQ"
|
||||
@input="$emit('change-url', $event.target.value, index)"
|
||||
>
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-if="isYoutube">
|
||||
|
|
@ -40,21 +30,21 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import YoutubeEmbed from '@/components/videos/YoutubeEmbed';
|
||||
import VimeoEmbed from '@/components/videos/VimeoEmbed';
|
||||
import SrfEmbed from '@/components/videos/SrfEmbed';
|
||||
import {isVimeoUrl, isYoutubeUrl, isSrfUrl} from '@/helpers/video';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const InfoIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/InfoIcon'));
|
||||
import YoutubeEmbed from '@/components/videos/YoutubeEmbed';
|
||||
import VimeoEmbed from '@/components/videos/VimeoEmbed';
|
||||
import SrfEmbed from '@/components/videos/SrfEmbed';
|
||||
import { isVimeoUrl, isYoutubeUrl, isSrfUrl } from '@/helpers/video';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const InfoIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/InfoIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: ['value', 'index'],
|
||||
|
||||
components: {
|
||||
InfoIcon,
|
||||
YoutubeEmbed,
|
||||
VimeoEmbed,
|
||||
SrfEmbed
|
||||
SrfEmbed,
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
|
@ -66,16 +56,16 @@
|
|||
},
|
||||
isSrf() {
|
||||
return isSrfUrl(this.value.url);
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_functions.scss";
|
||||
@import '@/styles/_variables.scss';
|
||||
@import '@/styles/_functions.scss';
|
||||
|
||||
.video-form {
|
||||
.video-form {
|
||||
display: grid;
|
||||
grid-auto-rows: auto;
|
||||
grid-template-columns: 40px 1fr;
|
||||
|
|
@ -84,11 +74,9 @@
|
|||
align-items: center;
|
||||
|
||||
&__help-icon {
|
||||
|
||||
}
|
||||
|
||||
&__help-description {
|
||||
|
||||
}
|
||||
|
||||
&__platform-link {
|
||||
|
|
@ -100,7 +88,7 @@
|
|||
|
||||
&__video-link {
|
||||
grid-column: 1 / span 2;
|
||||
width: $modal-input-width
|
||||
}
|
||||
width: $modal-input-width;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 378 505">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 378 505">
|
||||
<defs>
|
||||
<clipPath id="b">
|
||||
<path
|
||||
|
|
@ -284,14 +284,9 @@
|
|||
/>
|
||||
<path
|
||||
d="M339.92,387.48c0-.82-.33-1.61-.91-2.19-.58-.58-1.37-.91-2.19-.91H23.71c-.82,0-1.61,.33-2.19,.91-.58,.58-.91,1.37-.91,2.19h0c0,.82,.33,1.61,.91,2.19,.58,.58,1.37,.91,2.19,.91H336.83c.82,0,1.61-.33,2.19-.91,.58-.58,.91-1.37,.91-2.19h0Z"
|
||||
fill="#fff"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
fill="#fff" fill-rule="evenodd" />
|
||||
<polygon
|
||||
points="291.56 386.68 286.32 386.68 286.32 505.02 291.56 505.02 291.56 386.68 291.56 386.68"
|
||||
fill="#fff"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
points="291.56 386.68 286.32 386.68 286.32 505.02 291.56 505.02 291.56 386.68 291.56 386.68" fill="#fff" fill-rule="evenodd" />
|
||||
<polygon
|
||||
points="72.67 387.59 67.43 387.59 67.43 505.02 72.67 505.02 72.67 387.59 72.67 387.59"
|
||||
fill="#fff"
|
||||
|
|
|
|||
|
|
@ -1,31 +1,21 @@
|
|||
<template>
|
||||
<a
|
||||
:class="typeClass"
|
||||
class="filter-entry"
|
||||
data-cy="filter-entry"
|
||||
:style="categoryStyle"
|
||||
@click="$emit('filter')"
|
||||
<a :class="typeClass" class="filter-entry" data-cy="filter-entry" :style="categoryStyle" @click="$emit('filter')"
|
||||
>
|
||||
<span class="filter-entry__text">{{ text }}</span>
|
||||
<span
|
||||
:style="activeStyle"
|
||||
class="filter-entry__icon-wrapper"
|
||||
>
|
||||
<chevron-right
|
||||
:style="{fill: category.foreground}"
|
||||
class="filter-entry__icon"
|
||||
/>
|
||||
<span :style="activeStyle" class="filter-entry__icon-wrapper">
|
||||
<chevron-right :style="{ fill: category.foreground }" class="filter-entry__icon" />
|
||||
</span>
|
||||
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import INSTRUMENT_FILTER_QUERY from 'gql/local/instrumentFilter.gql';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const ChevronRight = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/ChevronRight'));
|
||||
import INSTRUMENT_FILTER_QUERY from 'gql/local/instrumentFilter.gql';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const ChevronRight = defineAsyncComponent(() =>
|
||||
import(/* webpackChunkName: "icons" */ '@/components/icons/ChevronRight')
|
||||
);
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
text: {
|
||||
type: String,
|
||||
|
|
@ -100,13 +90,13 @@
|
|||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
@import '~styles/helpers';
|
||||
|
||||
.filter-entry {
|
||||
.filter-entry {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
|
@ -175,5 +165,5 @@
|
|||
fill: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {defineComponent} from 'vue';
|
||||
import FilterEntry from '@/components/instruments/FilterEntry';
|
||||
import { defineComponent } from 'vue';
|
||||
import FilterEntry from '@/components/instruments/FilterEntry';
|
||||
|
||||
import SET_FILTER_MUTATION from 'gql/local/mutations/setInstrumentFilter.gql';
|
||||
import INSTRUMENT_FILTER_QUERY from 'gql/local/instrumentFilter.gql';
|
||||
import SET_FILTER_MUTATION from 'gql/local/mutations/setInstrumentFilter.gql';
|
||||
import INSTRUMENT_FILTER_QUERY from 'gql/local/instrumentFilter.gql';
|
||||
|
||||
export default defineComponent({
|
||||
export default defineComponent({
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
|
|
@ -51,15 +51,15 @@
|
|||
|
||||
apollo: {
|
||||
instrumentFilter: {
|
||||
query: INSTRUMENT_FILTER_QUERY
|
||||
}
|
||||
query: INSTRUMENT_FILTER_QUERY,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
instrumentFilter: {
|
||||
currentFilter: ''
|
||||
}
|
||||
currentFilter: '',
|
||||
},
|
||||
};
|
||||
},
|
||||
inheritAttrs: false,
|
||||
|
|
@ -76,18 +76,17 @@
|
|||
this.$apollo.mutate({
|
||||
mutation: SET_FILTER_MUTATION,
|
||||
variables: {
|
||||
filter
|
||||
}
|
||||
filter,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
@import '~styles/helpers';
|
||||
|
||||
.filter-group {
|
||||
.filter-group {
|
||||
border-bottom: 1px solid $color-silver;
|
||||
padding: $medium-spacing 0;
|
||||
display: flex;
|
||||
|
|
@ -96,5 +95,5 @@
|
|||
&__children {
|
||||
padding-left: $medium-spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
<template>
|
||||
<router-link
|
||||
:to="moduleLink"
|
||||
:class="['module-teaser', {'module-teaser--small': !teaser}]"
|
||||
>
|
||||
<div
|
||||
:style="{backgroundImage: 'url('+heroImage+')'}"
|
||||
class="module-teaser__image"
|
||||
/>
|
||||
<router-link :to="moduleLink" :class="['module-teaser', { 'module-teaser--small': !teaser }]">
|
||||
<div :style="{ backgroundImage: 'url(' + heroImage + ')' }" class="module-teaser__image" />
|
||||
<div class="module-teaser__body">
|
||||
<h3 class="module-teaser__meta-title">
|
||||
{{ metaTitle }}
|
||||
|
|
@ -22,7 +16,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
export default {
|
||||
props: ['metaTitle', 'title', 'teaser', 'id', 'slug', 'heroImage'],
|
||||
|
||||
computed: {
|
||||
|
|
@ -38,16 +32,17 @@
|
|||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
|
||||
.module-teaser {
|
||||
.module-teaser {
|
||||
box-shadow: 0 3px 9px 0 rgba(0, 0, 0, 0.12);
|
||||
border: 1px solid #E2E2E2;
|
||||
border: 1px solid #e2e2e2;
|
||||
height: 330px;
|
||||
max-width: 380px;
|
||||
width: 100%;
|
||||
|
|
@ -88,5 +83,5 @@
|
|||
line-height: $default-line-height;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
<template>
|
||||
<div
|
||||
class="bookmark-actions"
|
||||
v-if="!editMode"
|
||||
>
|
||||
<div class="bookmark-actions" v-if="!editMode">
|
||||
<a
|
||||
:class="{'bookmark-actions__action--bookmarked': bookmarked}"
|
||||
:class="{ 'bookmark-actions__action--bookmarked': bookmarked }"
|
||||
class="bookmark-actions__action bookmark-actions__bookmark"
|
||||
data-cy="bookmark-action"
|
||||
@click="$emit('bookmark')"
|
||||
|
|
@ -37,39 +34,39 @@
|
|||
const AddNoteIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/AddNoteIcon'));
|
||||
const NoteIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/NoteIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
bookmarked: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
note: {
|
||||
type: [Object, Boolean],
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
BookmarkIcon,
|
||||
AddNoteIcon,
|
||||
NoteIcon
|
||||
NoteIcon,
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.bookmark-actions {
|
||||
.bookmark-actions {
|
||||
height: 100%;
|
||||
min-height: 60px;
|
||||
|
||||
padding: 0 2*$large-spacing;
|
||||
padding: 0 2 * $large-spacing;
|
||||
position: absolute;
|
||||
right: -5*$large-spacing;
|
||||
right: -5 * $large-spacing;
|
||||
|
||||
display: none;
|
||||
|
||||
|
|
@ -88,7 +85,8 @@
|
|||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
&--bookmarked, &--noted {
|
||||
&--bookmarked,
|
||||
&--noted {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -100,6 +98,5 @@
|
|||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -6,34 +6,31 @@
|
|||
placeholder="Lernziel erfassen..."
|
||||
@input="$emit('input', $event)"
|
||||
/>
|
||||
<a
|
||||
class="icon-button"
|
||||
@click="$emit('delete')"
|
||||
>
|
||||
<a class="icon-button" @click="$emit('delete')">
|
||||
<trash-icon class="icon-button__icon icon-button__icon--subtle" />
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ModalInput from '@/components/ModalInput';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const TrashIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/TrashIcon'));
|
||||
import ModalInput from '@/components/ModalInput';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const TrashIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/TrashIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: ['objective'],
|
||||
|
||||
components: {
|
||||
ModalInput,
|
||||
TrashIcon
|
||||
}
|
||||
};
|
||||
TrashIcon,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import '@/styles/_variables.scss';
|
||||
|
||||
.objective-form {
|
||||
.objective-form {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 50px;
|
||||
margin-bottom: 10px;
|
||||
|
|
@ -41,5 +38,5 @@
|
|||
&__input {
|
||||
width: $modal-input-width;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
<template>
|
||||
<a
|
||||
class="add-project-entry"
|
||||
@click="addProjectEntry"
|
||||
>
|
||||
<a class="add-project-entry" @click="addProjectEntry">
|
||||
<plus-icon class="add-project-entry__icon" />
|
||||
<span class="add-project-entry__text">Beitrag erfassen</span>
|
||||
</a>
|
||||
|
|
@ -18,15 +15,15 @@
|
|||
methods: {
|
||||
addProjectEntry() {
|
||||
this.$store.dispatch('addProjectEntry', this.project);
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.add-project-entry {
|
||||
.add-project-entry {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
|
@ -45,5 +42,5 @@
|
|||
@include navigation-link;
|
||||
color: $color-brand;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,25 +1,9 @@
|
|||
<template>
|
||||
<div class="portfolio-onboarding">
|
||||
<h1
|
||||
class="portfolio-onboarding__heading"
|
||||
data-cy="page-title"
|
||||
>
|
||||
Portfolio
|
||||
</h1>
|
||||
<portfolio-illustration
|
||||
data-cy="portfolio-onboarding-illustration"
|
||||
class="portfolio-onboarding__illustration"
|
||||
/>
|
||||
<h2
|
||||
class="portfolio-onboarding__subheading"
|
||||
data-cy="portfolio-onboarding-subtitle"
|
||||
>
|
||||
Woran denken Sie gerade?
|
||||
</h2>
|
||||
<p
|
||||
class="portfolio-onboarding__text"
|
||||
data-cy="portfolio-onboarding-text"
|
||||
>
|
||||
<h1 class="portfolio-onboarding__heading" data-cy="page-title">Portfolio</h1>
|
||||
<portfolio-illustration data-cy="portfolio-onboarding-illustration" class="portfolio-onboarding__illustration" />
|
||||
<h2 class="portfolio-onboarding__subheading" data-cy="portfolio-onboarding-subtitle">Woran denken Sie gerade?</h2>
|
||||
<p class="portfolio-onboarding__text" data-cy="portfolio-onboarding-text">
|
||||
Hier können Sie Projekte erstellen, um Ihre Gedanken festzuhalten oder Ihre Arbeit zu dokumentieren.
|
||||
</p>
|
||||
|
||||
|
|
@ -37,9 +21,9 @@
|
|||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
@import '~styles/helpers';
|
||||
|
||||
.portfolio-onboarding {
|
||||
.portfolio-onboarding {
|
||||
@include onboarding-page;
|
||||
|
||||
&__heading {
|
||||
|
|
@ -57,5 +41,5 @@
|
|||
&__text {
|
||||
@include onboarding-text;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,48 +1,20 @@
|
|||
<template>
|
||||
<div
|
||||
class="project-actions"
|
||||
data-cy="project-actions"
|
||||
>
|
||||
<a
|
||||
class="project-actions__more-link"
|
||||
@click.stop="toggleMenu"
|
||||
>
|
||||
<div class="project-actions" data-cy="project-actions">
|
||||
<a class="project-actions__more-link" @click.stop="toggleMenu">
|
||||
<ellipses />
|
||||
</a>
|
||||
<widget-popover
|
||||
class="project-actions__popover"
|
||||
v-if="showMenu"
|
||||
@hide-me="showMenu = false"
|
||||
>
|
||||
<widget-popover class="project-actions__popover" v-if="showMenu" @hide-me="showMenu = false">
|
||||
<li class="popover-links__link">
|
||||
<a
|
||||
data-cy="delete-project"
|
||||
@click="deleteProject(slug)"
|
||||
>Projekt löschen</a>
|
||||
<a data-cy="delete-project" @click="deleteProject(slug)">Projekt löschen</a>
|
||||
</li>
|
||||
<li class="popover-links__link">
|
||||
<a
|
||||
data-cy="edit-project"
|
||||
@click="editProject(slug)"
|
||||
>Projekt bearbeiten</a>
|
||||
<a data-cy="edit-project" @click="editProject(slug)">Projekt bearbeiten</a>
|
||||
</li>
|
||||
<li
|
||||
class="popover-links__link"
|
||||
v-if="!final && shareButtons"
|
||||
>
|
||||
<a
|
||||
data-cy="share-project"
|
||||
@click="updateProjectShareState(slug, true)"
|
||||
>Projekt teilen</a>
|
||||
<li class="popover-links__link" v-if="!final && shareButtons">
|
||||
<a data-cy="share-project" @click="updateProjectShareState(slug, true)">Projekt teilen</a>
|
||||
</li>
|
||||
<li
|
||||
class="popover-links__link"
|
||||
v-if="final && shareButtons"
|
||||
>
|
||||
<a
|
||||
data-cy="unshare-project"
|
||||
@click="updateProjectShareState(slug, false)"
|
||||
>Projekt nicht mehr teilen</a>
|
||||
<li class="popover-links__link" v-if="final && shareButtons">
|
||||
<a data-cy="unshare-project" @click="updateProjectShareState(slug, false)">Projekt nicht mehr teilen</a>
|
||||
</li>
|
||||
</widget-popover>
|
||||
</div>
|
||||
|
|
@ -55,9 +27,9 @@ import DELETE_PROJECT_MUTATION from '@/graphql/gql/mutations/deleteProject.gql';
|
|||
import PROJECTS_QUERY from '@/graphql/gql/queries/allProjects.gql';
|
||||
|
||||
import updateProjectShareState from '@/mixins/update-project-share-state';
|
||||
import {removeAtIndex} from '@/graphql/immutable-operations.ts';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const Ellipses = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/Ellipses.vue'));
|
||||
import { removeAtIndex } from '@/graphql/immutable-operations.ts';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const Ellipses = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/Ellipses.vue'));
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
|
@ -93,33 +65,41 @@ export default {
|
|||
this.showMenu = !this.showMenu;
|
||||
},
|
||||
editProject(slug) {
|
||||
this.$router.push({name: 'edit-project', params: {slug}});
|
||||
this.$router.push({ name: 'edit-project', params: { slug } });
|
||||
},
|
||||
deleteProject(slug) {
|
||||
this.$apollo.mutate({
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: DELETE_PROJECT_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
slug,
|
||||
},
|
||||
},
|
||||
update(store, {data: {deleteProject: {success}}}) {
|
||||
update(
|
||||
store,
|
||||
{
|
||||
data: {
|
||||
deleteProject: { success },
|
||||
},
|
||||
}
|
||||
) {
|
||||
if (success) {
|
||||
const {projects: prevProjects} = store.readQuery({query: PROJECTS_QUERY});
|
||||
|
||||
const { projects: prevProjects } = store.readQuery({ query: PROJECTS_QUERY });
|
||||
|
||||
if (prevProjects) {
|
||||
let index = prevProjects.findIndex(project => project.slug === slug);
|
||||
let index = prevProjects.findIndex((project) => project.slug === slug);
|
||||
const projects = removeAtIndex(prevProjects, index);
|
||||
|
||||
const data = {
|
||||
projects
|
||||
projects,
|
||||
};
|
||||
store.writeQuery({query: PROJECTS_QUERY, data});
|
||||
store.writeQuery({ query: PROJECTS_QUERY, data });
|
||||
}
|
||||
}
|
||||
},
|
||||
}).then(() => {
|
||||
})
|
||||
.then(() => {
|
||||
this.$router.push('/portfolio');
|
||||
});
|
||||
},
|
||||
|
|
@ -128,7 +108,7 @@ export default {
|
|||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/_helpers.scss";
|
||||
@import '~styles/_helpers.scss';
|
||||
|
||||
.project-actions {
|
||||
position: relative;
|
||||
|
|
|
|||
|
|
@ -1,44 +1,22 @@
|
|||
<template>
|
||||
<div
|
||||
class="project-entry"
|
||||
data-cy="project-entry"
|
||||
>
|
||||
<more-options-widget
|
||||
class="project-entry__more"
|
||||
data-cy="project-entry-more"
|
||||
v-if="!readOnly"
|
||||
>
|
||||
<div class="project-entry" data-cy="project-entry">
|
||||
<more-options-widget class="project-entry__more" data-cy="project-entry-more" v-if="!readOnly">
|
||||
<li class="popover-links__link">
|
||||
<a
|
||||
data-cy="edit-project-entry"
|
||||
@click="editProjectEntry()"
|
||||
>Eintrag bearbeiten</a>
|
||||
<a data-cy="edit-project-entry" @click="editProjectEntry()">Eintrag bearbeiten</a>
|
||||
</li>
|
||||
<li class="popover-links__link">
|
||||
<a
|
||||
data-cy="delete-project-entry"
|
||||
@click="deleteProjectEntry()"
|
||||
>Eintrag löschen</a>
|
||||
<a data-cy="delete-project-entry" @click="deleteProjectEntry()">Eintrag löschen</a>
|
||||
</li>
|
||||
</more-options-widget>
|
||||
|
||||
<h3
|
||||
class="project-entry__heading"
|
||||
data-cy="project-entry-date"
|
||||
>
|
||||
<h3 class="project-entry__heading" data-cy="project-entry-date">
|
||||
{{ createdDateTime }}
|
||||
</h3>
|
||||
<p
|
||||
class="project-entry__paragraph"
|
||||
data-cy="project-entry-activity"
|
||||
>
|
||||
<p class="project-entry__paragraph" data-cy="project-entry-activity">
|
||||
{{ description }}
|
||||
</p>
|
||||
<p
|
||||
class="project-entry__paragraph"
|
||||
v-if="documentUrl"
|
||||
>
|
||||
<document-block :value="{url: documentUrl}" />
|
||||
<p class="project-entry__paragraph" v-if="documentUrl">
|
||||
<document-block :value="{ url: documentUrl }" />
|
||||
</p>
|
||||
<div class="project-entry__date">
|
||||
{{ createdDate }}
|
||||
|
|
@ -47,7 +25,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MoreOptionsWidget from '@/components/MoreOptionsWidget';
|
||||
import MoreOptionsWidget from '@/components/MoreOptionsWidget';
|
||||
|
||||
import DELETE_PROJECT_ENTRY_MUTATION from '@/graphql/gql/mutations/deleteProjectEntry.gql';
|
||||
import PROJECT_QUERY from '@/graphql/gql/queries/projectQuery.gql';
|
||||
|
|
@ -57,7 +35,7 @@
|
|||
const DocumentBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/DocumentBlock'));
|
||||
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: ['description', 'documentUrl', 'created', 'id', 'readOnly'],
|
||||
components: {
|
||||
DocumentBlock,
|
||||
|
|
@ -86,15 +64,22 @@
|
|||
id: this.id,
|
||||
},
|
||||
},
|
||||
update(store, {data: {deleteProjectEntry: {success}}}) {
|
||||
update(
|
||||
store,
|
||||
{
|
||||
data: {
|
||||
deleteProjectEntry: { success },
|
||||
},
|
||||
}
|
||||
) {
|
||||
if (success) {
|
||||
const query = PROJECT_QUERY;
|
||||
const variables = {
|
||||
slug: projectEntry.$route.params.slug,
|
||||
};
|
||||
const {project} = store.readQuery({query, variables});
|
||||
const { project } = store.readQuery({ query, variables });
|
||||
if (project) {
|
||||
const index = project.entries.findIndex(entry => entry.id === projectEntry.id);
|
||||
const index = project.entries.findIndex((entry) => entry.id === projectEntry.id);
|
||||
const entries = removeAtIndex(project.entries, index);
|
||||
const data = {
|
||||
project: {
|
||||
|
|
@ -102,20 +87,20 @@
|
|||
entries,
|
||||
},
|
||||
};
|
||||
store.writeQuery({query, variables, data});
|
||||
store.writeQuery({ query, variables, data });
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.project-entry {
|
||||
.project-entry {
|
||||
background-color: $color-white;
|
||||
border-radius: $default-border-radius;
|
||||
padding: 30px 20px;
|
||||
|
|
@ -151,6 +136,5 @@
|
|||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,7 @@
|
|||
<template>
|
||||
<modal :hide-header="false">
|
||||
<template #header>
|
||||
<h2
|
||||
class="project-entry-modal__heading"
|
||||
data-cy="modal-title"
|
||||
>
|
||||
Beitrag erfassen
|
||||
</h2>
|
||||
<h2 class="project-entry-modal__heading" data-cy="modal-title">Beitrag erfassen</h2>
|
||||
</template>
|
||||
|
||||
<div class="project-entry-modal">
|
||||
|
|
@ -36,29 +31,24 @@
|
|||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a
|
||||
class="button button--primary"
|
||||
data-cy="modal-save-button"
|
||||
@click="$emit('save', localProjectEntry)"
|
||||
>Speichern</a>
|
||||
<a
|
||||
class="button"
|
||||
@click="$emit('hide')"
|
||||
>Abbrechen</a>
|
||||
<a class="button button--primary" data-cy="modal-save-button" @click="$emit('save', localProjectEntry)"
|
||||
>Speichern</a
|
||||
>
|
||||
<a class="button" @click="$emit('hide')">Abbrechen</a>
|
||||
</template>
|
||||
</modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from '@/components/Modal';
|
||||
import ButtonWithIconAndText from '@/components/ui/ButtonWithIconAndText';
|
||||
import Modal from '@/components/Modal';
|
||||
import ButtonWithIconAndText from '@/components/ui/ButtonWithIconAndText';
|
||||
|
||||
import {PROJECT_ENTRY_TEMPLATE} from '@/consts/strings.consts';
|
||||
import { PROJECT_ENTRY_TEMPLATE } from '@/consts/strings.consts';
|
||||
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const FileUpload = defineAsyncComponent(() => import('@/components/ui/file-upload/FileUpload'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const FileUpload = defineAsyncComponent(() => import('@/components/ui/file-upload/FileUpload'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
projectEntry: {
|
||||
type: Object,
|
||||
|
|
@ -74,9 +64,12 @@
|
|||
|
||||
data() {
|
||||
return {
|
||||
localProjectEntry: Object.assign({}, {
|
||||
localProjectEntry: Object.assign(
|
||||
{},
|
||||
{
|
||||
...this.projectEntry,
|
||||
}),
|
||||
}
|
||||
),
|
||||
};
|
||||
},
|
||||
|
||||
|
|
@ -88,13 +81,13 @@
|
|||
this.localProjectEntry.description = `${this.localProjectEntry.description}${PROJECT_ENTRY_TEMPLATE}`;
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.project-entry-modal {
|
||||
.project-entry-modal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
|
|
@ -135,7 +128,5 @@
|
|||
@include heading-3;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,7 @@
|
|||
<template>
|
||||
<page-form
|
||||
:title="title"
|
||||
@save="$emit('save', localProject)"
|
||||
>
|
||||
<page-form-input
|
||||
label="Titel"
|
||||
v-model="localProject.title"
|
||||
/>
|
||||
<page-form-input
|
||||
label="Beschreibung"
|
||||
type="textarea"
|
||||
v-model="localProject.description"
|
||||
/>
|
||||
<page-form :title="title" @save="$emit('save', localProject)">
|
||||
<page-form-input label="Titel" v-model="localProject.title" />
|
||||
<page-form-input label="Beschreibung" type="textarea" v-model="localProject.description" />
|
||||
<template #footer>
|
||||
<button
|
||||
:class="{ 'button--disabled': !formValid }"
|
||||
|
|
@ -22,12 +12,7 @@
|
|||
>
|
||||
Speichern
|
||||
</button>
|
||||
<router-link
|
||||
to="/portfolio"
|
||||
class="button"
|
||||
>
|
||||
Abbrechen
|
||||
</router-link>
|
||||
<router-link to="/portfolio" class="button"> Abbrechen </router-link>
|
||||
</template>
|
||||
</page-form>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
<owner-widget :owner="project.student" class="project__owner" />
|
||||
|
||||
<entry-count-widget class="project__entry-count" :verbose="false" :entry-count="project.entriesCount" />
|
||||
<entry-count-widgetclass="project__entry-count" :verbose="false" :entry-count="project.entriesCount" />
|
||||
</router-link>
|
||||
<project-actions
|
||||
:final="project.final"
|
||||
|
|
@ -70,10 +70,8 @@ export default {
|
|||
@include desktop {
|
||||
display: flex;
|
||||
flex: 80%;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
flex-direction: row;align-items: center;
|
||||
}}
|
||||
|
||||
&__title {
|
||||
flex: 50%;
|
||||
|
|
@ -96,7 +94,6 @@ export default {
|
|||
|
||||
&__entry-count {
|
||||
justify-self: flex-end;
|
||||
grid-column: 2 / span 1;
|
||||
}
|
||||
grid-column: 2 / span 1;}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<template>
|
||||
<a
|
||||
class="share-icon"
|
||||
@click="$emit('share')"
|
||||
<a class="share-icon" @click="$emit('share')"
|
||||
>
|
||||
<share-icon class="share-icon__icon" />
|
||||
<span class="share-icon__text">
|
||||
|
|
@ -12,10 +10,10 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const ShareIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/ShareIcon'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const ShareIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/ShareIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
final: {
|
||||
type: Boolean,
|
||||
|
|
@ -23,14 +21,14 @@
|
|||
},
|
||||
},
|
||||
emits: ['share'],
|
||||
components: {ShareIcon},
|
||||
};
|
||||
components: { ShareIcon },
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
@import '~styles/helpers';
|
||||
|
||||
.share-icon {
|
||||
.share-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
|
@ -44,5 +42,5 @@
|
|||
&__text {
|
||||
@include large-link;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -2,31 +2,23 @@
|
|||
<div class="avatar">
|
||||
<transition name="fade">
|
||||
<default-avatar
|
||||
:class="{'avatar__placeholder--highlighted': iconHighlighted}"
|
||||
:class="{ 'avatar__placeholder--highlighted': iconHighlighted }"
|
||||
class="avatar__placeholder"
|
||||
v-show="!isAvatarLoaded"
|
||||
/>
|
||||
</transition>
|
||||
<transition name="show">
|
||||
<div
|
||||
:style="{'background-image': `url(${avatarUrl})`}"
|
||||
:style="{ 'background-image': `url(${avatarUrl})` }"
|
||||
class="avatar__image"
|
||||
v-show="isAvatarLoaded"
|
||||
ref="avatarImage"
|
||||
/>
|
||||
</transition>
|
||||
<img
|
||||
:src="avatarUrl"
|
||||
class="avatar__fake-image"
|
||||
ref="fakeImage"
|
||||
>
|
||||
<img :src="avatarUrl" class="avatar__fake-image" ref="fakeImage" />
|
||||
|
||||
<div
|
||||
class="avatar__edit"
|
||||
v-if="editable"
|
||||
@click="closeSidebar"
|
||||
>
|
||||
<router-link :to="{name: 'profile'}">
|
||||
<div class="avatar__edit" v-if="editable" @click="closeSidebar">
|
||||
<router-link :to="{ name: 'profile' }">
|
||||
<pen-icon />
|
||||
</router-link>
|
||||
</div>
|
||||
|
|
@ -40,23 +32,23 @@
|
|||
const DefaultAvatar = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/DefaultAvatar'));
|
||||
const PenIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/PenIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
avatarUrl: {
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
iconHighlighted: {},
|
||||
editable: {
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
DefaultAvatar,
|
||||
PenIcon
|
||||
PenIcon,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isAvatarLoaded: false
|
||||
isAvatarLoaded: false,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
|
|
@ -75,21 +67,21 @@
|
|||
mutation: TOGGLE_SIDEBAR,
|
||||
variables: {
|
||||
sidebar: {
|
||||
profile: false
|
||||
}
|
||||
}
|
||||
profile: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
$max-width: 100%;
|
||||
$max-width: 100%;
|
||||
|
||||
.avatar {
|
||||
.avatar {
|
||||
height: $max-width;
|
||||
width: $max-width;
|
||||
overflow: hidden;
|
||||
|
|
@ -149,5 +141,5 @@
|
|||
.show-enter-to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,9 @@
|
|||
<template>
|
||||
<div class="content-bookmark module-activity-entry">
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<div
|
||||
v-if="content.type === 'text_block'"
|
||||
v-html="text"
|
||||
/>
|
||||
<div v-if="content.type === 'text_block'" v-html="text" />
|
||||
<div v-else-if="content.type === 'link_block'">
|
||||
<link-block
|
||||
:value="content.value"
|
||||
:no-margin="true"
|
||||
/>
|
||||
<link-block :value="content.value" :no-margin="true" />
|
||||
</div>
|
||||
<p v-else>
|
||||
{{ type }}
|
||||
|
|
@ -21,14 +15,14 @@
|
|||
import {defineAsyncComponent} from 'vue';
|
||||
const LinkBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/LinkBlock'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: ['bookmark'],
|
||||
components: {LinkBlock},
|
||||
components: { LinkBlock },
|
||||
computed: {
|
||||
content() {
|
||||
return this.bookmark.contentBlock
|
||||
? this.bookmark.contentBlock.contents.find(e => e.id === this.bookmark.uuid)
|
||||
: this.bookmark.instrument.contents.find(e => e.id === this.bookmark.uuid);
|
||||
? this.bookmark.contentBlock.contents.find((e) => e.id === this.bookmark.uuid)
|
||||
: this.bookmark.instrument.contents.find((e) => e.id === this.bookmark.uuid);
|
||||
},
|
||||
text() {
|
||||
return this.content.value.text ? this.content.value.text : 'TO BE DEFINED';
|
||||
|
|
@ -46,7 +40,7 @@
|
|||
default:
|
||||
return this.content.type;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
<template>
|
||||
<a
|
||||
class="edit-group-name"
|
||||
data-cy="edit-group-name-link"
|
||||
@click="$emit('edit')"
|
||||
>
|
||||
<a class="edit-group-name" data-cy="edit-group-name-link" @click="$emit('edit')">
|
||||
<pen-icon class="edit-group-name__icon" />
|
||||
</a>
|
||||
</template>
|
||||
|
|
@ -12,21 +8,21 @@
|
|||
import {defineAsyncComponent} from 'vue';
|
||||
const PenIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/PenIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
PenIcon
|
||||
}
|
||||
};
|
||||
PenIcon,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/_variables.scss";
|
||||
@import '~styles/_variables.scss';
|
||||
|
||||
.edit-group-name {
|
||||
.edit-group-name {
|
||||
&__icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
fill: $color-brand;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -181,17 +181,13 @@ export default {
|
|||
}
|
||||
|
||||
&__role {
|
||||
@include desktop {
|
||||
flex: 0 1 110px;
|
||||
@include desktop {flex: 0 1 110px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
&__action {
|
||||
@include desktop {
|
||||
flex: 0 1 110px;
|
||||
@include desktop {flex: 0 1 110px;
|
||||
padding-left: $large-spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,49 +1,38 @@
|
|||
<template>
|
||||
<div class="profile">
|
||||
<h1 class="profile__header">
|
||||
Profilbild
|
||||
</h1>
|
||||
<div
|
||||
class="profile-avatar"
|
||||
v-if="me.avatarUrl"
|
||||
>
|
||||
<h1 class="profile__header">Profilbild</h1>
|
||||
<div class="profile-avatar" v-if="me.avatarUrl">
|
||||
<div class="profile-avatar__image">
|
||||
<avatar :avatar-url="me.avatarUrl" />
|
||||
</div>
|
||||
<a
|
||||
class="profile-avatar__remove icon-button"
|
||||
@click="deleteAvatar()"
|
||||
>
|
||||
<a class="profile-avatar__remove icon-button" @click="deleteAvatar()">
|
||||
<trash-icon class="profile-avatar__remove-icon icon-button__icon icon-button__icon--subtle" />
|
||||
</a>
|
||||
</div>
|
||||
<avatar-upload-form
|
||||
v-else
|
||||
@avatarUpdate="updateAvatar"
|
||||
/>
|
||||
<avatar-upload-form v-else @avatarUpdate="updateAvatar" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UPDATE_AVATAR_QUERY from '@/graphql/gql/mutations/updateAvatarUrl.gql';
|
||||
import ME_QUERY from '@/graphql/gql/queries/meQuery.gql';
|
||||
import AvatarUploadForm from '@/components/profile/AvatarUploadForm';
|
||||
import Avatar from '@/components/profile/Avatar';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const TrashIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/TrashIcon'));
|
||||
import UPDATE_AVATAR_QUERY from '@/graphql/gql/mutations/updateAvatarUrl.gql';
|
||||
import ME_QUERY from '@/graphql/gql/queries/meQuery.gql';
|
||||
import AvatarUploadForm from '@/components/profile/AvatarUploadForm';
|
||||
import Avatar from '@/components/profile/Avatar';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const TrashIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/TrashIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
AvatarUploadForm,
|
||||
Avatar,
|
||||
TrashIcon
|
||||
TrashIcon,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
me: {
|
||||
avatarUrl: ''
|
||||
}
|
||||
avatarUrl: '',
|
||||
},
|
||||
};
|
||||
},
|
||||
apollo: {
|
||||
|
|
@ -52,43 +41,52 @@
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
deleteAvatar () {
|
||||
deleteAvatar() {
|
||||
this.updateAvatar('');
|
||||
},
|
||||
updateAvatar (url) {
|
||||
this.$apollo.mutate({
|
||||
updateAvatar(url) {
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: UPDATE_AVATAR_QUERY,
|
||||
variables: {
|
||||
input: {
|
||||
avatarUrl: url
|
||||
}
|
||||
avatarUrl: url,
|
||||
},
|
||||
update(store, {data: {updateAvatar: {success}}}) {
|
||||
},
|
||||
update(
|
||||
store,
|
||||
{
|
||||
data: {
|
||||
updateAvatar: { success },
|
||||
},
|
||||
}
|
||||
) {
|
||||
if (success) {
|
||||
const {me} = store.readQuery({query: ME_QUERY});
|
||||
const { me } = store.readQuery({ query: ME_QUERY });
|
||||
if (me) {
|
||||
const data = {
|
||||
me: {
|
||||
...me,
|
||||
avatarUrl: url
|
||||
}
|
||||
avatarUrl: url,
|
||||
},
|
||||
};
|
||||
store.writeQuery({query: ME_QUERY, data});
|
||||
store.writeQuery({ query: ME_QUERY, data });
|
||||
}
|
||||
}
|
||||
}
|
||||
}).catch((error) => {
|
||||
},
|
||||
})
|
||||
.catch((error) => {
|
||||
console.warn('UploadError', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import '@/styles/_variables.scss';
|
||||
|
||||
.profile-avatar {
|
||||
.profile-avatar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
|
|
@ -96,10 +94,9 @@
|
|||
height: 230px;
|
||||
width: 230px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.profile-avatar {
|
||||
.profile-avatar {
|
||||
margin-bottom: $large-spacing;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,69 +1,31 @@
|
|||
<template>
|
||||
<transition name="slide">
|
||||
<div
|
||||
class="profile-sidebar"
|
||||
data-cy="sidebar"
|
||||
v-if="sidebar.profile"
|
||||
v-click-outside="close"
|
||||
>
|
||||
<a
|
||||
class="profile-sidebar__close-link"
|
||||
data-cy="close-profile-sidebar-link"
|
||||
@click="close"
|
||||
>
|
||||
<div class="profile-sidebar" data-cy="sidebar" v-if="sidebar.profile" v-click-outside="close">
|
||||
<a class="profile-sidebar__close-link" data-cy="close-profile-sidebar-link" @click="close">
|
||||
<cross class="profile-sidebar__close-icon" />
|
||||
</a>
|
||||
<div class="profile-sidebar__section">
|
||||
<profile-widget class="profile-sidebar__item" />
|
||||
<div
|
||||
class="profile-sidebar__item"
|
||||
@click="close"
|
||||
>
|
||||
<router-link
|
||||
to="/me/activity"
|
||||
class="profile-sidebar__link"
|
||||
>
|
||||
Meine Aktivitäten
|
||||
</router-link>
|
||||
<div class="profile-sidebar__item" @click="close">
|
||||
<router-link to="/me/activity" class="profile-sidebar__link"> Meine Aktivitäten </router-link>
|
||||
</div>
|
||||
<div
|
||||
class="profile-sidebar__item"
|
||||
v-if="me.isTeacher && !me.readOnly"
|
||||
@click="close"
|
||||
>
|
||||
<router-link
|
||||
:to="myTeamPage"
|
||||
data-cy="my-team-link"
|
||||
class="profile-sidebar__link"
|
||||
>
|
||||
Mein Team
|
||||
</router-link>
|
||||
<div class="profile-sidebar__item" v-if="me.isTeacher && !me.readOnly" @click="close">
|
||||
<router-link :to="myTeamPage" data-cy="my-team-link" class="profile-sidebar__link"> Mein Team </router-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="profile-sidebar__section">
|
||||
<div class="profile-sidebar__item">
|
||||
<class-selection-widget />
|
||||
<div @click="close">
|
||||
<router-link
|
||||
:to="{name: 'my-class'}"
|
||||
data-cy="class-list-link"
|
||||
class="profile-sidebar__link"
|
||||
>
|
||||
<router-link :to="{ name: 'my-class' }" data-cy="class-list-link" class="profile-sidebar__link">
|
||||
Klassenliste
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="profile-sidebar__section">
|
||||
<div
|
||||
class="profile-sidebar__item"
|
||||
@click="close"
|
||||
>
|
||||
<router-link
|
||||
:to="{name:'join-class'}"
|
||||
data-cy="join-class-link"
|
||||
class="profile-sidebar__link"
|
||||
>
|
||||
<div class="profile-sidebar__item" @click="close">
|
||||
<router-link :to="{ name: 'join-class' }" data-cy="join-class-link" class="profile-sidebar__link">
|
||||
Zugangscode
|
||||
</router-link>
|
||||
</div>
|
||||
|
|
@ -76,19 +38,18 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import ProfileWidget from '@/components/profile/ProfileWidget';
|
||||
import ProfileWidget from '@/components/profile/ProfileWidget';
|
||||
|
||||
import ClassSelectionWidget from '@/components/school-class/ClassSelectionWidget';
|
||||
import ClassSelectionWidget from '@/components/school-class/ClassSelectionWidget';
|
||||
|
||||
import sidebar from '@/mixins/sidebar';
|
||||
import me from '@/mixins/me';
|
||||
import LogoutWidget from '@/components/LogoutWidget';
|
||||
import {MY_TEAM} from '@/router/me.names';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const Cross = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/CrossIcon'));
|
||||
|
||||
export default {
|
||||
import sidebar from '@/mixins/sidebar';
|
||||
import me from '@/mixins/me';
|
||||
import LogoutWidget from '@/components/LogoutWidget';
|
||||
import { MY_TEAM } from '@/router/me.names';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const Cross = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/CrossIcon'));
|
||||
|
||||
export default {
|
||||
mixins: [sidebar, me],
|
||||
|
||||
components: {
|
||||
|
|
@ -111,15 +72,15 @@
|
|||
this.closeSidebar('profile');
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
$desktop-width: 333px;
|
||||
$desktop-width: 333px;
|
||||
|
||||
.profile-sidebar {
|
||||
.profile-sidebar {
|
||||
padding: $large-spacing 0;
|
||||
box-sizing: border-box;
|
||||
position: fixed;
|
||||
|
|
@ -170,18 +131,20 @@
|
|||
top: $small-spacing;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.slide {
|
||||
&-enter-active, &-leave-active {
|
||||
.slide {
|
||||
&-enter-active,
|
||||
&-leave-active {
|
||||
transition: right 0.2s;
|
||||
}
|
||||
|
||||
&-enter-from, &-leave-to {
|
||||
&-enter-from,
|
||||
&-leave-to {
|
||||
right: -100vw;
|
||||
@include desktop {
|
||||
right: -$desktop-width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -32,12 +32,9 @@ export default {
|
|||
.show-code {
|
||||
&__title {
|
||||
@include regular-text;
|
||||
|
||||
margin-bottom: $large-spacing;
|
||||
@include desktop {
|
||||
margin-bottom: 2 * $large-spacing;
|
||||
}
|
||||
}
|
||||
margin-bottom: $large-spacing;
|
||||
@include desktop { margin-bottom: 2 * $large-spacing;
|
||||
}}
|
||||
|
||||
&__code {
|
||||
font-size: toRem(60px);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
<template>
|
||||
<router-link
|
||||
class="add-room-entry-button"
|
||||
data-cy="add-room-entry-button"
|
||||
:to="addRoomEntryRoute"
|
||||
>
|
||||
<router-link class="add-room-entry-button" data-cy="add-room-entry-button" :to="addRoomEntryRoute">
|
||||
<plus-icon class="add-room-entry-button__icon" />
|
||||
<span class="add-room-entry-button__text">Beitrag erfassen</span>
|
||||
</router-link>
|
||||
|
|
@ -14,7 +10,7 @@
|
|||
const PlusIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/PlusIcon'));
|
||||
import { ADD_ROOM_ENTRY_PAGE } from '@/router/room.names';
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: ['parent'],
|
||||
|
||||
components: {
|
||||
|
|
@ -28,13 +24,13 @@
|
|||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.add-room-entry-button {
|
||||
.add-room-entry-button {
|
||||
border: 2px solid $color-white;
|
||||
border-radius: 12px;
|
||||
height: 150px;
|
||||
|
|
@ -61,5 +57,5 @@
|
|||
@include regular-text;
|
||||
color: $color-white;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,18 @@
|
|||
<template>
|
||||
<div class="entry-count-widget">
|
||||
<component :is="icon" />
|
||||
<span data-cy="entry-count">{{ entryCount }} <template v-if="verbose">{{ entryCount === 1 ? 'Beitrag' : 'Beiträge' }}</template></span>
|
||||
<span data-cy="entry-count"
|
||||
>{{ entryCount }} <template v-if="verbose">{{ entryCount === 1 ? 'Beitrag' : 'Beiträge' }}</template></span
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
import SpeechBubbleIcon from '@/components/icons/SpeechBubbleIcon';
|
||||
const Cards = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/Cards.vue'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
import SpeechBubbleIcon from '@/components/icons/SpeechBubbleIcon';
|
||||
const Cards = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/Cards.vue'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
entryCount: {
|
||||
type: Number,
|
||||
|
|
@ -21,8 +23,8 @@
|
|||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: 'cards'
|
||||
}
|
||||
default: 'cards',
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
|
|
@ -30,13 +32,13 @@
|
|||
SpeechBubbleIcon,
|
||||
Cards,
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.entry-count-widget {
|
||||
.entry-count-widget {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
opacity: 0.6;
|
||||
|
|
@ -51,6 +53,5 @@
|
|||
& > span {
|
||||
@include room-widget-text-style;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,34 +1,30 @@
|
|||
<template>
|
||||
<div class="more-actions">
|
||||
<a
|
||||
:class="{'more-actions__toggle--background': background}"
|
||||
:class="{ 'more-actions__toggle--background': background }"
|
||||
class="more-actions__toggle"
|
||||
data-cy="toggle-more-actions-menu"
|
||||
@click.stop="toggleMenu"
|
||||
>
|
||||
<ellipses />
|
||||
</a>
|
||||
<widget-popover
|
||||
class="more-actions__popover"
|
||||
v-if="showMenu"
|
||||
@hide-me="showMenu = false"
|
||||
>
|
||||
<widget-popover class="more-actions__popover" v-if="showMenu" @hide-me="showMenu = false">
|
||||
<slot :toggle="toggleMenu" />
|
||||
</widget-popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WidgetPopover from '@/components/ui/WidgetPopover';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const Ellipses = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/Ellipses'));
|
||||
import WidgetPopover from '@/components/ui/WidgetPopover';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const Ellipses = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/Ellipses'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
background: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
|
|
@ -46,13 +42,13 @@
|
|||
this.showMenu = !this.showMenu;
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
@import '~styles/helpers';
|
||||
|
||||
.more-actions {
|
||||
.more-actions {
|
||||
svg {
|
||||
width: 30px;
|
||||
fill: $color-charcoal-dark;
|
||||
|
|
@ -67,5 +63,5 @@
|
|||
background: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,65 +1,40 @@
|
|||
<template>
|
||||
<page-form
|
||||
class="room-form"
|
||||
title="Neuer Raum"
|
||||
@save="$emit('save', localRoom)"
|
||||
>
|
||||
<page-form-input
|
||||
label="Titel"
|
||||
v-model="localRoom.title"
|
||||
/>
|
||||
<page-form class="room-form" title="Neuer Raum" @save="$emit('save', localRoom)">
|
||||
<page-form-input label="Titel" v-model="localRoom.title" />
|
||||
|
||||
<page-form-input
|
||||
label="Beschreibung"
|
||||
type="textarea"
|
||||
v-model="localRoom.description"
|
||||
/>
|
||||
<page-form-input label="Beschreibung" type="textarea" v-model="localRoom.description" />
|
||||
|
||||
<h2 class="room-form__property-heading">
|
||||
Farbe
|
||||
</h2>
|
||||
<color-chooser
|
||||
:selected-color="localRoom.appearance"
|
||||
@input="updateColor"
|
||||
/>
|
||||
<h2 class="room-form__property-heading">Farbe</h2>
|
||||
<color-chooser :selected-color="localRoom.appearance" @input="updateColor" />
|
||||
<template #footer>
|
||||
<button
|
||||
type="submit"
|
||||
data-cy="room-form-save"
|
||||
class="button button--primary room-form__save-button"
|
||||
>
|
||||
<button type="submit" data-cy="room-form-save" class="button button--primary room-form__save-button">
|
||||
Speichern
|
||||
</button>
|
||||
<router-link
|
||||
to="/rooms"
|
||||
class="button"
|
||||
>
|
||||
Abbrechen
|
||||
</router-link>
|
||||
<router-link to="/rooms" class="button"> Abbrechen </router-link>
|
||||
</template>
|
||||
</page-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ColorChooser from '@/components/ColorChooser';
|
||||
import PageForm from '@/components/page-form/PageForm';
|
||||
import PageFormInput from '@/components/page-form/PageFormInput';
|
||||
import ColorChooser from '@/components/ColorChooser';
|
||||
import PageForm from '@/components/page-form/PageForm';
|
||||
import PageFormInput from '@/components/page-form/PageFormInput';
|
||||
|
||||
import ME_QUERY from '@/graphql/gql/queries/meQuery.gql';
|
||||
import ME_QUERY from '@/graphql/gql/queries/meQuery.gql';
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: ['room'],
|
||||
|
||||
components: {
|
||||
ColorChooser,
|
||||
PageForm,
|
||||
PageFormInput
|
||||
PageFormInput,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
localRoom: Object.assign({}, this.room),
|
||||
me: {}
|
||||
me: {},
|
||||
};
|
||||
},
|
||||
|
||||
|
|
@ -75,21 +50,21 @@
|
|||
updateColor(newColor) {
|
||||
this.localRoom.appearance = newColor;
|
||||
this.$store.dispatch('setSpecialContainerClass', newColor);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
apollo: {
|
||||
me: {
|
||||
query: ME_QUERY,
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.room-form {
|
||||
.room-form {
|
||||
&__property-heading {
|
||||
@include page-form-input-heading;
|
||||
}
|
||||
|
|
@ -103,5 +78,5 @@
|
|||
&__save-button {
|
||||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -8,22 +8,22 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const Group = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/Group.vue'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const Group = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/Group.vue'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: ['name'],
|
||||
|
||||
components: {
|
||||
Group
|
||||
}
|
||||
};
|
||||
Group,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.room-group-widget {
|
||||
.room-group-widget {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
opacity: 0.6;
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
}
|
||||
|
||||
& > span {
|
||||
@include room-widget-text-style;;
|
||||
}
|
||||
@include room-widget-text-style;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -13,29 +13,31 @@
|
|||
|
||||
<script>
|
||||
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const EyeIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/EyeIcon'));
|
||||
const ClosedEyeIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/ClosedEyeIcon'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const EyeIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/EyeIcon'));
|
||||
const ClosedEyeIcon = defineAsyncComponent(() =>
|
||||
import(/* webpackChunkName: "icons" */ '@/components/icons/ClosedEyeIcon')
|
||||
);
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
restricted: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
ClosedEyeIcon,
|
||||
EyeIcon
|
||||
}
|
||||
};
|
||||
EyeIcon,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.room-visibility-widget {
|
||||
.room-visibility-widget {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
opacity: 0.6;
|
||||
|
|
@ -49,6 +51,5 @@
|
|||
& > span {
|
||||
@include room-widget-text-style;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
<template>
|
||||
<div
|
||||
:class="roomClass"
|
||||
class="room-widget"
|
||||
>
|
||||
<router-link
|
||||
:to="{name: 'room', params: {slug: slug}}"
|
||||
class="room-widget__content"
|
||||
>
|
||||
<div :class="roomClass" class="room-widget">
|
||||
<router-link :to="{ name: 'room', params: { slug: slug } }" class="room-widget__content">
|
||||
<h2 class="room-widget__title">
|
||||
{{ title }}
|
||||
</h2>
|
||||
|
|
|
|||
|
|
@ -1,25 +1,12 @@
|
|||
<template>
|
||||
<div class="rooms-onboarding">
|
||||
<h1
|
||||
class="rooms-onboarding__heading"
|
||||
data-cy="page-title"
|
||||
>
|
||||
Räume
|
||||
</h1>
|
||||
<h1 class="rooms-onboarding__heading" data-cy="page-title">Räume</h1>
|
||||
<rooms-illustration class="rooms-onboarding__illustration" />
|
||||
<p
|
||||
data-cy="rooms-onboarding-text"
|
||||
class="rooms-onboarding__text"
|
||||
>
|
||||
<p data-cy="rooms-onboarding-text" class="rooms-onboarding__text">
|
||||
Hier können Sie Räume erstellen, damit SchülerInnen zusammenarbeiten und Beiträge teilen können.
|
||||
</p>
|
||||
<div class="rooms-onboarding__button">
|
||||
<router-link
|
||||
:to="newRoomRoute"
|
||||
class="button button--primary"
|
||||
data-cy="create-room-button"
|
||||
v-if="isTeacher"
|
||||
>
|
||||
<router-link :to="newRoomRoute" class="button button--primary" data-cy="create-room-button" v-if="isTeacher">
|
||||
Raum erstellen
|
||||
</router-link>
|
||||
</div>
|
||||
|
|
@ -27,31 +14,33 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {NEW_ROOM_PAGE} from '@/router/room.names';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const RoomsIllustration = defineAsyncComponent(() => import(/* webpackChunkName: "illustrations" */'@/components/illustrations/RoomsIllustration'));
|
||||
import { NEW_ROOM_PAGE } from '@/router/room.names';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const RoomsIllustration = defineAsyncComponent(() =>
|
||||
import(/* webpackChunkName: "illustrations" */ '@/components/illustrations/RoomsIllustration')
|
||||
);
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
isTeacher: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
components: {RoomsIllustration},
|
||||
components: { RoomsIllustration },
|
||||
|
||||
data() {
|
||||
return {
|
||||
newRoomRoute: NEW_ROOM_PAGE,
|
||||
};
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
@import '~styles/helpers';
|
||||
|
||||
.rooms-onboarding {
|
||||
.rooms-onboarding {
|
||||
@include onboarding-page;
|
||||
|
||||
&__heading {
|
||||
|
|
@ -65,5 +54,5 @@
|
|||
&__text {
|
||||
@include onboarding-text;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -13,12 +13,7 @@
|
|||
/>
|
||||
<chevron-down class="selected-class__dropdown-icon" />
|
||||
</div>
|
||||
<widget-popover
|
||||
:mobile="mobile"
|
||||
class="class-selection__popover"
|
||||
v-if="showPopover"
|
||||
@hide-me="showPopover = false"
|
||||
>
|
||||
<widget-popover :mobile="mobile" class="class-selection__popover" v-if="showPopover" @hide-me="showPopover = false">
|
||||
<li
|
||||
:label="schoolClass.name"
|
||||
:item="schoolClass"
|
||||
|
|
@ -59,8 +54,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import WidgetPopover from '@/components/ui/WidgetPopover';
|
||||
import CurrentClass from '@/components/school-class/CurrentClass';
|
||||
import WidgetPopover from '@/components/ui/WidgetPopover';
|
||||
import CurrentClass from '@/components/school-class/CurrentClass';
|
||||
|
||||
import updateSelectedClassMixin from '@/mixins/update-selected-class';
|
||||
import sidebarMixin from '@/mixins/sidebar';
|
||||
|
|
@ -69,13 +64,12 @@
|
|||
const ChevronDown = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/ChevronDown'));
|
||||
const AddIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/AddIcon'));
|
||||
|
||||
export default {
|
||||
|
||||
export default {
|
||||
props: {
|
||||
mobile: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
mixins: [updateSelectedClassMixin, sidebarMixin, meMixin],
|
||||
|
|
@ -83,22 +77,22 @@
|
|||
WidgetPopover,
|
||||
ChevronDown,
|
||||
CurrentClass,
|
||||
AddIcon
|
||||
AddIcon,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
showPopover: false
|
||||
showPopover: false,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
currentClassSelection() {
|
||||
let currentClass = this.me.schoolClasses.find(schoolClass => {
|
||||
let currentClass = this.me.schoolClasses.find((schoolClass) => {
|
||||
return schoolClass.id === this.me.selectedClass.id;
|
||||
});
|
||||
return currentClass || this.me.schoolClasses[0];
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
@ -111,14 +105,14 @@
|
|||
this.closeSidebar('profile');
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.class-selection {
|
||||
.class-selection {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
margin-bottom: $medium-spacing;
|
||||
|
|
@ -130,10 +124,9 @@
|
|||
left: 0;
|
||||
transform: translateY($small-spacing);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.selected-class {
|
||||
.selected-class {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: $small-spacing 0;
|
||||
|
|
@ -153,5 +146,5 @@
|
|||
height: 20px;
|
||||
fill: $color-charcoal-dark;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,27 +1,24 @@
|
|||
<template>
|
||||
<span
|
||||
class="current-class"
|
||||
data-cy="current-class-name"
|
||||
>{{ currentClassName }}</span>
|
||||
<span class="current-class" data-cy="current-class-name">{{ currentClassName }}</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import me from '@/mixins/me';
|
||||
import me from '@/mixins/me';
|
||||
|
||||
export default {
|
||||
export default {
|
||||
mixins: [me],
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
@import '@/styles/_variables.scss';
|
||||
@import '@/styles/_mixins.scss';
|
||||
|
||||
.current-class {
|
||||
.current-class {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-self: center;
|
||||
line-height: 1;
|
||||
@include regular-text;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -6,26 +6,19 @@
|
|||
class="base-input-container__input"
|
||||
data-cy="base-input-input"
|
||||
@change.prevent="$emit('input', $event.target.checked, item)"
|
||||
>
|
||||
/>
|
||||
<span
|
||||
:class="{'base-input-container__checkbox': type==='checkbox', 'base-input-container__radiobutton': type === 'radiobutton'}"
|
||||
:class="{
|
||||
'base-input-container__checkbox': type === 'checkbox',
|
||||
'base-input-container__radiobutton': type === 'radiobutton',
|
||||
}"
|
||||
class="base-input-container__icon checkbox"
|
||||
>
|
||||
<tick v-if="type === 'checkbox'" />
|
||||
<circle-icon
|
||||
data-cy="circle-icon"
|
||||
v-if="type === 'radiobutton'"
|
||||
/>
|
||||
<circle-icon data-cy="circle-icon" v-if="type === 'radiobutton'" />
|
||||
</span>
|
||||
<span
|
||||
class="base-input-container__label"
|
||||
data-cy="base-input-label"
|
||||
v-if="label"
|
||||
>{{ label }}</span>
|
||||
<slot
|
||||
class="base-input-container__label"
|
||||
v-if="!label"
|
||||
/>
|
||||
<span class="base-input-container__label" data-cy="base-input-label" v-if="label">{{ label }}</span>
|
||||
<slot class="base-input-container__label" v-if="!label" />
|
||||
</label>
|
||||
</template>
|
||||
|
||||
|
|
@ -34,19 +27,19 @@
|
|||
const Tick = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/Tick'));
|
||||
const CircleIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/CircleIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
label: String,
|
||||
checked: {
|
||||
type: Boolean
|
||||
type: Boolean,
|
||||
},
|
||||
item: Object,
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
|
||||
components: {
|
||||
Tick,
|
||||
CircleIcon
|
||||
}
|
||||
};
|
||||
CircleIcon,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,27 +1,19 @@
|
|||
<template>
|
||||
<li
|
||||
class="popover-links__link"
|
||||
>
|
||||
<a
|
||||
class="popover-link"
|
||||
@click="$emit('link-action')"
|
||||
>
|
||||
<component
|
||||
class="popover-link__icon"
|
||||
:is="icon"
|
||||
/>
|
||||
<li class="popover-links__link">
|
||||
<a class="popover-link" @click="$emit('link-action')">
|
||||
<component class="popover-link__icon" :is="icon" />
|
||||
<span class="popover-link__text">{{ text }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const EyeIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/EyeIcon'));
|
||||
const TrashIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/TrashIcon'));
|
||||
const PenIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/PenIcon'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const EyeIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/EyeIcon'));
|
||||
const TrashIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/TrashIcon'));
|
||||
const PenIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/PenIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
icon: {
|
||||
type: String,
|
||||
|
|
@ -37,13 +29,13 @@
|
|||
TrashIcon,
|
||||
PenIcon,
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
@import '~styles/helpers';
|
||||
|
||||
.popover-link {
|
||||
.popover-link {
|
||||
@include popover-link;
|
||||
|
||||
&__icon {
|
||||
|
|
@ -61,5 +53,5 @@
|
|||
flex-basis: auto;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
<template>
|
||||
<div class="file-upload">
|
||||
<template v-if="document">
|
||||
<document-block
|
||||
:value="{url: document}"
|
||||
show-trash-icon
|
||||
@trash="$emit('change-document-url', '')"
|
||||
/>
|
||||
<document-block :value="{ url: document }" show-trash-icon @trash="$emit('change-document-url', '')" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<simple-file-upload
|
||||
|
|
@ -18,11 +14,13 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const SimpleFileUpload = defineAsyncComponent(() => import('@/components/ui/file-upload/SimpleFileUpload'));
|
||||
const DocumentBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/DocumentBlock'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const SimpleFileUpload = defineAsyncComponent(() => import('@/components/ui/file-upload/SimpleFileUpload'));
|
||||
const DocumentBlock = defineAsyncComponent(() =>
|
||||
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/DocumentBlock')
|
||||
);
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
document: {
|
||||
type: String,
|
||||
|
|
@ -30,14 +28,13 @@
|
|||
},
|
||||
withText: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
components: {SimpleFileUpload, DocumentBlock},
|
||||
};
|
||||
},
|
||||
components: { SimpleFileUpload, DocumentBlock },
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
|
||||
@import '~styles/helpers';
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -5,21 +5,23 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const DocumentIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/DocumentIcon'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const DocumentIcon = defineAsyncComponent(() =>
|
||||
import(/* webpackChunkName: "icons" */ '@/components/icons/DocumentIcon')
|
||||
);
|
||||
|
||||
export default {
|
||||
components: {DocumentIcon},
|
||||
};
|
||||
export default {
|
||||
components: { DocumentIcon },
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
@import '~styles/helpers';
|
||||
|
||||
.simple-file-upload-icon {
|
||||
.simple-file-upload-icon {
|
||||
&__icon {
|
||||
width: 25px;
|
||||
fill: $color-silver-dark;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -30,5 +30,5 @@ export default {
|
|||
ArrowThinDown,
|
||||
ArrowThinTop,
|
||||
ArrowThinUp,
|
||||
TrashIcon
|
||||
TrashIcon,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
<template>
|
||||
<div
|
||||
class="skillboxform-input"
|
||||
>
|
||||
<label
|
||||
:for="id"
|
||||
class="skillboxform-input__label"
|
||||
>
|
||||
<div class="skillboxform-input">
|
||||
<label :for="id" class="skillboxform-input__label">
|
||||
{{ label }}
|
||||
</label>
|
||||
<slot :id="id" />
|
||||
|
|
@ -13,8 +8,8 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
defineProps({
|
||||
defineProps({
|
||||
id: String,
|
||||
label: String
|
||||
}) ;
|
||||
label: String,
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,59 +1,51 @@
|
|||
<template>
|
||||
<div class="visibility-action">
|
||||
<a
|
||||
class="visibility-action__action-button"
|
||||
v-if="canManageContent"
|
||||
@click="toggleVisibility()"
|
||||
>
|
||||
<closed-eye-icon
|
||||
class="visibility-action__action-icon action-icon"
|
||||
v-if="hidden"
|
||||
/>
|
||||
<eye-icon
|
||||
class="visibility-action__action-icon action-icon"
|
||||
v-else
|
||||
/>
|
||||
<a class="visibility-action__action-button" v-if="canManageContent" @click="toggleVisibility()">
|
||||
<closed-eye-icon class="visibility-action__action-icon action-icon" v-if="hidden" />
|
||||
<eye-icon class="visibility-action__action-icon action-icon" v-else />
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import me from '@/mixins/me';
|
||||
import me from '@/mixins/me';
|
||||
|
||||
import {TYPES, CONTENT_TYPE} from '@/consts/types';
|
||||
import {createVisibilityMutation, hidden} from '@/helpers/visibility';
|
||||
import { TYPES, CONTENT_TYPE } from '@/consts/types';
|
||||
import { createVisibilityMutation, hidden } from '@/helpers/visibility';
|
||||
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const EyeIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/EyeIcon'));
|
||||
const ClosedEyeIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/ClosedEyeIcon'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const EyeIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/EyeIcon'));
|
||||
const ClosedEyeIcon = defineAsyncComponent(() =>
|
||||
import(/* webpackChunkName: "icons" */ '@/components/icons/ClosedEyeIcon')
|
||||
);
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
block: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
default: () => ({}),
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: CONTENT_TYPE,
|
||||
validator: value => {
|
||||
validator: (value) => {
|
||||
// value must be one of TYPES
|
||||
return TYPES.indexOf(value) !== -1;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
mixins: [me],
|
||||
|
||||
components: {
|
||||
EyeIcon,
|
||||
ClosedEyeIcon
|
||||
ClosedEyeIcon,
|
||||
},
|
||||
|
||||
computed: {
|
||||
hidden() {
|
||||
return hidden({type: this.type, block: this.block, schoolClass: this.schoolClass});
|
||||
}
|
||||
return hidden({ type: this.type, block: this.block, schoolClass: this.schoolClass });
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
@ -61,24 +53,26 @@
|
|||
const hidden = !this.hidden;
|
||||
const schoolClassId = this.schoolClass.id;
|
||||
|
||||
const visibility = [{
|
||||
const visibility = [
|
||||
{
|
||||
schoolClassId,
|
||||
hidden
|
||||
}];
|
||||
hidden,
|
||||
},
|
||||
];
|
||||
|
||||
const {mutation, variables} = createVisibilityMutation(this.type, this.block.id, visibility);
|
||||
const { mutation, variables } = createVisibilityMutation(this.type, this.block.id, visibility);
|
||||
|
||||
this.$apollo.mutate({
|
||||
mutation,
|
||||
variables
|
||||
variables,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.visibility-action {
|
||||
.visibility-action {
|
||||
margin-top: 9px;
|
||||
|
||||
position: absolute;
|
||||
|
|
@ -89,5 +83,5 @@
|
|||
&__visibility-menu {
|
||||
top: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,56 +1,29 @@
|
|||
<template>
|
||||
<footer
|
||||
class="default-footer"
|
||||
data-cy="page-footer"
|
||||
>
|
||||
<footer class="default-footer" data-cy="page-footer">
|
||||
<div class="default-footer__section">
|
||||
<div class="default-footer__info">
|
||||
<div class="default-footer__who-are-we who-are-we">
|
||||
<h5 class="who-are-we__title">
|
||||
Wer sind wir?
|
||||
</h5>
|
||||
<h5 class="who-are-we__title">Wer sind wir?</h5>
|
||||
<p class="who-are-we__text">
|
||||
mySkillbox ist ein Angebot des hep Verlags in
|
||||
Zusammenarbeit mit der Eidgenössischen Hochschule für Berufsbildung (EHB).
|
||||
mySkillbox ist ein Angebot des hep Verlags in Zusammenarbeit mit der Eidgenössischen Hochschule für
|
||||
Berufsbildung (EHB).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<a
|
||||
href="https://www.hep-verlag.ch/"
|
||||
target="_blank"
|
||||
>
|
||||
<a href="https://www.hep-verlag.ch/" target="_blank">
|
||||
<hep-logo class="default-footer__logo-hep" />
|
||||
</a>
|
||||
<a
|
||||
href="https://www.ehb.swiss/"
|
||||
target="_blank"
|
||||
>
|
||||
<a href="https://www.ehb.swiss/" target="_blank">
|
||||
<ehb-logo class="default-footer__logo-ehb" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="default-footer__section">
|
||||
<div class="default-footer__links">
|
||||
<a
|
||||
href="https://myskillbox.ch/datenschutz"
|
||||
target="_blank"
|
||||
class="default-footer__link"
|
||||
>Datenschutz</a>
|
||||
<a
|
||||
href="https://myskillbox.ch/impressum"
|
||||
target="_blank"
|
||||
class="default-footer__link"
|
||||
>Impressum</a>
|
||||
<a
|
||||
href="https://myskillbox.ch/agb"
|
||||
target="_blank"
|
||||
class="default-footer__link"
|
||||
>AGB</a>
|
||||
<a
|
||||
:href="$flavor.supportLink"
|
||||
target="_blank"
|
||||
class="default-footer__link"
|
||||
>Support</a>
|
||||
<a href="https://myskillbox.ch/datenschutz" target="_blank" class="default-footer__link">Datenschutz</a>
|
||||
<a href="https://myskillbox.ch/impressum" target="_blank" class="default-footer__link">Impressum</a>
|
||||
<a href="https://myskillbox.ch/agb" target="_blank" class="default-footer__link">AGB</a>
|
||||
<a :href="$flavor.supportLink" target="_blank" class="default-footer__link">Support</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
|
@ -62,19 +35,19 @@
|
|||
const HepLogo = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/HepLogo'));
|
||||
const EhbLogo = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/EhbLogo'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
HepLogo,
|
||||
EhbLogo
|
||||
}
|
||||
};
|
||||
EhbLogo,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
@import '@/styles/_variables.scss';
|
||||
@import '@/styles/_mixins.scss';
|
||||
|
||||
.default-footer {
|
||||
.default-footer {
|
||||
background-color: $color-silver-light;
|
||||
max-width: 100vw;
|
||||
overflow: hidden;
|
||||
|
|
@ -89,7 +62,7 @@
|
|||
&__info {
|
||||
width: 100%;
|
||||
max-width: $footer-width;
|
||||
padding: 2*$large-spacing 0;
|
||||
padding: 2 * $large-spacing 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
|
|
@ -146,9 +119,9 @@
|
|||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.who-are-we {
|
||||
.who-are-we {
|
||||
&__title {
|
||||
@include heading-4;
|
||||
}
|
||||
|
|
@ -156,5 +129,5 @@
|
|||
&__text {
|
||||
@include aside-text;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
<template>
|
||||
<div
|
||||
:class="specialContainerClass"
|
||||
class="container layout layout--fullscreen"
|
||||
>
|
||||
<div
|
||||
class="close-button"
|
||||
@click="back"
|
||||
>
|
||||
<div :class="specialContainerClass" class="container layout layout--fullscreen">
|
||||
<div class="close-button" @click="back">
|
||||
<cross class="close-button__icon" />
|
||||
</div>
|
||||
|
||||
|
|
@ -15,39 +9,38 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const Cross = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/CrossIcon'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const Cross = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/CrossIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
Cross
|
||||
Cross,
|
||||
},
|
||||
|
||||
computed: {
|
||||
specialContainerClass() {
|
||||
let cls = this.$store.state.specialContainerClass;
|
||||
return [cls ? `skillbox--${cls}` : ''];
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
back() {
|
||||
this.$router.go(-1);
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/styles/_default-layout.scss";
|
||||
@import '@/styles/_default-layout.scss';
|
||||
|
||||
.close-button {
|
||||
.close-button {
|
||||
margin-top: $medium-spacing;
|
||||
margin-right: $medium-spacing;
|
||||
justify-self: end;
|
||||
cursor: pointer;
|
||||
|
||||
display:flex;
|
||||
justify-content:flex-end;
|
||||
}
|
||||
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,57 +1,51 @@
|
|||
<template>
|
||||
<div class="layout layout--public public">
|
||||
<div class="public__logo">
|
||||
<router-link
|
||||
:to="{name: 'hello'}"
|
||||
class="hep-link"
|
||||
>
|
||||
<router-link :to="{ name: 'hello' }" class="hep-link">
|
||||
<logo />
|
||||
</router-link>
|
||||
</div>
|
||||
<router-view class="public__content layout__content" />
|
||||
<default-footer
|
||||
class="skillbox__footer public__footer footer"
|
||||
v-if="$flavor.showFooter"
|
||||
/>
|
||||
<default-footer class="skillbox__footer public__footer footer" v-if="$flavor.showFooter" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
import DefaultFooter from '@/layouts/DefaultFooter';
|
||||
const Logo = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/Logo'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
import DefaultFooter from '@/layouts/DefaultFooter';
|
||||
const Logo = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/Logo'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
Logo,
|
||||
DefaultFooter
|
||||
DefaultFooter,
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
@import "@/styles/_default-layout.scss";
|
||||
@import '@/styles/_variables.scss';
|
||||
@import '@/styles/_mixins.scss';
|
||||
@import '@/styles/_default-layout.scss';
|
||||
|
||||
@mixin content-block {
|
||||
@mixin content-block {
|
||||
padding-right: $medium-spacing;
|
||||
padding-left: $medium-spacing;
|
||||
max-width: 800px;
|
||||
min-width: 320px;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
.logo {
|
||||
position: relative;
|
||||
|
||||
width: auto;
|
||||
height: 43px;
|
||||
}
|
||||
}
|
||||
|
||||
.public {
|
||||
grid-template-areas: "h" "c" "f";
|
||||
.public {
|
||||
grid-template-areas: 'h' 'c' 'f';
|
||||
|
||||
&__content {
|
||||
@include content-block();
|
||||
|
|
@ -61,20 +55,20 @@
|
|||
|
||||
&__logo {
|
||||
@include content-block();
|
||||
margin-top: $medium-spacing
|
||||
margin-top: $medium-spacing;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
background-color: $color-silver-light;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
.footer {
|
||||
padding: $large-spacing $medium-spacing 0;
|
||||
|
||||
&__content {
|
||||
@include content-block();
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,31 +1,22 @@
|
|||
<template>
|
||||
<div
|
||||
:class="{'layout--full-width': $route.meta.fullWidth}"
|
||||
class="skillbox layout layout--simple"
|
||||
>
|
||||
<div
|
||||
class="close-button"
|
||||
@click="back"
|
||||
>
|
||||
<div :class="{ 'layout--full-width': $route.meta.fullWidth }" class="skillbox layout layout--simple">
|
||||
<div class="close-button" @click="back">
|
||||
<cross class="close-button__icon" />
|
||||
</div>
|
||||
<router-view class="layout__content" />
|
||||
<simple-footer
|
||||
class="layout__footer"
|
||||
v-if="enableFooter"
|
||||
/>
|
||||
<simple-footer class="layout__footer" v-if="enableFooter" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SimpleFooter from '@/layouts/SimpleFooter';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const Cross = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/CrossIcon'));
|
||||
import SimpleFooter from '@/layouts/SimpleFooter';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const Cross = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/CrossIcon'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
Cross,
|
||||
SimpleFooter
|
||||
SimpleFooter,
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
|
@ -34,21 +25,21 @@
|
|||
return false;
|
||||
}
|
||||
return this.$flavor.showFooter;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
back() {
|
||||
this.$router.go(-1);
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.layout {
|
||||
.layout {
|
||||
&--simple {
|
||||
display: -ms-grid;
|
||||
@supports (display: grid) {
|
||||
|
|
@ -83,14 +74,14 @@
|
|||
grid-column: 1 / span 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.close-button {
|
||||
.close-button {
|
||||
justify-self: end;
|
||||
cursor: pointer;
|
||||
|
||||
display:flex;
|
||||
justify-content:flex-end;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
margin-right: $small-spacing;
|
||||
margin-top: $small-spacing;
|
||||
|
|
@ -103,5 +94,5 @@
|
|||
margin-right: $medium-spacing;
|
||||
margin-top: $medium-spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div :class="['split-view', {'split-view--illustration': illustration}]">
|
||||
<div :class="['split-view', { 'split-view--illustration': illustration }]">
|
||||
<div :class="['split-view__illustration', illustrationAlignment]">
|
||||
<component :is="illustration" />
|
||||
</div>
|
||||
|
|
@ -19,12 +19,12 @@
|
|||
const HelloMyKVIllustration = defineAsyncComponent(() => import(/* webpackChunkName: "illustrations" */'@/components/illustrations/HelloMyKVIllustration'));
|
||||
const Hello = flavorValues.appFlavor === 'my-kv' ? HelloMyKVIllustration : HelloIllustration;
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
contents: ContentsIllustration,
|
||||
portfolio: PortfolioIllustration,
|
||||
rooms: RoomsIllustration,
|
||||
hello: Hello
|
||||
hello: Hello,
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
|
@ -32,16 +32,18 @@
|
|||
return this.$route.meta.illustration;
|
||||
},
|
||||
illustrationAlignment() {
|
||||
return this.$route.meta.illustrationAlign ? `split-view__illustration--${this.$route.meta.illustrationAlign}` : '';
|
||||
}
|
||||
return this.$route.meta.illustrationAlign
|
||||
? `split-view__illustration--${this.$route.meta.illustrationAlign}`
|
||||
: '';
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.split-view {
|
||||
.split-view {
|
||||
background-color: $color-brand;
|
||||
|
||||
display: flex;
|
||||
|
|
@ -94,7 +96,7 @@
|
|||
width: 100%;
|
||||
|
||||
@include desktop {
|
||||
padding: 2*$large-spacing;
|
||||
padding: 2 * $large-spacing;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +119,7 @@
|
|||
&__page-heading {
|
||||
@include heading-2;
|
||||
color: $color-brand;
|
||||
margin-bottom: 2*$large-spacing;
|
||||
margin-bottom: 2 * $large-spacing;
|
||||
}
|
||||
|
||||
&__heading {
|
||||
|
|
@ -135,7 +137,7 @@
|
|||
margin-bottom: $medium-spacing;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 2*$large-spacing;
|
||||
margin-bottom: 2 * $large-spacing;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -159,5 +161,5 @@
|
|||
margin-top: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -126,11 +126,12 @@
|
|||
|
||||
const redirectUrl = this.$route.query.redirect ? this.$route.query.redirect : '/';
|
||||
|
||||
this.$apollo.mutate({
|
||||
this.$apollo
|
||||
.mutate({
|
||||
client: 'publicClient',
|
||||
mutation: BETA_LOGIN_MUTATION,
|
||||
variables,
|
||||
update: (store, {data: {betaLogin}}) => {
|
||||
update: (store, { data: { betaLogin } }) => {
|
||||
try {
|
||||
if (betaLogin.success) {
|
||||
console.log(this);
|
||||
|
|
@ -141,7 +142,8 @@
|
|||
this.loginError = 'Es ist ein Fehler aufgetreten. Bitte versuchen Sie nochmals.';
|
||||
}
|
||||
},
|
||||
}).catch(error => {
|
||||
})
|
||||
.catch((error) => {
|
||||
const firstError = error.graphQLErrors[0];
|
||||
switch (firstError.message) {
|
||||
case 'invalid_credentials':
|
||||
|
|
@ -158,15 +160,14 @@
|
|||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.text-link {
|
||||
.text-link {
|
||||
font-family: $sans-serif-font-family;
|
||||
color: $color-brand;
|
||||
}
|
||||
|
||||
.actions {
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
|
|
@ -176,6 +177,5 @@
|
|||
padding: 15px;
|
||||
line-height: 19px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,20 +1,15 @@
|
|||
<template>
|
||||
<content-block-form
|
||||
title="Inhaltsblock erfassen"
|
||||
:content-block="contentBlock"
|
||||
@back="goToModule"
|
||||
@save="save"
|
||||
/>
|
||||
<content-block-form title="Inhaltsblock erfassen" :content-block="contentBlock" @back="goToModule" @save="save" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {defineComponent} from 'vue';
|
||||
|
||||
import ContentBlockForm from '@/components/content-block-form/ContentBlockForm';
|
||||
import {setUserBlockType} from '@/helpers/content-block';
|
||||
import NEW_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/addContentBlock.gql';
|
||||
import MODULE_DETAILS_QUERY from '@/graphql/gql/queries/modules/moduleDetailsQuery.gql';
|
||||
import {cleanUpContents} from '@/components/content-block-form/helpers';
|
||||
import ContentBlockForm from '@/components/content-block-form/ContentBlockForm';
|
||||
import { setUserBlockType } from '@/helpers/content-block';
|
||||
import NEW_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/addContentBlock.gql';
|
||||
import MODULE_DETAILS_QUERY from '@/graphql/gql/queries/modules/moduleDetailsQuery.gql';
|
||||
import { cleanUpContents } from '@/components/content-block-form/helpers';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
|
|
@ -27,6 +22,7 @@
|
|||
default: ''
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
ContentBlockForm,
|
||||
|
|
@ -36,12 +32,12 @@
|
|||
contentBlock: {
|
||||
title: '',
|
||||
isAssignment: false,
|
||||
contents: [
|
||||
]},
|
||||
contents: [],
|
||||
},
|
||||
}),
|
||||
|
||||
methods: {
|
||||
save({title, contents, isAssignment}) {
|
||||
save({ title, contents, isAssignment }) {
|
||||
let cleanedContents = cleanUpContents(contents);
|
||||
const contentBlock = {
|
||||
title: title,
|
||||
|
|
@ -50,36 +46,38 @@
|
|||
};
|
||||
let input;
|
||||
const { parent, after, slug } = this.$route.params;
|
||||
if(after) {
|
||||
if (after) {
|
||||
input = {
|
||||
contentBlock,
|
||||
after
|
||||
after,
|
||||
};
|
||||
} else {
|
||||
input = {
|
||||
contentBlock,
|
||||
parent
|
||||
parent,
|
||||
};
|
||||
}
|
||||
this.$apollo.mutate({
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: NEW_CONTENT_BLOCK_MUTATION,
|
||||
variables: {
|
||||
input
|
||||
input,
|
||||
},
|
||||
refetchQueries: [{
|
||||
refetchQueries: [
|
||||
{
|
||||
query: MODULE_DETAILS_QUERY,
|
||||
variables: {
|
||||
slug
|
||||
}
|
||||
}]
|
||||
}).then(this.goToModule);
|
||||
slug,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
.then(this.goToModule);
|
||||
},
|
||||
goToModule() {
|
||||
// use the history, so the scroll position is preserved
|
||||
this.$router.go(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,64 +1,39 @@
|
|||
<template>
|
||||
<div
|
||||
class="hello"
|
||||
data-cy="hello-page"
|
||||
>
|
||||
<div class="hello" data-cy="hello-page">
|
||||
<div class="about">
|
||||
<div class="about__logos logos">
|
||||
<a
|
||||
href="https://www.hep-verlag.ch/"
|
||||
target="_blank"
|
||||
>
|
||||
<a href="https://www.hep-verlag.ch/" target="_blank">
|
||||
<hep-logo-no-claim class="logos__logo" />
|
||||
</a>
|
||||
<a
|
||||
href="https://www.ehb.swiss/"
|
||||
target="_blank"
|
||||
v-if="$flavor.showEHB"
|
||||
>
|
||||
<a href="https://www.ehb.swiss/" target="_blank" v-if="$flavor.showEHB">
|
||||
<ehb-logo class="logos__logo" />
|
||||
</a>
|
||||
</div>
|
||||
<p class="about__text">
|
||||
<template v-if="$flavor.showEHB">
|
||||
{{ $flavor.textAppName }} ist ein Angebot des hep Verlags in
|
||||
Zusammenarbeit mit der Eidgenössischen Hochschule für Berufsbildung (EHB).
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ $flavor.textAppName }} ist ein Angebot des hep Verlags.
|
||||
{{ $flavor.textAppName }} ist ein Angebot des hep Verlags in Zusammenarbeit mit der Eidgenössischen Hochschule
|
||||
für Berufsbildung (EHB).
|
||||
</template>
|
||||
<template v-else> {{ $flavor.textAppName }} ist ein Angebot des hep Verlags. </template>
|
||||
</p>
|
||||
</div>
|
||||
<logo class="logo" />
|
||||
<div class="login-actions">
|
||||
<h2
|
||||
class="login-actions__title"
|
||||
data-cy="hello-title"
|
||||
>
|
||||
<h2 class="login-actions__title" data-cy="hello-title">
|
||||
Wollen Sie {{ $flavor.textAppName }} im Unterricht verwenden?
|
||||
</h2>
|
||||
<a
|
||||
class="button button--primary button--big actions__submit"
|
||||
href="/api/oauth/login/"
|
||||
data-cy="oauth-login"
|
||||
>Mit hep Konto anmelden</a>
|
||||
<a class="button button--primary button--big actions__submit" href="/api/oauth/login/" data-cy="oauth-login"
|
||||
>Mit hep Konto anmelden</a
|
||||
>
|
||||
|
||||
<div class="login-actions__register register">
|
||||
<p>Haben Sie noch kein hep Konto?</p>
|
||||
<a
|
||||
class="hep-link"
|
||||
href="/api/oauth/login/"
|
||||
data-cy="oauth-login"
|
||||
>Jetzt registrieren</a>
|
||||
<a class="hep-link" href="/api/oauth/login/" data-cy="oauth-login">Jetzt registrieren</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="information">
|
||||
<p>Was ist ein hep Konto und wie kann ich mich dafür registrieren?</p>
|
||||
<a
|
||||
class="hep-link"
|
||||
href="https://myskillbox.ch/anleitung"
|
||||
data-cy="oauth-login"
|
||||
>Anleitung anschauen</a>
|
||||
<a class="hep-link" href="https://myskillbox.ch/anleitung" data-cy="oauth-login">Anleitung anschauen</a>
|
||||
</div>
|
||||
<div class="links">
|
||||
<ul class="links__list">
|
||||
|
|
@ -82,39 +57,38 @@
|
|||
const EhbLogo = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/EhbLogo'));
|
||||
const Logo = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/Logo'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
HepLogoNoClaim,
|
||||
EhbLogo,
|
||||
Logo
|
||||
Logo,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
email: '',
|
||||
submitted: false,
|
||||
loading: false
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
$hello-block-margin: 2*$medium-spacing;
|
||||
$hello-block-margin: 2 * $medium-spacing;
|
||||
|
||||
.hello {
|
||||
.hello {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
@include desktop {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
.logo {
|
||||
display: block;
|
||||
width: 300px;
|
||||
margin: $small-spacing auto $hello-block-margin;
|
||||
|
|
@ -122,9 +96,9 @@
|
|||
@include desktop {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.about {
|
||||
.about {
|
||||
display: none;
|
||||
margin-bottom: $hello-block-margin;
|
||||
|
||||
|
|
@ -142,15 +116,15 @@
|
|||
margin-right: $large-spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.logos {
|
||||
.logos {
|
||||
&__logo {
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.login-actions {
|
||||
.login-actions {
|
||||
@include widget-shadow;
|
||||
padding: $medium-spacing;
|
||||
margin-bottom: $hello-block-margin;
|
||||
|
|
@ -163,25 +137,26 @@
|
|||
&__register {
|
||||
margin-top: $large-spacing;
|
||||
|
||||
> p, a {
|
||||
> p,
|
||||
a {
|
||||
@include regular-text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.information {
|
||||
.information {
|
||||
margin-top: $hello-block-margin;
|
||||
> p, a {
|
||||
> p,
|
||||
a {
|
||||
@include regular-text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.links {
|
||||
.links {
|
||||
margin-top: $hello-block-margin;
|
||||
display: flex;
|
||||
|
||||
&__list-item {
|
||||
|
||||
color: $color-silver-dark;
|
||||
|
||||
> a {
|
||||
|
|
@ -204,6 +179,5 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -88,9 +88,10 @@ export default {
|
|||
display: grid;
|
||||
@include desktop {
|
||||
grid-template-columns: 300px auto;
|
||||
}
|
||||
grid-column-gap: $small-spacing;
|
||||
}grid-column-gap: $small-spacing;
|
||||
|
||||
padding: 0 $small-spacing;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
&__list {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
<div class="license-activation public-page">
|
||||
<header class="info-header">
|
||||
<p class="info-header__text small-emph">
|
||||
Für <span class="info-header__emph">{{ me.email }}</span> haben wir keine
|
||||
gültige Lizenz gefunden
|
||||
Für <span class="info-header__emph">{{ me.email }}</span> haben wir keine gültige Lizenz gefunden
|
||||
</p>
|
||||
</header>
|
||||
<section class="coupon">
|
||||
|
|
@ -67,16 +66,10 @@
|
|||
<h2>Oder, kaufen Sie eine Lizenz</h2>
|
||||
<ul class="license-links">
|
||||
<li class="license-links__item">
|
||||
<a
|
||||
:href="teacherEditionUrl"
|
||||
class="hep-link"
|
||||
>{{ $flavor.textAppName }} für Lehrpersonen</a>
|
||||
<a :href="teacherEditionUrl" class="hep-link">{{ $flavor.textAppName }} für Lehrpersonen</a>
|
||||
</li>
|
||||
<li class="license-links__item">
|
||||
<a
|
||||
:href="studentEditionUrl"
|
||||
class="hep-link"
|
||||
>{{ $flavor.textAppName }} für Lernende</a>
|
||||
<a :href="studentEditionUrl" class="hep-link">{{ $flavor.textAppName }} für Lernende</a>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
|
@ -84,16 +77,16 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {defineComponent} from 'vue';
|
||||
import REDEEM_COUPON from '@/graphql/gql/mutations/redeemCoupon.gql';
|
||||
import ME_QUERY from '@/graphql/gql/queries/meQuery.gql';
|
||||
import LoadingButton from '@/components/LoadingButton';
|
||||
import { defineComponent } from 'vue';
|
||||
import REDEEM_COUPON from '@/graphql/gql/mutations/redeemCoupon.gql';
|
||||
import ME_QUERY from '@/graphql/gql/queries/meQuery.gql';
|
||||
import LoadingButton from '@/components/LoadingButton';
|
||||
|
||||
import me from '@/mixins/me';
|
||||
import logout from '@/mixins/logout';
|
||||
import me from '@/mixins/me';
|
||||
import logout from '@/mixins/logout';
|
||||
|
||||
import {Form, Field, ErrorMessage} from 'vee-validate';
|
||||
import InputWrapper from '@/components/validation/InputWrapper';
|
||||
import { Form, Field, ErrorMessage } from 'vee-validate';
|
||||
import InputWrapper from '@/components/validation/InputWrapper';
|
||||
|
||||
export default defineComponent({
|
||||
mixins: [me, logout],
|
||||
|
|
@ -120,42 +113,43 @@
|
|||
};
|
||||
},
|
||||
methods: {
|
||||
required(value, {field}) {
|
||||
required(value, { field }) {
|
||||
if (value && value.trim()) {
|
||||
return true;
|
||||
}
|
||||
return `${field} ist ein Pflichtfeld`;
|
||||
},
|
||||
validateBeforeSubmit({coupon: couponCode}) {
|
||||
validateBeforeSubmit({ coupon: couponCode }) {
|
||||
console.log('coupon', couponCode);
|
||||
this.submitted = true;
|
||||
this.loading = true;
|
||||
this.$apollo.mutate({
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: REDEEM_COUPON,
|
||||
variables: {
|
||||
input: {
|
||||
couponCode
|
||||
},
|
||||
},
|
||||
update: (
|
||||
store,
|
||||
{
|
||||
data: {coupon},
|
||||
},
|
||||
) => {
|
||||
update: (store, { data: { coupon } }) => {
|
||||
if (coupon.success) {
|
||||
this.couponErrors = [];
|
||||
this.$apollo.query({
|
||||
this.$apollo
|
||||
.query({
|
||||
query: ME_QUERY,
|
||||
fetchPolicy: 'network-only',
|
||||
}).then(() => this.$router.push('/'));
|
||||
})
|
||||
.then(() => this.$router.push('/'));
|
||||
}
|
||||
},
|
||||
}).catch(({message}) => {
|
||||
})
|
||||
.catch(({ message }) => {
|
||||
if (message.indexOf('invalid_coupon') > -1) {
|
||||
this.couponErrors = ['Der angegebene Coupon-Code ist ungültig.'];
|
||||
} else {
|
||||
this.couponErrors = ['Es ist ein Fehler aufgetreten. Bitte versuchen Sie es nochmals oder kontaktieren Sie den Administrator.'];
|
||||
this.couponErrors = [
|
||||
'Es ist ein Fehler aufgetreten. Bitte versuchen Sie es nochmals oder kontaktieren Sie den Administrator.',
|
||||
];
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
|
|
@ -163,32 +157,31 @@
|
|||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~styles/helpers";
|
||||
@import '~styles/helpers';
|
||||
|
||||
.text-link {
|
||||
.text-link {
|
||||
font-family: $sans-serif-font-family;
|
||||
color: $color-brand;
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
.actions {
|
||||
&__reset {
|
||||
display: inline-block;
|
||||
margin-left: $large-spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.get-license {
|
||||
margin-top: $large-spacing
|
||||
}
|
||||
.get-license {
|
||||
margin-top: $large-spacing;
|
||||
}
|
||||
|
||||
.license-links {
|
||||
.license-links {
|
||||
&__item {
|
||||
margin-bottom: $medium-spacing;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
<template>
|
||||
<div class="module-visibility">
|
||||
<h1 class="module-visibility__page-title">
|
||||
Sichtbarkeit
|
||||
</h1>
|
||||
<h1 class="module-visibility__page-title">Sichtbarkeit</h1>
|
||||
<div class="module-visibility__section">
|
||||
<p class="module-visibility__paragraph">
|
||||
Wollen Sie die angepasste Sichtbarkeit (
|
||||
|
|
@ -18,44 +16,30 @@
|
|||
class="skillbox-input skillbox-dropdown module-visibility__dropdown"
|
||||
@change="select($event.target.value)"
|
||||
>
|
||||
<option
|
||||
value=""
|
||||
selected
|
||||
>
|
||||
-
|
||||
</option>
|
||||
<option
|
||||
:value="schoolClass.id"
|
||||
v-for="schoolClass in schoolClasses"
|
||||
:key="schoolClass.id"
|
||||
>
|
||||
<option value="" selected>-</option>
|
||||
<option :value="schoolClass.id" v-for="schoolClass in schoolClasses" :key="schoolClass.id">
|
||||
{{ schoolClass.name }}
|
||||
</option>
|
||||
</select>
|
||||
für {{ currentClassName }} übernehmen.
|
||||
</div>
|
||||
<div class="module-visibility__section">
|
||||
<a
|
||||
class="button button--primary"
|
||||
data-cy="save-visibility-button"
|
||||
@click="sync"
|
||||
>Anpassungen übernehmen</a>
|
||||
<a class="button button--primary" data-cy="save-visibility-button" @click="sync">Anpassungen übernehmen</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import me from '@/mixins/me';
|
||||
import me from '@/mixins/me';
|
||||
|
||||
import SYNC_VISIBILITY_MUTATION from '@/graphql/gql/mutations/syncModuleVisibility.gql';
|
||||
import MODULE_DETAILS_QUERY from '@/graphql/gql/queries/modules/moduleDetailsQuery';
|
||||
import {MODULE_PAGE} from '@/router/module.names';
|
||||
import SYNC_VISIBILITY_MUTATION from '@/graphql/gql/mutations/syncModuleVisibility.gql';
|
||||
import MODULE_DETAILS_QUERY from '@/graphql/gql/queries/modules/moduleDetailsQuery';
|
||||
import { MODULE_PAGE } from '@/router/module.names';
|
||||
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const EyeIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/EyeIcon'));
|
||||
|
||||
export default {
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const EyeIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/EyeIcon'));
|
||||
|
||||
export default {
|
||||
mixins: [me],
|
||||
components: {
|
||||
EyeIcon,
|
||||
|
|
@ -69,11 +53,11 @@
|
|||
|
||||
computed: {
|
||||
schoolClasses() {
|
||||
return this.me.schoolClasses.filter(schoolClass => schoolClass.id !== this.me.selectedClass.id);
|
||||
return this.me.schoolClasses.filter((schoolClass) => schoolClass.id !== this.me.selectedClass.id);
|
||||
},
|
||||
slug() {
|
||||
return this.$route.params.slug;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
@ -83,7 +67,8 @@
|
|||
sync() {
|
||||
if (this.selectedClassId) {
|
||||
const slug = this.slug;
|
||||
this.$apollo.mutate({
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: SYNC_VISIBILITY_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
|
|
@ -100,25 +85,25 @@
|
|||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
).then(() => {
|
||||
})
|
||||
.then(() => {
|
||||
this.$router.push({
|
||||
name: MODULE_PAGE,
|
||||
params: {
|
||||
slug
|
||||
}
|
||||
slug,
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/_helpers';
|
||||
@import '~styles/_helpers';
|
||||
|
||||
.module-visibility {
|
||||
.module-visibility {
|
||||
@include settings-page;
|
||||
|
||||
margin: 0 auto;
|
||||
|
|
@ -140,5 +125,5 @@
|
|||
@include regular-text;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,23 +1,19 @@
|
|||
<template>
|
||||
<div>
|
||||
<logo class="onboarding__logo" />
|
||||
<h1 class="onboarding__heading">
|
||||
Herzlich willkommen!
|
||||
</h1>
|
||||
<h1 class="onboarding__heading">Herzlich willkommen!</h1>
|
||||
|
||||
<p class="onboarding__claim">
|
||||
Schauen Sie sich die Einführung an und lernen Sie {{ $flavor.textAppName }} kennen.
|
||||
</p>
|
||||
<p class="onboarding__claim">Schauen Sie sich die Einführung an und lernen Sie {{ $flavor.textAppName }} kennen.</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
const Logo = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/Logo'));
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
const Logo = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/Logo'));
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
Logo
|
||||
Logo,
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -140,8 +140,7 @@ export default {
|
|||
't t'
|
||||
'd d'
|
||||
'm m';
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
&__back {
|
||||
grid-area: b;
|
||||
|
|
@ -155,10 +154,8 @@ export default {
|
|||
grid-area: a;
|
||||
display: flex;
|
||||
|
||||
@include desktop {
|
||||
justify-self: end;
|
||||
}
|
||||
}
|
||||
@include desktop {justify-self: end;
|
||||
}}
|
||||
|
||||
&__more {
|
||||
display: none;
|
||||
|
|
@ -198,17 +195,15 @@ export default {
|
|||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: $medium-spacing;
|
||||
|
||||
@include desktop {
|
||||
flex-direction: row-reverse;
|
||||
align-items: center;
|
||||
margin-bottom: $medium-spacing;@include desktop {
|
||||
flex-direction: row-reverse;align-items: center;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
justify-content: flex-start;
|
||||
position: relative;
|
||||
& > :first-child {
|
||||
margin-bottom: $medium-spacing;
|
||||
|
||||
|
||||
& > :first-child {margin-bottom: $medium-spacing;
|
||||
@include desktop {
|
||||
margin-left: $large-spacing;
|
||||
margin-bottom: 0;
|
||||
|
|
@ -216,11 +211,9 @@ export default {
|
|||
}
|
||||
|
||||
& > :nth-child(2) {
|
||||
@include desktop {
|
||||
margin-left: $large-spacing;
|
||||
}
|
||||
}
|
||||
@include desktop {margin-left: $large-spacing;
|
||||
}
|
||||
}}
|
||||
|
||||
&__content {
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -1,23 +1,17 @@
|
|||
<template>
|
||||
<content-block-form
|
||||
:content-block="roomEntry"
|
||||
:features="features"
|
||||
v-if="roomEntry.id"
|
||||
@save="save"
|
||||
@back="goBack"
|
||||
/>
|
||||
<content-block-form :content-block="roomEntry" :features="features" v-if="roomEntry.id" @save="save" @back="goBack" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {defineComponent} from 'vue';
|
||||
|
||||
import ROOM_ENTRY_QUERY from 'gql/queries/roomEntryQuery.gql';
|
||||
import ROOM_ENTRY_FRAGMENT from 'gql/fragments/roomEntryParts.gql';
|
||||
import UPDATE_ROOM_ENTRY_MUTATION from 'gql/mutations/rooms/updateRoomEntry.gql';
|
||||
import ROOM_ENTRY_QUERY from 'gql/queries/roomEntryQuery.gql';
|
||||
import ROOM_ENTRY_FRAGMENT from 'gql/fragments/roomEntryParts.gql';
|
||||
import UPDATE_ROOM_ENTRY_MUTATION from 'gql/mutations/rooms/updateRoomEntry.gql';
|
||||
|
||||
import ContentBlockForm from '@/components/content-block-form/ContentBlockForm';
|
||||
import {ROOMS_FEATURE_SET} from '@/consts/features.consts';
|
||||
import {ROOM_PAGE} from '@/router/room.names';
|
||||
import ContentBlockForm from '@/components/content-block-form/ContentBlockForm';
|
||||
import { ROOMS_FEATURE_SET } from '@/consts/features.consts';
|
||||
import { ROOM_PAGE } from '@/router/room.names';
|
||||
|
||||
export default defineComponent( {
|
||||
props: {
|
||||
|
|
@ -30,6 +24,7 @@
|
|||
required: true
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
ContentBlockForm,
|
||||
|
|
@ -50,10 +45,10 @@
|
|||
query: ROOM_ENTRY_QUERY,
|
||||
variables() {
|
||||
return {
|
||||
slug: this.entrySlug
|
||||
slug: this.entrySlug,
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
@ -61,50 +56,55 @@
|
|||
this.$router.push({
|
||||
name: ROOM_PAGE,
|
||||
params: {
|
||||
slug: this.slug
|
||||
}
|
||||
slug: this.slug,
|
||||
},
|
||||
});
|
||||
},
|
||||
save({title, contents}) {
|
||||
save({ title, contents }) {
|
||||
const entry = {
|
||||
slug: this.roomEntry.slug,
|
||||
title,
|
||||
contents,
|
||||
};
|
||||
this.$apollo.mutate({
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: UPDATE_ROOM_ENTRY_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
roomEntry: entry,
|
||||
}
|
||||
},
|
||||
update: (store, {data: {updateRoomEntry: {roomEntry}}}) => {
|
||||
},
|
||||
update: (
|
||||
store,
|
||||
{
|
||||
data: {
|
||||
updateRoomEntry: { roomEntry },
|
||||
},
|
||||
}
|
||||
) => {
|
||||
try {
|
||||
const fragment = ROOM_ENTRY_FRAGMENT;
|
||||
const id = store.identify(roomEntry);
|
||||
const cachedEntry = store.readQuery({fragment, id});
|
||||
const cachedEntry = store.readQuery({ fragment, id });
|
||||
const data = Object.assign({}, cachedEntry, roomEntry);
|
||||
store.writeFragment({
|
||||
id,
|
||||
fragment,
|
||||
data
|
||||
data,
|
||||
});
|
||||
} catch (e) {
|
||||
// Query did not exist in the cache, and apollo throws a generic Error. Do nothing
|
||||
}
|
||||
}
|
||||
}).then(() => {
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
this.goBack();
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
} );
|
||||
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
|
||||
|
||||
@import '~styles/helpers';
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,28 +1,23 @@
|
|||
<template>
|
||||
<content-block-form
|
||||
:content-block="roomEntry"
|
||||
:features="features"
|
||||
@save="save"
|
||||
@back="goBack"
|
||||
/>
|
||||
<content-block-form :content-block="roomEntry" :features="features" @save="save" @back="goBack" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {defineComponent} from 'vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
import NEW_ROOM_ENTRY_MUTATION from 'gql/mutations/rooms/addRoomEntry.gql';
|
||||
import ROOM_ENTRIES_QUERY from '@/graphql/gql/queries/roomEntriesQuery.gql';
|
||||
import NEW_ROOM_ENTRY_MUTATION from 'gql/mutations/rooms/addRoomEntry.gql';
|
||||
import ROOM_ENTRIES_QUERY from '@/graphql/gql/queries/roomEntriesQuery.gql';
|
||||
|
||||
import ContentBlockForm from '@/components/content-block-form/ContentBlockForm';
|
||||
import {ROOMS_FEATURE_SET} from '@/consts/features.consts';
|
||||
import {ROOM_PAGE} from '@/router/room.names';
|
||||
import ContentBlockForm from '@/components/content-block-form/ContentBlockForm';
|
||||
import { ROOMS_FEATURE_SET } from '@/consts/features.consts';
|
||||
import { ROOM_PAGE } from '@/router/room.names';
|
||||
|
||||
export default defineComponent( {
|
||||
export default defineComponent({
|
||||
props: {
|
||||
slug: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
|
|
@ -44,64 +39,66 @@
|
|||
this.$router.push({
|
||||
name: ROOM_PAGE,
|
||||
params: {
|
||||
slug: this.slug
|
||||
}
|
||||
slug: this.slug,
|
||||
},
|
||||
});
|
||||
},
|
||||
save({title, contents}) {
|
||||
save({ title, contents }) {
|
||||
const entry = {
|
||||
title,
|
||||
contents,
|
||||
roomSlug: this.slug
|
||||
roomSlug: this.slug,
|
||||
};
|
||||
this.$apollo.mutate({
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: NEW_ROOM_ENTRY_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
roomEntry: entry,
|
||||
}
|
||||
},
|
||||
update: (store, {data: {addRoomEntry: {roomEntry}}}) => {
|
||||
},
|
||||
update: (
|
||||
store,
|
||||
{
|
||||
data: {
|
||||
addRoomEntry: { roomEntry },
|
||||
},
|
||||
}
|
||||
) => {
|
||||
try {
|
||||
const query = ROOM_ENTRIES_QUERY;
|
||||
const variables = {slug: this.slug};
|
||||
const {room} = store.readQuery({query, variables});
|
||||
const variables = { slug: this.slug };
|
||||
const { room } = store.readQuery({ query, variables });
|
||||
if (room && room.roomEntries) {
|
||||
const newEdge ={
|
||||
const newEdge = {
|
||||
node: roomEntry,
|
||||
__typename: 'RoomEntryNodeEdge'
|
||||
__typename: 'RoomEntryNodeEdge',
|
||||
};
|
||||
const edges = [
|
||||
newEdge,
|
||||
...room.roomEntries.edges
|
||||
];
|
||||
const edges = [newEdge, ...room.roomEntries.edges];
|
||||
const data = {
|
||||
room: {
|
||||
...room,
|
||||
roomEntries: {
|
||||
...room.roomEntries,
|
||||
edges
|
||||
}
|
||||
}
|
||||
edges,
|
||||
},
|
||||
},
|
||||
};
|
||||
store.writeQuery({query, variables, data});
|
||||
store.writeQuery({ query, variables, data });
|
||||
}
|
||||
} catch (e) {
|
||||
// Query did not exist in the cache, and apollo throws a generic Error. Do nothing
|
||||
}
|
||||
}
|
||||
}).then(() => {
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
this.goBack();
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
} );
|
||||
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
|
||||
|
||||
@import '~styles/helpers';
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -17,12 +17,7 @@
|
|||
:key="index"
|
||||
/>
|
||||
</div>
|
||||
<router-link
|
||||
:to="topicRoute"
|
||||
class="button"
|
||||
>
|
||||
Alle {{ $flavor.textModules }} anzeigen
|
||||
</router-link>
|
||||
<router-link :to="topicRoute" class="button"> Alle {{ $flavor.textModules }} anzeigen </router-link>
|
||||
</div>
|
||||
<div class="start-page__news news" data-cy="news-teasers" v-if="!me.readOnly">
|
||||
<h2 class="start-page__heading">News</h2>
|
||||
|
|
|
|||
|
|
@ -14,10 +14,9 @@
|
|||
|
||||
<script>
|
||||
import '@/styles/survey.modern.css';
|
||||
import '@/styles/survey.reset.css';
|
||||
import { css } from '@/survey.config';
|
||||
import '@/styles/survey.reset.css';import { css } from '@/survey.config';
|
||||
import gql from 'graphql-tag';
|
||||
import { Model, StylesManager } from 'survey-knockout';
|
||||
import { Model , StylesManager } from 'survey-knockout';
|
||||
// we are switching to the knockout version because the Vue version only works with Vue 2 (as of July 2022)
|
||||
|
||||
import SURVEY_QUERY from '@/graphql/gql/queries/surveyQuery.gql';
|
||||
|
|
@ -35,7 +34,8 @@ const Solution = defineAsyncComponent(() =>
|
|||
*/ '@/components/content-blocks/Solution'
|
||||
)
|
||||
);
|
||||
StylesManager.applyTheme('modern');
|
||||
StylesManager.applyTheme('modern')
|
||||
);
|
||||
|
||||
const MODULE_QUERY = gql`
|
||||
query ModuleSolutions($slug: String) {
|
||||
|
|
@ -56,8 +56,7 @@ export default {
|
|||
return {
|
||||
survey: this.initSurvey(),
|
||||
currentPage: null,
|
||||
surveyData: null,
|
||||
title: '',
|
||||
surveyData: null,title: '',
|
||||
module: {},
|
||||
completed: false,
|
||||
me: {
|
||||
|
|
@ -115,15 +114,14 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
destroyed() {},
|
||||
|
||||
methods: {
|
||||
destroyed() {},methods: {
|
||||
initSurvey(data, answers) {
|
||||
let survey = new Model(data);
|
||||
const flatAnswers = {};
|
||||
for (let k in answers) {
|
||||
flatAnswers[k] = answers[k].answer;
|
||||
}
|
||||
|
||||
if (Object.keys(flatAnswers).length > 0) {
|
||||
// answers are not empty
|
||||
survey.data = flatAnswers;
|
||||
|
|
@ -215,6 +213,7 @@ export default {
|
|||
survey.locale = 'de';
|
||||
survey.showProgressBar = 'bottom';
|
||||
survey.pageNextText = 'Speichern & Weiter';
|
||||
|
||||
survey.render('survey');
|
||||
return survey;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -5,21 +5,14 @@
|
|||
</div>
|
||||
|
||||
<div class="topic__content">
|
||||
<h1
|
||||
data-cy="topic-title"
|
||||
class="topic__title"
|
||||
>
|
||||
<h1 data-cy="topic-title" class="topic__title">
|
||||
{{ topic.title }}
|
||||
</h1>
|
||||
<p class="topic__teaser">
|
||||
{{ topic.teaser }}
|
||||
</p>
|
||||
<div class="topic__links">
|
||||
<div
|
||||
class="topic__video-link topic__link"
|
||||
v-if="topic.vimeoId"
|
||||
@click="openVideo"
|
||||
>
|
||||
<div class="topic__video-link topic__link" v-if="topic.vimeoId" @click="openVideo">
|
||||
<play-icon class="topic__video-link-icon topic__link-icon" />
|
||||
<span class="topic__link-description">Video schauen</span>
|
||||
</div>
|
||||
|
|
@ -34,10 +27,7 @@
|
|||
</a>
|
||||
</div>
|
||||
<div class="topic__modules">
|
||||
<module-teaser
|
||||
v-for="module in modules"
|
||||
v-bind="module"
|
||||
:key="module.slug"
|
||||
<module-teaser v-for="module in modules" v-bind="module" :key="module.slug"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -45,19 +35,18 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import ModuleTeaser from '@/components/modules/ModuleTeaser.vue';
|
||||
import {defineAsyncComponent} from 'vue';
|
||||
import TOPIC_QUERY from '@/graphql/gql/queries/topicQuery.gql';
|
||||
import me from '@/mixins/me';
|
||||
import TopicNavigation from '@/components/book-navigation/TopicNavigation';
|
||||
import ModuleTeaser from '@/components/modules/ModuleTeaser.vue';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
import TOPIC_QUERY from '@/graphql/gql/queries/topicQuery.gql';
|
||||
import me from '@/mixins/me';
|
||||
import TopicNavigation from '@/components/book-navigation/TopicNavigation';
|
||||
|
||||
import UPDATE_LAST_TOPIC_MUTATION from '@/graphql/gql/mutations/updateLastTopic.gql';
|
||||
import ME_QUERY from '@/graphql/gql/queries/meQuery.gql';
|
||||
const PlayIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/Play'));
|
||||
const BulbIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */'@/components/icons/BulbIcon'));
|
||||
|
||||
export default {
|
||||
import UPDATE_LAST_TOPIC_MUTATION from '@/graphql/gql/mutations/updateLastTopic.gql';
|
||||
import ME_QUERY from '@/graphql/gql/queries/meQuery.gql';
|
||||
const PlayIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/Play'));
|
||||
const BulbIcon = defineAsyncComponent(() => import(/* webpackChunkName: "icons" */ '@/components/icons/BulbIcon'));
|
||||
|
||||
export default {
|
||||
mixins: [me],
|
||||
components: {
|
||||
TopicNavigation,
|
||||
|
|
@ -104,7 +93,8 @@
|
|||
},
|
||||
|
||||
mounted() {
|
||||
if (!this.topic.id) { // component was loaded before topic, apollo not ready yet
|
||||
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);
|
||||
|
|
@ -126,10 +116,17 @@
|
|||
id: topicId,
|
||||
},
|
||||
},
|
||||
update(store, {data: {updateLastTopic: {topic}}}) {
|
||||
update(
|
||||
store,
|
||||
{
|
||||
data: {
|
||||
updateLastTopic: { topic },
|
||||
},
|
||||
}
|
||||
) {
|
||||
if (topic) {
|
||||
const query = ME_QUERY;
|
||||
const {me} = store.readQuery({query});
|
||||
const { me } = store.readQuery({ query });
|
||||
if (me) {
|
||||
const data = {
|
||||
me: {
|
||||
|
|
@ -137,21 +134,21 @@
|
|||
lastTopic: topic,
|
||||
},
|
||||
};
|
||||
store.writeQuery({query, data});
|
||||
store.writeQuery({ query, data });
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
@import '@/styles/_variables.scss';
|
||||
@import '@/styles/_mixins.scss';
|
||||
|
||||
.topic {
|
||||
.topic {
|
||||
display: grid;
|
||||
padding: $large-spacing 0;
|
||||
grid-template-columns: 1fr;
|
||||
|
|
@ -213,5 +210,5 @@
|
|||
grid-template-columns: repeat(3, minmax(auto, 380px));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// adapted from
|
||||
// https://stackoverflow.com/questions/41791193/vuejs-reactive-binding-for-a-plugin-how-to/41801107#41801107
|
||||
import {reactive, App} from 'vue';
|
||||
import { reactive, App } from 'vue';
|
||||
|
||||
class ModalStore {
|
||||
data: any;
|
||||
|
|
@ -18,19 +18,19 @@ class ModalStore {
|
|||
}
|
||||
|
||||
interface Modal {
|
||||
state: any,
|
||||
component: string,
|
||||
payload?: any,
|
||||
confirm: (res: any) => void,
|
||||
open: (component: string, payload?: any) => Promise<(resolve: () => any, reject: () => any) => void>,
|
||||
cancel: () => void,
|
||||
_resolve: (r?: any) => any,
|
||||
_reject: (r?: any) => any
|
||||
state: any;
|
||||
component: string;
|
||||
payload?: any;
|
||||
confirm: (res: any) => void;
|
||||
open: (component: string, payload?: any) => Promise<(resolve: () => any, reject: () => any) => void>;
|
||||
cancel: () => void;
|
||||
_resolve: (r?: any) => any;
|
||||
_reject: (r?: any) => any;
|
||||
}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface ComponentCustomProperties {
|
||||
$modal: Modal
|
||||
$modal: Modal;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import {RouteLocationNormalized} from "vue-router";
|
||||
import { RouteLocationNormalized } from 'vue-router';
|
||||
|
||||
function getCookieValue(cookieName: string) {
|
||||
// https://stackoverflow.com/questions/5639346/what-is-the-shortest-function-for-reading-a-cookie-by-name-in-javascript
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import {createRouter, createWebHistory} from 'vue-router';
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
|
||||
import moduleRoutes from './module.routes';
|
||||
import portfolioRoutes from './portfolio.routes';
|
||||
|
|
@ -7,19 +7,19 @@ import meRoutes from './me.routes';
|
|||
import authRoutes from './auth.routes';
|
||||
import roomRoutes from './room.routes';
|
||||
|
||||
import {store} from '@/store';
|
||||
import {LAYOUT_SIMPLE} from '@/router/core.constants';
|
||||
import {EMAIL_NOT_VERIFIED_STATE, NO_VALID_LICENSE_STATE, SUCCESS_STATE} from './oauth.names';
|
||||
import { store } from '@/store';
|
||||
import { LAYOUT_SIMPLE } from '@/router/core.constants';
|
||||
import { EMAIL_NOT_VERIFIED_STATE, NO_VALID_LICENSE_STATE, SUCCESS_STATE } from './oauth.names';
|
||||
|
||||
import start from '@/pages/start';
|
||||
|
||||
const instrument = () => import(/* webpackChunkName: "instruments" */'@/pages/instrument');
|
||||
const instrumentOverview = () => import(/* webpackChunkName: "instruments" */'@/pages/instrumentOverview');
|
||||
const instrument = () => import(/* webpackChunkName: "instruments" */ '@/pages/instrument');
|
||||
const instrumentOverview = () => import(/* webpackChunkName: "instruments" */ '@/pages/instrumentOverview');
|
||||
|
||||
const article = () => import(/* webpackChunkName: "news" */'@/pages/article');
|
||||
const news = () => import(/* webpackChunkName: "news" */'@/pages/news');
|
||||
const article = () => import(/* webpackChunkName: "news" */ '@/pages/article');
|
||||
const news = () => import(/* webpackChunkName: "news" */ '@/pages/news');
|
||||
|
||||
const surveyPage = () => import(/* webpackChunkName: "survey" */'@/pages/survey');
|
||||
const surveyPage = () => import(/* webpackChunkName: "survey" */ '@/pages/survey');
|
||||
|
||||
const styleGuidePage = () => import('@/pages/styleguide');
|
||||
const joinClass = () => import('@/pages/joinClass');
|
||||
|
|
@ -50,22 +50,22 @@ const routes = [
|
|||
...onboardingRoutes,
|
||||
...portfolioRoutes,
|
||||
...meRoutes,
|
||||
{path: '/article/:slug', name: 'article', component: article, meta: {layout: LAYOUT_SIMPLE}},
|
||||
{ path: '/article/:slug', name: 'article', component: article, meta: { layout: LAYOUT_SIMPLE } },
|
||||
{
|
||||
path: '/instruments/',
|
||||
name: 'instrument-overview',
|
||||
component: instrumentOverview,
|
||||
},
|
||||
{path: '/instrument/:slug', name: 'instrument', component: instrument, meta: {layout: LAYOUT_SIMPLE}},
|
||||
{path: '/submission/:id', name: 'submission', component: submission, meta: {layout: LAYOUT_SIMPLE}},
|
||||
{path: '/topic/:topicSlug', name: 'topic', component: topic, alias: '/book/topic/:topicSlug'},
|
||||
{path: '/join-class', name: 'join-class', component: joinClass, meta: {layout: LAYOUT_SIMPLE}},
|
||||
{ path: '/instrument/:slug', name: 'instrument', component: instrument, meta: { layout: LAYOUT_SIMPLE } },
|
||||
{ path: '/submission/:id', name: 'submission', component: submission, meta: { layout: LAYOUT_SIMPLE } },
|
||||
{ path: '/topic/:topicSlug', name: 'topic', component: topic, alias: '/book/topic/:topicSlug' },
|
||||
{ path: '/join-class', name: 'join-class', component: joinClass, meta: { layout: LAYOUT_SIMPLE } },
|
||||
{
|
||||
path: '/survey/:id',
|
||||
component: surveyPage,
|
||||
name: 'survey',
|
||||
props: true,
|
||||
meta: {layout: LAYOUT_SIMPLE},
|
||||
meta: { layout: LAYOUT_SIMPLE },
|
||||
},
|
||||
{
|
||||
path: '/news',
|
||||
|
|
@ -74,7 +74,7 @@ const routes = [
|
|||
},
|
||||
{
|
||||
path: '/oauth-redirect',
|
||||
redirect: to => {
|
||||
redirect: (to) => {
|
||||
switch (to.query.state) {
|
||||
case EMAIL_NOT_VERIFIED_STATE:
|
||||
return '/verify-email';
|
||||
|
|
@ -92,15 +92,15 @@ const routes = [
|
|||
}
|
||||
},
|
||||
},
|
||||
{path: '/styleguide', component: styleGuidePage},
|
||||
{ path: '/styleguide', component: styleGuidePage },
|
||||
{
|
||||
path: '/not-found',
|
||||
name: 'not-found',
|
||||
...notFoundRoute
|
||||
...notFoundRoute,
|
||||
},
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
...notFoundRoute
|
||||
...notFoundRoute,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ const router = createRouter({
|
|||
if (savedPosition) {
|
||||
return savedPosition;
|
||||
}
|
||||
return {left: 0, top: 0};
|
||||
return { left: 0, top: 0 };
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -122,4 +122,4 @@ router.afterEach(() => {
|
|||
store.dispatch('showMobileNavigation', false);
|
||||
});
|
||||
|
||||
export {router, postLoginRedirectUrlKey};
|
||||
export { router, postLoginRedirectUrlKey };
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { ONBOARDING_STEP_1, ONBOARDING_STEP_2, ONBOARDING_STEP_3 } from '@/router/onboarding.names';
|
||||
|
||||
const onboarding = () => import('@/pages/onboarding.vue');
|
||||
const onboardingStart = () => import('@/pages/onboarding/start.vue');
|
||||
const onboarding = () => import( '@/pages/onboarding.vue');
|
||||
const onboardingStart = () => import( '@/pages/onboarding/start.vue');
|
||||
const onboardingStep1 = () => import(/* webpackChunkName: "onboarding" */ '@/pages/onboarding/step1.vue');
|
||||
const onboardingStep2 = () => import(/* webpackChunkName: "onboarding" */ '@/pages/onboarding/step2.vue');
|
||||
const onboardingStep3 = () => import(/* webpackChunkName: "onboarding" */ '@/pages/onboarding/step3.vue');
|
||||
|
|
|
|||
|
|
@ -10,4 +10,3 @@ declare module '*.vue' {
|
|||
const component: DefineComponent<{}, {}, any>;
|
||||
export default component;
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue