Add read-only banner

This commit is contained in:
Ramon Wenger 2021-08-03 15:12:09 +02:00
parent b6298710a0
commit 44f25bd113
11 changed files with 159 additions and 19 deletions

View File

@ -0,0 +1,67 @@
const getOperations = ({readOnly, classReadOnly = false}) => ({
MeQuery: {
me: {
onboardingVisited: true,
readOnly,
isTeacher: true,
selectedClass: {
id: 'selectedClassId',
readOnly: classReadOnly
}
},
},
NewsTeasers: {
newsTeasers: {
edges: []
}
}
});
const checkReadOnly = (shouldBannerExist, text) => {
cy.visit('/');
cy.getByDataCy('start-page-heading').should('exist');
if (shouldBannerExist) {
cy.getByDataCy('read-only-banner').should('exist').should('contain', text);
} else {
cy.getByDataCy('read-only-banner').should('not.exist');
}
};
describe('Read Only Banner', () => {
beforeEach(() => {
cy.setup();
});
it('is not shown', () => {
cy.mockGraphqlOps({
operations: getOperations({readOnly: false}),
});
checkReadOnly(false);
});
it('is shown for expired license', () => {
cy.mockGraphqlOps({
operations: getOperations({readOnly: true}),
});
checkReadOnly(true, 'Lizenz');
// cy.visit('/');
//
// cy.getByDataCy('start-page-heading').should('exist');
// cy.getByDataCy('read-only-banner').should('exist').should('contain', 'nicht mehr aktiv');
});
it('is shown for inactive school class', () => {
cy.mockGraphqlOps({
operations: getOperations({readOnly: false, classReadOnly: true}),
});
checkReadOnly(true, 'Klasse');
//
// cy.visit('/');
// cy.getByDataCy('start-page-heading').should('exist');
// cy.getByDataCy('read-only-banner').should('exist').should('contain', 'nicht mehr aktiv');
});
});

View File

@ -3,6 +3,7 @@
:class="{'no-scroll': showModal || showMobileNavigation}"
class="app"
id="app">
<read-only-banner/>
<scroll-up/>
<component
:is="showModalDeprecated"
@ -40,11 +41,13 @@
import SnapshotCreated from '@/components/modules/SnapshotCreated';
import {mapGetters} from 'vuex';
import ScrollUp from '@/components/ScrollUp';
import ReadOnlyBanner from '@/components/ReadOnlyBanner';
export default {
name: 'App',
components: {
ReadOnlyBanner,
ScrollUp,
DefaultLayout,
SimpleLayout,
@ -68,7 +71,7 @@
FullscreenInfographic,
FullscreenVideo,
DeactivatePerson,
SnapshotCreated
SnapshotCreated,
},
computed: {
@ -77,17 +80,17 @@
},
...mapGetters({
showModalDeprecated: 'showModal', // don't use this any more todo: remove this
showMobileNavigation: 'showMobileNavigation'
showMobileNavigation: 'showMobileNavigation',
}),
showModal() {
return this.$modal.state.component;
}
},
},
};
</script>
<style lang="scss">
@import "styles/main.scss";
@import "~styles/main.scss";
body {
overflow-y: auto;
@ -100,6 +103,8 @@
min-height: 100vh;
/*for IE10+*/
display: flex;
flex-direction: column;
}
.no-scroll {

View File

@ -0,0 +1,41 @@
<template>
<div
class="read-only-banner"
data-cy="read-only-banner"
v-if="me.readOnly || me.selectedClass.readOnly">
<p class="read-only-banner__text">
{{ readOnlyText }} Sie können Inhalte lesen, aber nicht
bearbeiten.
</p>
</div>
</template>
<script>
import me from '@/mixins/me';
export default {
mixins: [me],
computed: {
readOnlyText() {
return this.me.readOnly ? 'Sie besitzen keine aktive Lizenz.' : 'Sie sind in dieser Klasse nicht mehr aktiv.';
}
}
};
</script>
<style scoped lang="scss">
@import '~styles/helpers';
.read-only-banner {
background-color: $color-brand-light;
display: flex;
justify-content: center;
&__text {
padding: $small-spacing 0;
@include regular-text;
max-width: $screen-width;
}
}
</style>

View File

@ -5,7 +5,7 @@ export default {
addSchoolClass(store, schoolClass) {
const query = ME_QUERY;
if (schoolClass) {
console.log('updating school class');
this.$log.debug('updating school class', schoolClass);
const data = store.readQuery({query});
if (data) {
data.me.schoolClasses.edges = [

View File

@ -76,7 +76,7 @@
}
&__title {
max-width: 1200px;
max-width: $screen-width;
line-height: 1.2;
margin-bottom: 0;
}
@ -87,7 +87,7 @@
&__list {
padding: $large-spacing 0;
max-width: 1200px;
max-width: $screen-width;
width: 100%;
display: flex;
flex-direction: column;

View File

@ -34,7 +34,7 @@
this.error = '';
},
joinClass(code) {
let self = this;
this.$log.debug('joining class');
this.$apollo.mutate({
mutation: JOIN_CLASS_MUTATION,
variables: {
@ -42,9 +42,10 @@
code,
},
},
update(store, {data: {joinClass: {schoolClass}}}) {
self.addSchoolClass(store, schoolClass);
self.$router.push({name: 'my-class'});
update: (store, {data: {joinClass: {schoolClass}}}) => {
this.addSchoolClass(store, schoolClass);
this.$log.debug('added school class');
this.$router.push({name: 'my-class'});
},
refetchQueries: [{query: MY_SCHOOL_CLASS_QUERY}],
})

View File

@ -4,7 +4,9 @@
<div
class="start-page__modules start-sections"
data-cy="start-modules-list">
<h2 class="start-page__heading">Letzte Module</h2>
<h2
class="start-page__heading"
data-cy="start-page-heading">Letzte Module</h2>
<h3
class="start-page__no-modules"
data-cy="no-modules-yet"
@ -109,9 +111,7 @@
</script>
<style scoped lang="scss">
@import "@/styles/_variables.scss";
@import "@/styles/_mixins.scss";
@import "~styles/helpers";
.start-page {
display: flex;
@ -151,7 +151,7 @@
box-sizing: border-box;
max-width: 100%;
@include desktop {
max-width: 1200px;
max-width: $screen-width;
margin: 0 auto;
}
}

View File

@ -56,7 +56,7 @@
.submissions-page {
display: grid;
width: 100%;
max-width: 1200px;
max-width: $screen-width;
grid-template-rows: auto 1fr;

View File

@ -1,5 +1,4 @@
@import "@/styles/_variables.scss";
@import "@/styles/_mixins.scss";
@import "~styles/helpers";
.layout {
$footer-height: 287px;

View File

@ -80,3 +80,5 @@ $popover-default-bottom: -110px;
$footer-width: 800px;
$news-width: 550px;
$screen-width: 1200px;

View File

@ -426,6 +426,7 @@ type CustomMutation {
}
type CustomQuery {
newsTeasers(offset: Int, before: String, after: String, first: Int, last: Int, date: Date): NewsTeaserNodeConnection
survey(id: ID): SurveyNode
surveys(offset: Int, before: String, after: String, first: Int, last: Int): SurveyNodeConnection
project(id: ID, slug: String): ProjectNode
@ -458,6 +459,8 @@ type CustomQuery {
_debug: DjangoDebug
}
scalar Date
scalar DateTime
input DeleteContentBlockInput {
@ -692,6 +695,28 @@ type MutateContentBlockPayload {
clientMutationId: String
}
type NewsTeaserNode implements Node {
id: ID!
imageUrl: String
title: String!
description: String
date: Date
orderId: Int!
newsArticleUrl: String
imageSource: String!
displayDate: String
}
type NewsTeaserNodeConnection {
pageInfo: PageInfo!
edges: [NewsTeaserNodeEdge]!
}
type NewsTeaserNodeEdge {
node: NewsTeaserNode
cursor: String!
}
interface Node {
id: ID!
}