Refactor some code, generalize some components

This commit is contained in:
Ramon Wenger 2021-03-25 16:24:47 +01:00
parent 45db4e3258
commit d334370f3b
13 changed files with 354 additions and 244 deletions

View File

@ -46,12 +46,12 @@ describe('New student', () => {
});
cy.visit('/');
cy.get('[data-cy=join-class-title]').should('contain', 'Einer Klasse beitreten');
cy.get('[data-cy=input-class-code]').type('XXXX');
cy.get('[data-cy=join-class]').click();
cy.get('[data-cy=join-form-title]').should('contain', 'Einer Klasse beitreten');
cy.get('[data-cy=input-form-code]').type('XXXX');
cy.get('[data-cy=join-form-confirm]').click();
cy.skipOnboarding();
cy.get('[data-cy=user-widget-avatar]').click();
cy.get('[data-cy=class-list-link]').click();
cy.get('[data-cy=class-list-title]').should('contain', 'Klassenliste');
cy.get('[data-cy=group-list-title]').should('contain', 'Klassenliste');
});
});

View File

@ -229,7 +229,7 @@ describe('Teacher Class Management', () => {
cy.visit('/me/my-class');
cy.get('[data-cy=edit-class-name-link]').click();
cy.get('[data-cy=edit-group-name-link]').click();
cy.get('[data-cy=edit-class-name-input] input').type('{selectall}{backspace}').type(className);
cy.get('[data-cy=modal-save-button]').click();
cy.get('[data-cy=school-class-name]').should('contain', className);

View File

@ -1,115 +0,0 @@
<template>
<div class="school-class">
<h2 class="school-class__heading"><span
class="school-class__name"
data-cy="school-class-name">{{ name }}</span>
<edit-class-name
v-if="teacher"
@edit="editClassName"/>
</h2>
<div class="school-class__members school-class-members">
<ul
class="school-class-members__list simple-list simple-list--active"
data-cy="active-class-members-list">
<li
:key="member.id"
class="simple-list__item member-item"
data-cy="school-class-member"
v-for="member in activeMembers">
<span class="member-item__name">{{ fullName(member) }}</span>
<span class="member-item__role">{{ role(member) }}</span>
<!-- <a-->
<!-- class="member-item__action simple-list__action"-->
<!-- data-cy="remove-from-class"-->
<!-- v-if="teacher"-->
<!-- @click="$emit('remove', member)">Deaktivieren</a>-->
</li>
</ul>
<!-- <template v-if="inactiveMembers.length">-->
<!-- <h3 class="school-class__inactive-heading">Deaktivierte Personen</h3>-->
<!-- <ul data-cy="inactive-class-members-list" class="simple-list simple-list&#45;&#45;inactive">-->
<!-- <li-->
<!-- class="simple-list__item member-item"-->
<!-- data-cy="school-class-member"-->
<!-- v-for="member in inactiveMembers"-->
<!-- :key="member.id">-->
<!-- <span class="member-item__name">{{fullName(member)}}</span>-->
<!-- <span class="member-item__role">{{role(member)}}</span>-->
<!-- <a-->
<!-- class="member-item__action simple-list__action"-->
<!-- data-cy="add-to-class"-->
<!-- v-if="teacher"-->
<!-- @click="$emit('add', member)">Aktivieren</a>-->
<!-- </li>-->
<!-- </ul>-->
<!-- </template>-->
</div>
</div>
</template>
<script>
import EditClassName from '@/components/school-class/EditClassName';
export default {
props: ['members', 'name', 'teacher', 'id'],
components: {
EditClassName
},
computed: {
activeMembers() {
return this.members.filter(member => member.active);
},
inactiveMembers() {
return this.members.filter(member => !member.active);
}
},
methods: {
fullName(member) {
return `${member.firstName} ${member.lastName}`;
},
role({isTeacher}) {
return isTeacher ? 'Lehrperson' : 'Schüler';
},
editClassName() {
this.$store.dispatch('editClassName');
}
},
};
</script>
<style scoped lang="scss">
@import "@/styles/_variables.scss";
@import "@/styles/_mixins.scss";
.school-class {
&__inactive-heading {
@include heading-4;
margin-bottom: $small-spacing;
}
&__name {
@include heading-2;
}
}
.member-item {
&__name {
font-family: $sans-serif-font-family;
font-weight: $font-weight-bold;
flex: 2 1 auto;
}
&__role {
flex: 0 1 110px;
text-align: right;
}
&__action {
flex: 0 1 110px;
padding-left: $large-spacing;
}
}
</style>

View File

@ -1,9 +1,9 @@
<template>
<a
class="edit-class-name"
data-cy="edit-class-name-link"
class="edit-group-name"
data-cy="edit-group-name-link"
@click="$emit('edit')">
<pen-icon class="edit-class-name__icon"/>
<pen-icon class="edit-group-name__icon"/>
</a>
</template>
@ -18,9 +18,9 @@
</script>
<style scoped lang="scss">
@import "@/styles/_variables.scss";
@import "~styles/_variables.scss";
.edit-class-name {
.edit-group-name {
&__icon {
width: 20px;
height: 20px;

View File

@ -0,0 +1,170 @@
<template>
<div class="group-list">
<h1
class="group-list__header"
data-cy="group-list-title">{{ title }}</h1>
<router-link
:to="showCodeRoute"
class="group-list__code-link button button--primary"
v-if="showCode">Zugangscode anzeigen
</router-link>
<div class="group-list__content">
<h2 class="group-list__heading"><span
class="group-list__name"
data-cy="group-list-name">{{ name }}</span>
<edit-group-name
v-if="canEdit"
@edit="$emit('edit')"/>
</h2>
<div class="group-list__members group-list-members">
<ul
class="group-list-members__list simple-list simple-list--active"
data-cy="active-class-members-list">
<li
:key="member.id"
class="simple-list__item member-item"
data-cy="group-list-member"
v-for="member in activeMembers">
<span class="member-item__name">{{ fullName(member) }}</span>
<span class="member-item__role">{{ role(member) }}</span>
<!-- <a-->
<!-- class="member-item__action simple-list__action"-->
<!-- data-cy="remove-from-class"-->
<!-- v-if="teacher"-->
<!-- @click="$emit('remove', member)">Deaktivieren</a>-->
</li>
</ul>
<!-- <template v-if="inactiveMembers.length">-->
<!-- <h3 class="group-list__inactive-heading">Deaktivierte Personen</h3>-->
<!-- <ul data-cy="inactive-class-members-list" class="simple-list simple-list&#45;&#45;inactive">-->
<!-- <li-->
<!-- class="simple-list__item member-item"-->
<!-- data-cy="group-list-member"-->
<!-- v-for="member in inactiveMembers"-->
<!-- :key="member.id">-->
<!-- <span class="member-item__name">{{fullName(member)}}</span>-->
<!-- <span class="member-item__role">{{role(member)}}</span>-->
<!-- <a-->
<!-- class="member-item__action simple-list__action"-->
<!-- data-cy="add-to-class"-->
<!-- v-if="teacher"-->
<!-- @click="$emit('add', member)">Aktivieren</a>-->
<!-- </li>-->
<!-- </ul>-->
<!-- </template>-->
</div>
</div>
</div>
</template>
<script>
import EditGroupName from '@/components/profile/EditGroupName';
export default {
// props: ['active-members', 'inactive-members', 'name', 'canEdit'],
props: {
title: {
type: String,
default: '',
},
showCode: {
type: Boolean,
default: false,
},
showCodeRoute: {
type: Object,
default: () => ({}),
},
activeMembers: {
type: Array,
default: () => [],
},
inactiveMembers: {
type: Array,
default: () => [],
},
name: {
type: String,
default: '',
},
canEdit: {
type: Boolean,
default: false,
},
},
components: {
EditGroupName,
},
methods: {
fullName(member) {
return `${member.firstName} ${member.lastName}`;
},
role({isTeacher}) {
if (isTeacher === undefined) {
return '';
}
return isTeacher ? 'Lehrperson' : 'Schüler';
},
},
};
</script>
<style scoped lang="scss">
@import "~styles/helpers";
.group-list {
display: grid;
grid-template-columns: auto auto;
grid-template-rows: auto auto;
grid-template-areas: "h b" "c c";
&__header {
grid-area: h;
}
&__code-link {
grid-area: b;
justify-self: end;
align-self: center;
}
&__content {
grid-area: c;
width: 100%;
margin-bottom: $large-spacing;
}
&__inactive-heading {
@include heading-4;
margin-bottom: $small-spacing;
}
&__name {
@include heading-2;
}
}
.member-item {
&__name {
font-family: $sans-serif-font-family;
font-weight: $font-weight-bold;
flex: 2 1 auto;
}
&__role {
flex: 0 1 110px;
text-align: right;
}
&__action {
flex: 0 1 110px;
padding-left: $large-spacing;
}
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div>
<h1 data-cy="join-class-title">{{ title }}</h1>
<h1 data-cy="join-form-title">{{ title }}</h1>
<div>
<div class="skillboxform-input">
<label
@ -10,7 +10,7 @@
:class="{'skillboxform-input__input--error': error}"
:value="value"
class="skillbox-input skillboxform-input__input"
data-cy="input-class-code"
data-cy="input-form-code"
id="join-code"
@input="$emit('input', $event)">
<small
@ -23,11 +23,11 @@
<div>
<a
class="button button--primary button--big"
data-cy="join-class"
data-cy="join-form-confirm"
@click="$emit('confirm', value)">{{ okText }}</a>
<button
class="button button--big"
data-cy="join-class-cancel"
data-cy="join-form-cancel"
@click="$emit('cancel')">{{ cancelText }}
</button>
</div>

View File

@ -0,0 +1,42 @@
<template>
<div class="show-code">
<h2 class="show-code__title">Zugangscode {{ type }} {{ name }}</h2>
<h1 class="show-code__code">{{ code }}</h1>
</div>
</template>
<script>
export default {
props: {
code: {
type: String,
default: '',
},
type: {
type: String,
default: '',
},
name: {
type: String,
default: '',
},
},
};
</script>
<style scoped lang="scss">
@import '~styles/helpers';
.show-code {
&__title {
@include regular-text;
margin-bottom: 2*$large-spacing;
}
&__code {
font-size: toRem(120px);
letter-spacing: toRem(20px);
font-weight: 600;
}
}
</style>

View File

@ -0,0 +1,76 @@
<template>
<div class="my-team">
<template v-if="me.team">
<group-list
:active-members="me.team.members"
:can-edit="true"
:show-code-route="showCodeRoute"
:show-code="true"
:name="me.team.name"
title="Mein Team"
/>
</template>
<template v-else>
<h1 class="my-team__heading">Mein Team {{ me.team }}</h1>
<div class="my-team__section">
<h2 class="my-team__subheading">Willst du einem bestehenden Team beitreten?</h2>
<router-link
:to="joinTeamRoute"
class="button button--primary">Zugangscode eingeben
</router-link>
</div>
<div class="my-team__section">
<h2 class="my-team__subheading">Willst du ein neues Team erfassen?</h2>
<router-link
:to="createTeamRoute"
class="button button--primary">Team erfassen
</router-link>
</div>
</template>
</div>
</template>
<script>
import {CREATE_TEAM, JOIN_TEAM, SHOW_TEAM_CODE} from '@/router/me.names';
import me from '@/mixins/me';
import GroupList from '@/components/profile/GroupList';
export default {
mixins: [me],
components: {GroupList},
data() {
return {
joinTeamRoute: {
name: JOIN_TEAM,
},
createTeamRoute: {
name: CREATE_TEAM,
},
showCodeRoute: {
name: SHOW_TEAM_CODE
}
};
},
};
</script>
<style scoped lang="scss">
@import '~styles/helpers';
.my-team {
&__heading {
margin-bottom: $section-spacing;
}
&__section {
margin-bottom: $section-spacing;
}
&__subheading {
@include heading-3;
margin-bottom: $large-spacing;
}
}
</style>

View File

@ -0,0 +1,17 @@
<template>
<show-code
:name="me.selectedClass.name"
:code="me.selectedClass.code"
class="show-school-class-code"
type="Klasse"/>
</template>
<script>
import selectedClassMixin from '@/mixins/selected-class';
import ShowCode from '@/components/profile/ShowCode';
export default {
mixins: [selectedClassMixin],
components: {ShowCode},
};
</script>

View File

@ -1,53 +0,0 @@
<template>
<div class="my-team">
<h1 class="my-team__heading">Mein Team</h1>
<div class="my-team__section">
<h2 class="my-team__subheading">Willst du einem bestehenden Team beitreten?</h2>
<router-link
:to="joinTeamRoute"
class="button button--primary">Zugangscode eingeben</router-link>
</div>
<div class="my-team__section">
<h2 class="my-team__subheading">Willst du ein neues Team erfassen?</h2>
<router-link
:to="createTeamRoute"
class="button button--primary">Team erfassen</router-link>
</div>
</div>
</template>
<script>
import {JOIN_TEAM, CREATE_TEAM} from '@/router/me.names';
export default {
data() {
return {
joinTeamRoute: {
name: JOIN_TEAM
},
createTeamRoute: {
name: CREATE_TEAM
}
};
},
};
</script>
<style scoped lang="scss">
@import '~styles/helpers';
.my-team {
&__heading {
margin-bottom: $section-spacing;
}
&__section {
margin-bottom: $section-spacing;
}
&__subheading {
@include heading-3;
margin-bottom: $large-spacing;
}
}
</style>

View File

@ -1,37 +1,41 @@
<template>
<div class="my-class">
<h1
class="my-class__header"
data-cy="class-list-title">Klassenliste</h1>
<router-link
:to="{name: 'show-code'}"
class="my-class__code-link button button--primary"
v-if="me.isTeacher">Zugangscode anzeigen
</router-link>
<class-list
<group-list
:name="me.selectedClass.name"
:members="me.selectedClass.members"
:teacher="me.isTeacher"
:id="me.selectedClass.id"
:active-members="me.selectedClass.members.filter(member => member.active)"
:inactive-members="me.selectedClass.members.filter(member => !member.active)"
:show-code="me.isTeacher"
:show-code-route="showCodeRoute"
:can-edit="me.isTeacher"
title="Klassenliste"
class="my-class__class"
@remove="remove"
@add="add"
@edit="editClassName"
/>
</div>
</template>
<script>
import ClassList from '@/components/profile/ClassList';
import GroupList from '@/components/profile/GroupList';
import MY_SCHOOL_CLASS_QUERY from '@/graphql/gql/mySchoolClass.gql';
import ADD_REMOVE_MEMBER_MUTATION from '@/graphql/gql/mutations/addRemoveMember.gql';
import selectedClassMixin from '@/mixins/selected-class';
import {SHOW_SCHOOL_CLASS_CODE} from '@/router/me.names';
export default {
mixins: [selectedClassMixin],
components: {
ClassList
GroupList,
},
data() {
return {
showCodeRoute: {
name: SHOW_SCHOOL_CLASS_CODE,
},
};
},
methods: {
@ -42,8 +46,8 @@
input: {
member: member.id,
schoolClass: this.me.selectedClass.id,
active
}
active,
},
},
update(store, {data: {addRemoveMember: {success}}}) {
if (success) {
@ -57,7 +61,7 @@
];
store.writeQuery({query, data});
}
}
},
});
},
add(member) {
@ -65,15 +69,18 @@
},
remove(member) {
this.$modal.open('deactivate-person', {
myself: member.id === this.me.id,
name: `${member.firstName} ${member.lastName}`,
className: this.me.selectedClass.name,
})
.then(() => {
this.changeMember(member, false);
})
.catch(() => {
});
myself: member.id === this.me.id,
name: `${member.firstName} ${member.lastName}`,
className: this.me.selectedClass.name,
})
.then(() => {
this.changeMember(member, false);
})
.catch(() => {
});
},
editClassName() {
this.$store.dispatch('editClassName');
}
},
};

View File

@ -5,9 +5,7 @@
</template>
<style scoped lang="scss">
@import "@/styles/_variables.scss";
@import "@/styles/_functions.scss";
@import "@/styles/_mixins.scss";
@import "~styles/helpers";
.profile {
padding: $large-spacing;

View File

@ -1,32 +0,0 @@
<template>
<div class="show-code">
<h2 class="show-code__title">Zugangscode Klasse {{ me.selectedClass.name }}</h2>
<h1 class="show-code__code">{{ me.selectedClass.code }}</h1>
</div>
</template>
<script>
import selectedClassMixin from '@/mixins/selected-class';
export default {
mixins: [selectedClassMixin],
};
</script>
<style scoped lang="scss">
@import "@/styles/_variables.scss";
@import "@/styles/_mixins.scss";
.show-code {
&__title {
@include regular-text;
margin-bottom: 2*$large-spacing;
}
&__code {
font-size: toRem(120px);
letter-spacing: toRem(20px);
font-weight: 600;
}
}
</style>