Move project and room actions to own component
Also adds those actions to the detail pages of both entity types. Also refactors some code.
This commit is contained in:
parent
016f6ce502
commit
590fd180c3
|
|
@ -1,41 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="widget-footer">
|
<div class="widget-footer">
|
||||||
<a @click="toggleMenu"
|
<slot></slot>
|
||||||
class="widget-footer__more-link">
|
|
||||||
<ellipses></ellipses>
|
|
||||||
</a>
|
|
||||||
<widget-popover v-if="showMenu"
|
|
||||||
@hide-me="showMenu = false">
|
|
||||||
<slot :hide="toggleMenu"></slot>
|
|
||||||
</widget-popover>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
import Ellipses from '@/components/icons/Ellipses.vue';
|
|
||||||
import WidgetPopover from '@/components/rooms/WidgetPopover';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
|
|
||||||
components: {
|
|
||||||
Ellipses,
|
|
||||||
WidgetPopover
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showMenu: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
toggleMenu: function () {
|
|
||||||
this.showMenu = !this.showMenu
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import "@/styles/_variables.scss";
|
@import "@/styles/_variables.scss";
|
||||||
@import "@/styles/_mixins.scss";
|
@import "@/styles/_mixins.scss";
|
||||||
|
|
@ -58,15 +26,5 @@
|
||||||
* For IE10+
|
* For IE10+
|
||||||
*/
|
*/
|
||||||
-ms-grid-row: 2;
|
-ms-grid-row: 2;
|
||||||
|
|
||||||
&__more-link {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
width: 30px;
|
|
||||||
fill: $color-darkgrey-1;
|
|
||||||
margin-right: 15px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="owner-widget">
|
<div class="owner-widget">
|
||||||
<avatar class="owner-widget__avatar" :avatarUrl="avatarUrl" />
|
<avatar class="owner-widget__avatar" :avatarUrl="owner.avatarUrl" />
|
||||||
<span>
|
<span>
|
||||||
{{name}}
|
{{name}}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -11,10 +11,16 @@
|
||||||
import Avatar from '@/components/profile/Avatar';
|
import Avatar from '@/components/profile/Avatar';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['name', 'avatarUrl'],
|
props: ['owner'],
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
Avatar
|
Avatar
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
name() {
|
||||||
|
return `${this.owner.firstName} ${this.owner.lastName}`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -26,7 +32,6 @@
|
||||||
.owner-widget {
|
.owner-widget {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: $small-spacing;
|
|
||||||
|
|
||||||
&__avatar {
|
&__avatar {
|
||||||
width: 30px;
|
width: 30px;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
<template>
|
||||||
|
<div class="project-actions">
|
||||||
|
<a @click="toggleMenu"
|
||||||
|
class="project-actions__more-link">
|
||||||
|
<ellipses></ellipses>
|
||||||
|
</a>
|
||||||
|
<widget-popover v-if="showMenu"
|
||||||
|
@hide-me="showMenu = false">
|
||||||
|
<li class="popover-links__link"><a @click="deleteProject(id)">Projekt löschen</a></li>
|
||||||
|
<li class="popover-links__link"><a @click="editProject(id)">Projekt bearbeiten</a></li>
|
||||||
|
<li v-if="!final" class="popover-links__link"><a @click="updateShareState(id, true)">Projekt teilen</a></li>
|
||||||
|
<li v-if="final" class="popover-links__link"><a @click="updateShareState(id, false)">Projekt nicht mehr teilen</a>
|
||||||
|
</li>
|
||||||
|
</widget-popover>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Ellipses from '@/components/icons/Ellipses.vue';
|
||||||
|
import WidgetPopover from '@/components/rooms/WidgetPopover';
|
||||||
|
|
||||||
|
import DELETE_PROJECT_MUTATION from '@/graphql/gql/mutations/deleteProject.gql';
|
||||||
|
import PROJECT_QUERY from '@/graphql/gql/projectQuery.gql';
|
||||||
|
import PROJECTS_QUERY from '@/graphql/gql/allProjects.gql';
|
||||||
|
import UPDATE_PROJECT_SHARED_STATE_MUTATION from '@/graphql/gql/mutations/updateProjectSharedState.gql';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ['id', 'final'],
|
||||||
|
|
||||||
|
components: {
|
||||||
|
Ellipses,
|
||||||
|
WidgetPopover
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showMenu: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
toggleMenu: function () {
|
||||||
|
this.showMenu = !this.showMenu
|
||||||
|
},
|
||||||
|
editProject(id) {
|
||||||
|
this.$router.push({name: 'edit-project', params: {id}});
|
||||||
|
},
|
||||||
|
deleteProject(id) {
|
||||||
|
this.$apollo.mutate({
|
||||||
|
mutation: DELETE_PROJECT_MUTATION,
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
},
|
||||||
|
update(store, {data: {deleteProject: {success}}}) {
|
||||||
|
if (success) {
|
||||||
|
const data = store.readQuery({query: PROJECTS_QUERY});
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
data.projects.edges.splice(data.projects.edges.findIndex(edge => edge.node.id === id), 1);
|
||||||
|
store.writeQuery({query: PROJECTS_QUERY, data});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).then(() => {
|
||||||
|
this.$router.push('/portfolio');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
updateShareState(id, state) {
|
||||||
|
const project = this;
|
||||||
|
this.$apollo.mutate({
|
||||||
|
mutation: UPDATE_PROJECT_SHARED_STATE_MUTATION,
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
id: this.id,
|
||||||
|
shared: state
|
||||||
|
}
|
||||||
|
},
|
||||||
|
update(store, {data: {updateProjectSharedState: {shared, errors}}}) {
|
||||||
|
if (!errors) {
|
||||||
|
const query = PROJECT_QUERY;
|
||||||
|
const variables = {
|
||||||
|
id: project.id
|
||||||
|
};
|
||||||
|
const data = store.readQuery({query, variables});
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
data.project.final = shared;
|
||||||
|
store.writeQuery({query, variables, data});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import "@/styles/_variables.scss";
|
||||||
|
|
||||||
|
.project-actions {
|
||||||
|
&__more-link {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 30px;
|
||||||
|
fill: $color-darkgrey-1;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,24 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="project-widget" :class="widgetClass">
|
<div class="project-widget" :class="widgetClass">
|
||||||
<router-link :to="{name: 'project', params: {slug: slug}}" tag="div" class="project-widget__content" data-cy="project-link">
|
<router-link :to="{name: 'project', params: {slug: slug}}" tag="div" class="project-widget__content"
|
||||||
|
data-cy="project-link">
|
||||||
<h3 class="project-widget__title">{{title}}</h3>
|
<h3 class="project-widget__title">{{title}}</h3>
|
||||||
|
|
||||||
<entry-count-widget :entry-count="entriesCount"></entry-count-widget>
|
<entry-count-widget :entry-count="entriesCount"></entry-count-widget>
|
||||||
<owner-widget :name="owner" :avatarUrl="student.avatarUrl"></owner-widget>
|
<owner-widget class="project-widget__owner" :owner="student"></owner-widget>
|
||||||
</router-link>
|
</router-link>
|
||||||
<widget-footer v-if="isOwner" class="project-widget__footer">
|
<widget-footer v-if="isOwner" class="project-widget__footer">
|
||||||
<template slot-scope="scope">
|
<project-actions :id="id" :final="final"></project-actions>
|
||||||
<li class="popover-links__link"><a @click="$emit('delete', id)">Projekt löschen</a></li>
|
|
||||||
<li class="popover-links__link"><a @click="$emit('edit', id)">Projekt bearbeiten</a></li>
|
|
||||||
<li v-if="!final" class="popover-links__link"><a @click="share(scope)">Projekt teilen</a></li>
|
|
||||||
<li v-if="final" class="popover-links__link"><a @click="unshare(scope)">Projekt nicht mehr teilen</a></li>
|
|
||||||
</template>
|
|
||||||
</widget-footer>
|
</widget-footer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import OwnerWidget from '@/components/portfolio/OwnerWidget';
|
import OwnerWidget from '@/components/portfolio/OwnerWidget';
|
||||||
|
import ProjectActions from '@/components/portfolio/ProjectActions';
|
||||||
import EntryCountWidget from '@/components/rooms/EntryCountWidget';
|
import EntryCountWidget from '@/components/rooms/EntryCountWidget';
|
||||||
import WidgetFooter from '@/components/WidgetFooter';
|
import WidgetFooter from '@/components/WidgetFooter';
|
||||||
|
|
||||||
|
|
@ -28,33 +25,19 @@
|
||||||
components: {
|
components: {
|
||||||
WidgetFooter,
|
WidgetFooter,
|
||||||
EntryCountWidget,
|
EntryCountWidget,
|
||||||
OwnerWidget
|
OwnerWidget,
|
||||||
|
ProjectActions
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
widgetClass () {
|
widgetClass() {
|
||||||
return `project-widget--${this.appearance}`;
|
return `project-widget--${this.appearance}`;
|
||||||
},
|
},
|
||||||
isOwner () {
|
isOwner() {
|
||||||
return this.student.id === this.userId;
|
return this.student.id === this.userId;
|
||||||
},
|
},
|
||||||
owner () {
|
|
||||||
return `${this.student.firstName} ${this.student.lastName}`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
},
|
||||||
share: function (scope) {
|
|
||||||
this.updateShare(scope, true);
|
|
||||||
},
|
|
||||||
unshare: function (scope) {
|
|
||||||
this.updateShare(scope, false);
|
|
||||||
},
|
|
||||||
updateShare: function (scope, state) {
|
|
||||||
scope.hide();
|
|
||||||
this.$emit('updateShare', this.id, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -68,6 +51,7 @@
|
||||||
background-color: $color-accent-4;
|
background-color: $color-accent-4;
|
||||||
@include widget-shadow;
|
@include widget-shadow;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
display: -ms-grid;
|
display: -ms-grid;
|
||||||
margin-bottom: $large-spacing;
|
margin-bottom: $large-spacing;
|
||||||
|
|
@ -106,6 +90,10 @@
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__owner {
|
||||||
|
margin-top: $small-spacing;
|
||||||
|
}
|
||||||
|
|
||||||
&__footer {
|
&__footer {
|
||||||
-ms-grid-row: 2;
|
-ms-grid-row: 2;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
<template>
|
||||||
|
<div class="room-actions">
|
||||||
|
<a @click="toggleMenu"
|
||||||
|
class="room-actions__more-link">
|
||||||
|
<ellipses></ellipses>
|
||||||
|
</a>
|
||||||
|
<widget-popover v-if="showMenu"
|
||||||
|
@hide-me="showMenu = false">
|
||||||
|
<li class="popover-links__link"><a @click="deleteRoom()">Raum löschen</a></li>
|
||||||
|
<li class="popover-links__link"><a @click="editRoom()">Raum bearbeiten</a></li>
|
||||||
|
</widget-popover>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Ellipses from '@/components/icons/Ellipses.vue';
|
||||||
|
import WidgetPopover from '@/components/rooms/WidgetPopover';
|
||||||
|
|
||||||
|
import DELETE_ROOM_MUTATION from '@/graphql/gql/mutations/deleteRoom.gql';
|
||||||
|
import ROOMS_QUERY from '@/graphql/gql/roomsQuery.gql';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ['id'],
|
||||||
|
|
||||||
|
components: {
|
||||||
|
Ellipses,
|
||||||
|
WidgetPopover
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showMenu: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
toggleMenu: function () {
|
||||||
|
this.showMenu = !this.showMenu
|
||||||
|
},
|
||||||
|
deleteRoom() {
|
||||||
|
const theId = this.id;
|
||||||
|
this.$apollo.mutate({
|
||||||
|
mutation: DELETE_ROOM_MUTATION,
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
id: theId
|
||||||
|
}
|
||||||
|
},
|
||||||
|
update(store, {data: {deleteRoom: {success}}}) {
|
||||||
|
if (success) {
|
||||||
|
const data = store.readQuery({query: ROOMS_QUERY});
|
||||||
|
if (data) {
|
||||||
|
data.rooms.edges.splice(data.rooms.edges.findIndex(edge => edge.node.id === theId), 1);
|
||||||
|
store.writeQuery({query: ROOMS_QUERY, data});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
editRoom() {
|
||||||
|
this.$router.push({name: 'edit-room', params: {id: this.id}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import "@/styles/_variables.scss";
|
||||||
|
|
||||||
|
.room-actions {
|
||||||
|
&__more-link {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 30px;
|
||||||
|
fill: $color-darkgrey-1;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -6,19 +6,17 @@
|
||||||
<entry-count-widget :entryCount="entryCount"></entry-count-widget>
|
<entry-count-widget :entryCount="entryCount"></entry-count-widget>
|
||||||
</router-link>
|
</router-link>
|
||||||
<widget-footer v-if="canEditRoom">
|
<widget-footer v-if="canEditRoom">
|
||||||
<li class="popover-links__link"><a @click="deleteRoom()">Raum löschen</a></li>
|
<room-actions :id="this.id"></room-actions>
|
||||||
<li class="popover-links__link"><a @click="editRoom()">Raum bearbeiten</a></li>
|
|
||||||
</widget-footer>
|
</widget-footer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import DELETE_ROOM_MUTATION from '@/graphql/gql/mutations/deleteRoom.gql';
|
|
||||||
import ROOMS_QUERY from '@/graphql/gql/roomsQuery.gql';
|
|
||||||
|
|
||||||
import RoomGroupWidget from '@/components/rooms/RoomGroupWidget';
|
import RoomGroupWidget from '@/components/rooms/RoomGroupWidget';
|
||||||
import EntryCountWidget from '@/components/rooms/EntryCountWidget';
|
import EntryCountWidget from '@/components/rooms/EntryCountWidget';
|
||||||
import WidgetFooter from '@/components/WidgetFooter';
|
import WidgetFooter from '@/components/WidgetFooter';
|
||||||
|
import RoomActions from '@/components/rooms/RoomActions';
|
||||||
|
|
||||||
import {meQuery} from '@/graphql/queries';
|
import {meQuery} from '@/graphql/queries';
|
||||||
|
|
||||||
|
|
@ -28,7 +26,8 @@
|
||||||
components: {
|
components: {
|
||||||
EntryCountWidget,
|
EntryCountWidget,
|
||||||
RoomGroupWidget,
|
RoomGroupWidget,
|
||||||
WidgetFooter
|
WidgetFooter,
|
||||||
|
RoomActions
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -52,32 +51,6 @@
|
||||||
apollo: {
|
apollo: {
|
||||||
me: meQuery
|
me: meQuery
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
|
||||||
deleteRoom() {
|
|
||||||
const theId = this.id
|
|
||||||
this.$apollo.mutate({
|
|
||||||
mutation: DELETE_ROOM_MUTATION,
|
|
||||||
variables: {
|
|
||||||
input: {
|
|
||||||
id: theId
|
|
||||||
}
|
|
||||||
},
|
|
||||||
update(store, {data: {deleteRoom: {success}}}) {
|
|
||||||
if (success) {
|
|
||||||
const data = store.readQuery({query: ROOMS_QUERY});
|
|
||||||
if (data) {
|
|
||||||
data.rooms.edges.splice(data.rooms.edges.findIndex(edge => edge.node.id === theId), 1);
|
|
||||||
store.writeQuery({query: ROOMS_QUERY, data});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
editRoom() {
|
|
||||||
this.$router.push({name: 'edit-room', params: {id: this.id}});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
methods: {
|
methods: {
|
||||||
hidePopover() {
|
hidePopover() {
|
||||||
this.$emit('hide-me');
|
this.$emit('hide-me');
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
mutation UpdateProjectShareState($input: UpdateProjectSharedStateInput!) {
|
||||||
|
updateProjectSharedState(input: $input) {
|
||||||
|
errors
|
||||||
|
success
|
||||||
|
shared
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,9 +7,6 @@
|
||||||
v-for="project in projects"
|
v-for="project in projects"
|
||||||
v-bind="project"
|
v-bind="project"
|
||||||
:userId="userId"
|
:userId="userId"
|
||||||
@delete="deleteProject"
|
|
||||||
@updateShare="updateShareState"
|
|
||||||
@edit="editProject"
|
|
||||||
:key="project.id"
|
:key="project.id"
|
||||||
class="portfolio__project"
|
class="portfolio__project"
|
||||||
></project-widget>
|
></project-widget>
|
||||||
|
|
@ -23,8 +20,6 @@
|
||||||
|
|
||||||
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
||||||
import PROJECTS_QUERY from '@/graphql/gql/allProjects.gql';
|
import PROJECTS_QUERY from '@/graphql/gql/allProjects.gql';
|
||||||
import DELETE_PROJECT_MUTATION from '@/graphql/gql/mutations/deleteProject.gql';
|
|
||||||
import UPDATE_PROJECT_MUTATION from '@/graphql/gql/mutations/updateProject.gql';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -57,50 +52,6 @@
|
||||||
return this.me.id;
|
return this.me.id;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
|
||||||
deleteProject(id) {
|
|
||||||
this.$apollo.mutate({
|
|
||||||
mutation: DELETE_PROJECT_MUTATION,
|
|
||||||
variables: {
|
|
||||||
input: {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
},
|
|
||||||
update(store, {data: {deleteProject: {success}}}) {
|
|
||||||
if (success) {
|
|
||||||
const data = store.readQuery({query: PROJECTS_QUERY});
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
data.projects.edges.splice(data.projects.edges.findIndex(edge => edge.node.id === id), 1);
|
|
||||||
store.writeQuery({query: PROJECTS_QUERY, data});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
editProject(id) {
|
|
||||||
this.$router.push({name: 'edit-project', params: {id}});
|
|
||||||
},
|
|
||||||
updateShareState(id, state) {
|
|
||||||
const project = this.projects.filter(project => project.id === id)[0];
|
|
||||||
this.$apollo.mutate({
|
|
||||||
mutation: UPDATE_PROJECT_MUTATION,
|
|
||||||
variables: {
|
|
||||||
input: {
|
|
||||||
project: {
|
|
||||||
id: project.id,
|
|
||||||
title: project.title,
|
|
||||||
description: project.description,
|
|
||||||
appearance: project.appearance,
|
|
||||||
objectives: project.objectives,
|
|
||||||
final: state
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,16 @@
|
||||||
<li class="project__objective" :key="index" v-for="(objective, index) in objectives">{{objective}}</li>
|
<li class="project__objective" :key="index" v-for="(objective, index) in objectives">{{objective}}</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<div class="project__meta">
|
||||||
|
<project-actions :id="this.project.id"></project-actions>
|
||||||
|
<owner-widget :owner="this.project.student"></owner-widget>
|
||||||
|
<entry-count-widget :entry-count="projectEntryCount"></entry-count-widget>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="project__content">
|
<div class="project__content">
|
||||||
<add-project-entry v-if="isOwner" class="project__add-entry" data-cy="add-project-entry" :project="project.id"></add-project-entry>
|
<add-project-entry v-if="isOwner" class="project__add-entry" data-cy="add-project-entry"
|
||||||
|
:project="project.id"></add-project-entry>
|
||||||
<project-entry v-bind="entry" v-for="(entry, index) in project.entries" :key="index"></project-entry>
|
<project-entry v-bind="entry" v-for="(entry, index) in project.entries" :key="index"></project-entry>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -21,7 +28,10 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ProjectEntry from '@/components/portfolio/ProjectEntry';
|
import ProjectEntry from '@/components/portfolio/ProjectEntry';
|
||||||
|
import ProjectActions from '@/components/portfolio/ProjectActions';
|
||||||
import AddProjectEntry from '@/components/portfolio/AddProjectEntry';
|
import AddProjectEntry from '@/components/portfolio/AddProjectEntry';
|
||||||
|
import EntryCountWidget from '@/components/rooms/EntryCountWidget';
|
||||||
|
import OwnerWidget from '@/components/portfolio/OwnerWidget';
|
||||||
|
|
||||||
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
||||||
import PROJECT_QUERY from '@/graphql/gql/projectQuery.gql';
|
import PROJECT_QUERY from '@/graphql/gql/projectQuery.gql';
|
||||||
|
|
@ -31,7 +41,10 @@
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
AddProjectEntry,
|
AddProjectEntry,
|
||||||
ProjectEntry
|
ProjectEntry,
|
||||||
|
ProjectActions,
|
||||||
|
EntryCountWidget,
|
||||||
|
OwnerWidget
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -44,7 +57,10 @@
|
||||||
},
|
},
|
||||||
isOwner() {
|
isOwner() {
|
||||||
return this.me.id === this.project.student.id;
|
return this.me.id === this.project.student.id;
|
||||||
}
|
},
|
||||||
|
projectEntryCount() {
|
||||||
|
return this.project.entries ? this.project.entries.length : 0;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
apollo: {
|
apollo: {
|
||||||
|
|
@ -129,12 +145,33 @@
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__content {
|
&__meta {
|
||||||
background-color: $color-grey--lighter;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
max-width: 840px;
|
@include desktop {
|
||||||
align-content: center;
|
flex-direction: row-reverse;
|
||||||
|
}
|
||||||
|
justify-content: start;
|
||||||
|
position: relative;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
& > :first-child {
|
||||||
|
margin-left: $large-spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > :nth-child(2) {
|
||||||
|
margin-left: $large-spacing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
background-color: rgba($color-darkgrey-1, 0.18);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
/*max-width: 840px;*/
|
||||||
|
width: 100%;
|
||||||
|
min-height: 75vh;
|
||||||
|
align-content: start;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@supports (display: grid) {
|
@supports (display: grid) {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
{{room.description}}
|
{{room.description}}
|
||||||
</p>
|
</p>
|
||||||
<div class="room__meta">
|
<div class="room__meta">
|
||||||
|
<room-actions :id="this.room.id"></room-actions>
|
||||||
<room-group-widget v-bind="room.schoolClass"></room-group-widget>
|
<room-group-widget v-bind="room.schoolClass"></room-group-widget>
|
||||||
<entry-count-widget :entry-count="roomEntryCount"></entry-count-widget>
|
<entry-count-widget :entry-count="roomEntryCount"></entry-count-widget>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -29,6 +30,7 @@
|
||||||
import RoomEntry from '@/components/rooms/RoomEntry.vue';
|
import RoomEntry from '@/components/rooms/RoomEntry.vue';
|
||||||
import RoomGroupWidget from '@/components/rooms/RoomGroupWidget';
|
import RoomGroupWidget from '@/components/rooms/RoomGroupWidget';
|
||||||
import EntryCountWidget from '@/components/rooms/EntryCountWidget';
|
import EntryCountWidget from '@/components/rooms/EntryCountWidget';
|
||||||
|
import RoomActions from '@/components/rooms/RoomActions';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['slug'],
|
props: ['slug'],
|
||||||
|
|
@ -37,7 +39,8 @@
|
||||||
EntryCountWidget,
|
EntryCountWidget,
|
||||||
RoomGroupWidget,
|
RoomGroupWidget,
|
||||||
AddRoomEntryButton,
|
AddRoomEntryButton,
|
||||||
RoomEntry
|
RoomEntry,
|
||||||
|
RoomActions
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
|
|
@ -115,9 +118,14 @@
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
}
|
}
|
||||||
justify-content: start;
|
justify-content: start;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
& > :first-child {
|
& > :first-child {
|
||||||
margin-right: 45px;
|
margin-left: $large-spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > :nth-child(2) {
|
||||||
|
margin-left: $large-spacing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,38 @@ class DeleteProjectEntry(relay.ClientIDMutation):
|
||||||
return cls(success=True)
|
return cls(success=True)
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateProjectSharedState(relay.ClientIDMutation):
|
||||||
|
class Input:
|
||||||
|
id = graphene.ID()
|
||||||
|
shared = graphene.Boolean()
|
||||||
|
|
||||||
|
success = graphene.Boolean()
|
||||||
|
shared = graphene.Boolean()
|
||||||
|
errors = graphene.List(graphene.String)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def mutate_and_get_payload(cls, root, info, **args):
|
||||||
|
try:
|
||||||
|
id = args.get('id')
|
||||||
|
shared = args.get('shared')
|
||||||
|
user = info.context.user
|
||||||
|
|
||||||
|
project = get_object(Project, id)
|
||||||
|
if project.student != user:
|
||||||
|
raise PermissionError()
|
||||||
|
project.final = shared
|
||||||
|
project.save()
|
||||||
|
|
||||||
|
return cls(success=True, shared=shared)
|
||||||
|
|
||||||
|
except PermissionError:
|
||||||
|
errors = ["You don't have the permission to do that."]
|
||||||
|
except Exception as e:
|
||||||
|
errors = ['Error: {}'.format(e)]
|
||||||
|
|
||||||
|
return cls(success=False, shared=None, errors=errors)
|
||||||
|
|
||||||
|
|
||||||
class PortfolioMutations:
|
class PortfolioMutations:
|
||||||
add_project = AddProject.Field()
|
add_project = AddProject.Field()
|
||||||
update_project = UpdateProject.Field()
|
update_project = UpdateProject.Field()
|
||||||
|
|
@ -150,3 +182,4 @@ class PortfolioMutations:
|
||||||
add_project_entry = AddProjectEntry.Field()
|
add_project_entry = AddProjectEntry.Field()
|
||||||
update_project_entry = UpdateProjectEntry.Field()
|
update_project_entry = UpdateProjectEntry.Field()
|
||||||
delete_project_entry = DeleteProjectEntry.Field()
|
delete_project_entry = DeleteProjectEntry.Field()
|
||||||
|
update_project_shared_state = UpdateProjectSharedState.Field()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue