Add a dropdown on participate menu, disallow listing participations
Now requires quering the person endpoint to know if an actor
participates in an event, organizers can make authenticated requests to
event { participants { } } to see the pending / approved participants.
Also closes #174
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -1,29 +1,22 @@
|
||||
<template>
|
||||
<div class="identity-picker">
|
||||
<img class="image" v-if="currentIdentity.avatar" :src="currentIdentity.avatar.url" :alt="currentIdentity.avatar.alt"/> {{ currentIdentity.name || `@${currentIdentity.preferredUsername}` }}
|
||||
<b-button type="is-text" @click="isComponentModalActive = true">
|
||||
{{ $t('Change') }}
|
||||
</b-button>
|
||||
<b-modal :active.sync="isComponentModalActive" has-modal-card>
|
||||
<div class="modal-card">
|
||||
<header class="modal-card-head">
|
||||
<p class="modal-card-title">{{ $t('Pick an identity') }}</p>
|
||||
</header>
|
||||
<section class="modal-card-body">
|
||||
<div class="list is-hoverable">
|
||||
<a class="list-item" v-for="identity in identities" :class="{ 'is-active': identity.id === currentIdentity.id }" @click="changeCurrentIdentity(identity)">
|
||||
<div class="media">
|
||||
<img class="media-left image" v-if="identity.avatar" :src="identity.avatar.url" />
|
||||
<div class="media-content">
|
||||
<h3>@{{ identity.preferredUsername }}</h3>
|
||||
<small>{{ identity.name }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="modal-card">
|
||||
<header class="modal-card-head">
|
||||
<p class="modal-card-title">{{ $t('Pick an identity') }}</p>
|
||||
</header>
|
||||
<section class="modal-card-body">
|
||||
<div class="list is-hoverable">
|
||||
<a class="list-item" v-for="identity in identities" :class="{ 'is-active': identity.id === currentIdentity.id }" @click="changeCurrentIdentity(identity)">
|
||||
<div class="media">
|
||||
<img class="media-left image" v-if="identity.avatar" :src="identity.avatar.url" />
|
||||
<div class="media-content">
|
||||
<h3>@{{ identity.preferredUsername }}</h3>
|
||||
<small>{{ identity.name }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</a>
|
||||
</div>
|
||||
</b-modal>
|
||||
</section>
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
@@ -40,22 +33,13 @@ import { IDENTITIES } from '@/graphql/actor';
|
||||
})
|
||||
export default class IdentityPicker extends Vue {
|
||||
@Prop() value!: IActor;
|
||||
isComponentModalActive: boolean = false;
|
||||
identities: IActor[] = [];
|
||||
currentIdentity: IActor = this.value;
|
||||
|
||||
changeCurrentIdentity(identity: IActor) {
|
||||
this.currentIdentity = identity;
|
||||
this.$emit('input', identity);
|
||||
this.isComponentModalActive = false;
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.identity-picker img.image {
|
||||
display: inline;
|
||||
height: 1.5em;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
</style>
|
||||
</script>
|
||||
39
js/src/views/Account/IdentityPickerWrapper.vue
Normal file
39
js/src/views/Account/IdentityPickerWrapper.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<div class="identity-picker">
|
||||
<img class="image" v-if="currentIdentity.avatar" :src="currentIdentity.avatar.url" :alt="currentIdentity.avatar.alt"/> {{ currentIdentity.name || `@${currentIdentity.preferredUsername}` }}
|
||||
<b-button type="is-text" @click="isComponentModalActive = true">
|
||||
{{ $t('Change') }}
|
||||
</b-button>
|
||||
<b-modal :active.sync="isComponentModalActive" has-modal-card>
|
||||
<identity-picker :currentIdentity="currentIdentity" @input="relay" />
|
||||
</b-modal>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||
import { IActor } from '@/types/actor';
|
||||
import IdentityPicker from './IdentityPicker.vue';
|
||||
|
||||
@Component({
|
||||
components: { IdentityPicker },
|
||||
})
|
||||
export default class IdentityPickerWrapper extends Vue {
|
||||
@Prop() value!: IActor;
|
||||
isComponentModalActive: boolean = false;
|
||||
currentIdentity: IActor = this.value;
|
||||
|
||||
relay(identity: IActor) {
|
||||
this.currentIdentity = identity;
|
||||
this.$emit('input', identity);
|
||||
this.isComponentModalActive = false;
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.identity-picker img.image {
|
||||
display: inline;
|
||||
height: 1.5em;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
</style>
|
||||
@@ -92,6 +92,7 @@ export default class Register extends Vue {
|
||||
domain: null,
|
||||
feedTokens: [],
|
||||
goingToEvents: [],
|
||||
participations: [],
|
||||
};
|
||||
errors: object = {};
|
||||
validationSent: boolean = false;
|
||||
|
||||
@@ -29,7 +29,7 @@ import {EventJoinOptions} from "@/types/event.model";
|
||||
<address-auto-complete v-model="event.physicalAddress" />
|
||||
|
||||
<b-field :label="$t('Organizer')">
|
||||
<identity-picker v-model="event.organizerActor"></identity-picker>
|
||||
<identity-picker-wrapper v-model="event.organizerActor"></identity-picker-wrapper>
|
||||
</b-field>
|
||||
|
||||
<div class="field">
|
||||
@@ -188,7 +188,6 @@ import {
|
||||
EventModel,
|
||||
EventStatus,
|
||||
EventVisibility,
|
||||
EventVisibilityJoinOptions,
|
||||
} from '@/types/event.model';
|
||||
import { CURRENT_ACTOR_CLIENT } from '@/graphql/actor';
|
||||
import { Person } from '@/types/actor';
|
||||
@@ -200,10 +199,10 @@ import { TAGS } from '@/graphql/tags';
|
||||
import { ITag } from '@/types/tag.model';
|
||||
import AddressAutoComplete from '@/components/Event/AddressAutoComplete.vue';
|
||||
import { buildFileFromIPicture, buildFileVariable } from '@/utils/image';
|
||||
import IdentityPicker from '@/views/Account/IdentityPicker.vue';
|
||||
import IdentityPickerWrapper from '@/views/Account/IdentityPickerWrapper.vue';
|
||||
|
||||
@Component({
|
||||
components: { AddressAutoComplete, TagInput, DateTimePicker, PictureUpload, Editor, IdentityPicker },
|
||||
components: { IdentityPickerWrapper, AddressAutoComplete, TagInput, DateTimePicker, PictureUpload, Editor },
|
||||
apollo: {
|
||||
currentActor: {
|
||||
query: CURRENT_ACTOR_CLIENT,
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import {ParticipantRole} from "@/types/event.model";
|
||||
import {ParticipantRole} from "@/types/event.model";
|
||||
import {ParticipantRole} from "@/types/event.model";
|
||||
<template>
|
||||
<div>
|
||||
<b-loading :active.sync="$apollo.loading"></b-loading>
|
||||
@@ -10,7 +13,7 @@
|
||||
<img src="https://picsum.photos/600/200/">
|
||||
</figure>
|
||||
</div>
|
||||
<section class="container">
|
||||
<section>
|
||||
<div class="title-and-participate-button">
|
||||
<div class="title-wrapper">
|
||||
<div class="date-component">
|
||||
@@ -18,21 +21,21 @@
|
||||
</div>
|
||||
<h1 class="title">{{ event.title }}</h1>
|
||||
</div>
|
||||
<span v-if="event.participantStats.approved > 0 && !actorIsParticipant()">
|
||||
{{ $tc('One person is going', event.participantStats.approved, {approved: event.participantStats.approved}) }}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ $tc('You and one other person are going to this event', event.participantStats.approved - 1, {approved: event.participantStats.approved - 1}) }}
|
||||
</span>
|
||||
<div v-if="!actorIsOrganizer()" class="participate-button has-text-centered">
|
||||
<a v-if="!actorIsParticipant()" @click="isJoinModalActive = true" class="button is-large is-primary is-rounded">
|
||||
<b-icon icon="circle-outline"></b-icon>
|
||||
{{ $t('Join') }}
|
||||
</a>
|
||||
<a v-if="actorIsParticipant()" @click="confirmLeave()" class="button is-large is-primary is-rounded">
|
||||
<b-icon icon="check-circle"></b-icon>
|
||||
{{ $t('Leave') }}
|
||||
</a>
|
||||
<div class="has-text-right">
|
||||
<small v-if="event.participantStats.approved > 0 && !actorIsParticipant">
|
||||
{{ $tc('One person is going', event.participantStats.approved, {approved: event.participantStats.approved}) }}
|
||||
</small>
|
||||
<small v-else>
|
||||
{{ $tc('You and one other person are going to this event', event.participantStats.approved - 1, {approved: event.participantStats.approved - 1}) }}
|
||||
</small>
|
||||
<participation-button
|
||||
v-if="currentActor.id && !actorIsOrganizer"
|
||||
:participation="participations[0]"
|
||||
:current-actor="currentActor"
|
||||
@joinEvent="joinEvent"
|
||||
@joinModal="isJoinModalActive = true"
|
||||
@confirmLeave="confirmLeave"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="metadata columns">
|
||||
@@ -60,8 +63,8 @@
|
||||
</p>
|
||||
</div>
|
||||
<div class="column sidebar">
|
||||
<div class="field has-addons">
|
||||
<p class="control" v-if="actorIsOrganizer()">
|
||||
<div class="field has-addons" v-if="currentActor.id">
|
||||
<p class="control" v-if="actorIsOrganizer">
|
||||
<router-link
|
||||
class="button"
|
||||
:to="{ name: 'EditEvent', params: {eventId: event.uuid}}"
|
||||
@@ -69,7 +72,7 @@
|
||||
{{ $t('Edit') }}
|
||||
</router-link>
|
||||
</p>
|
||||
<p class="control" v-if="actorIsOrganizer()">
|
||||
<p class="control" v-if="actorIsOrganizer">
|
||||
<a class="button is-danger" @click="openDeleteEventModalWrapper">
|
||||
{{ $t('Delete') }}
|
||||
</a>
|
||||
@@ -133,26 +136,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<section class="container">
|
||||
<h3 class="title">{{ $t('Participants') }}</h3>
|
||||
<router-link v-if="currentActor.id === event.organizerActor.id" :to="{ name: EventRouteName.PARTICIPATIONS, params: { eventId: event.uuid } }">
|
||||
{{ $t('Manage participants') }}
|
||||
</router-link>
|
||||
<span v-if="event.participants.length === 0">{{ $t('No participants yet.') }}</span>
|
||||
<div class="columns">
|
||||
<div
|
||||
class="column"
|
||||
v-for="participant in event.participants"
|
||||
:key="participant.id"
|
||||
>
|
||||
<figure class="image is-48x48">
|
||||
<img v-if="!participant.actor.avatar.url" src="https://picsum.photos/48/48/" class="is-rounded">
|
||||
<img v-else :src="participant.actor.avatar.url" class="is-rounded">
|
||||
</figure>
|
||||
<span>{{ participant.actor.preferredUsername }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="share">
|
||||
<div class="container">
|
||||
<div class="columns">
|
||||
@@ -188,19 +171,35 @@
|
||||
<report-modal :on-confirm="reportEvent" :title="$t('Report this event')" :outside-domain="event.organizerActor.domain" @close="$refs.reportModal.close()" />
|
||||
</b-modal>
|
||||
<b-modal :active.sync="isJoinModalActive" has-modal-card ref="participationModal">
|
||||
<participation-modal :on-confirm="joinEvent" :event="event" :defaultIdentity="currentActor" @close="$refs.participationModal.close()" />
|
||||
<identity-picker v-model="identity">
|
||||
<template v-slot:footer>
|
||||
<footer class="modal-card-foot">
|
||||
<button
|
||||
class="button"
|
||||
ref="cancelButton"
|
||||
@click="isJoinModalActive = false">
|
||||
{{ $t('Cancel') }}
|
||||
</button>
|
||||
<button
|
||||
class="button is-primary"
|
||||
ref="confirmButton"
|
||||
@click="joinEvent(identity)">
|
||||
{{ $t('Confirm my particpation') }}
|
||||
</button>
|
||||
</footer>
|
||||
</template>
|
||||
</identity-picker>
|
||||
</b-modal>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { DELETE_EVENT, FETCH_EVENT, JOIN_EVENT, LEAVE_EVENT } from '@/graphql/event';
|
||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||
import { EVENT_PERSON_PARTICIPATION, FETCH_EVENT, JOIN_EVENT, LEAVE_EVENT } from '@/graphql/event';
|
||||
import { Component, Prop } from 'vue-property-decorator';
|
||||
import { CURRENT_ACTOR_CLIENT } from '@/graphql/actor';
|
||||
import { EventVisibility, IEvent, IParticipant, ParticipantRole } from '@/types/event.model';
|
||||
import { IPerson } from '@/types/actor';
|
||||
import { RouteName } from '@/router';
|
||||
import { IPerson, Person } from '@/types/actor';
|
||||
import { GRAPHQL_API_ENDPOINT } from '@/api/_entrypoint';
|
||||
import DateCalendarIcon from '@/components/Event/DateCalendarIcon.vue';
|
||||
import BIcon from 'buefy/src/components/icon/Icon.vue';
|
||||
@@ -208,11 +207,11 @@ import EventCard from '@/components/Event/EventCard.vue';
|
||||
import EventFullDate from '@/components/Event/EventFullDate.vue';
|
||||
import ActorLink from '@/components/Account/ActorLink.vue';
|
||||
import ReportModal from '@/components/Report/ReportModal.vue';
|
||||
import ParticipationModal from '@/components/Event/ParticipationModal.vue';
|
||||
import { IReport } from '@/types/report.model';
|
||||
import { CREATE_REPORT } from '@/graphql/report';
|
||||
import EventMixin from '@/mixins/event';
|
||||
import { EventRouteName } from '@/router/event';
|
||||
import IdentityPicker from '@/views/Account/IdentityPicker.vue';
|
||||
import ParticipationButton from '@/components/Event/ParticipationButton.vue';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
@@ -222,7 +221,8 @@ import { EventRouteName } from '@/router/event';
|
||||
BIcon,
|
||||
DateCalendarIcon,
|
||||
ReportModal,
|
||||
ParticipationModal,
|
||||
IdentityPicker,
|
||||
ParticipationButton,
|
||||
// tslint:disable:space-in-parens
|
||||
'map-leaflet': () => import(/* webpackChunkName: "map" */ '@/components/Map.vue'),
|
||||
// tslint:enable
|
||||
@@ -233,13 +233,25 @@ import { EventRouteName } from '@/router/event';
|
||||
variables() {
|
||||
return {
|
||||
uuid: this.uuid,
|
||||
roles: [ParticipantRole.CREATOR, ParticipantRole.MODERATOR, ParticipantRole.MODERATOR, ParticipantRole.PARTICIPANT].join(),
|
||||
};
|
||||
},
|
||||
},
|
||||
currentActor: {
|
||||
query: CURRENT_ACTOR_CLIENT,
|
||||
},
|
||||
participations: {
|
||||
query: EVENT_PERSON_PARTICIPATION,
|
||||
variables() {
|
||||
return {
|
||||
eventId: this.event.id,
|
||||
name: this.currentActor.preferredUsername,
|
||||
};
|
||||
},
|
||||
update: (data) => {
|
||||
if (data && data.person) return data.person.participations;
|
||||
return [];
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
export default class Event extends EventMixin {
|
||||
@@ -247,13 +259,17 @@ export default class Event extends EventMixin {
|
||||
|
||||
event!: IEvent;
|
||||
currentActor!: IPerson;
|
||||
validationSent: boolean = false;
|
||||
identity: IPerson = new Person();
|
||||
participations: IParticipant[] = [];
|
||||
showMap: boolean = false;
|
||||
isReportModalActive: boolean = false;
|
||||
isJoinModalActive: boolean = false;
|
||||
|
||||
EventVisibility = EventVisibility;
|
||||
EventRouteName = EventRouteName;
|
||||
|
||||
mounted() {
|
||||
this.identity = this.currentActor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the event, then redirect to home.
|
||||
@@ -298,6 +314,24 @@ export default class Event extends EventMixin {
|
||||
},
|
||||
update: (store, { data }) => {
|
||||
if (data == null) return;
|
||||
|
||||
const participationCachedData = store.readQuery<{ person: IPerson }>({
|
||||
query: EVENT_PERSON_PARTICIPATION,
|
||||
variables: { eventId: this.event.id, name: identity.preferredUsername },
|
||||
});
|
||||
if (participationCachedData == null) return;
|
||||
const { person } = participationCachedData;
|
||||
if (person === null) {
|
||||
console.error('Cannot update participation cache, because of null value.');
|
||||
return;
|
||||
}
|
||||
person.participations.push(data.joinEvent);
|
||||
store.writeQuery({
|
||||
query: EVENT_PERSON_PARTICIPATION,
|
||||
variables: { eventId: this.event.id, name: identity.preferredUsername },
|
||||
data: { person },
|
||||
});
|
||||
|
||||
const cachedData = store.readQuery<{ event: IEvent }>({ query: FETCH_EVENT, variables: { uuid: this.event.uuid } });
|
||||
if (cachedData == null) return;
|
||||
const { event } = cachedData;
|
||||
@@ -306,9 +340,13 @@ export default class Event extends EventMixin {
|
||||
return;
|
||||
}
|
||||
|
||||
event.participants = event.participants.concat([data.joinEvent]);
|
||||
if (data.joinEvent.role === ParticipantRole.NOT_APPROVED) {
|
||||
event.participantStats.unapproved = event.participantStats.unapproved + 1;
|
||||
} else {
|
||||
event.participantStats.approved = event.participantStats.approved + 1;
|
||||
}
|
||||
|
||||
store.writeQuery({ query: FETCH_EVENT, data: { event } });
|
||||
store.writeQuery({ query: FETCH_EVENT, variables: { uuid: this.uuid }, data: { event } });
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -338,19 +376,38 @@ export default class Event extends EventMixin {
|
||||
},
|
||||
update: (store, { data }) => {
|
||||
if (data == null) return;
|
||||
const cachedData = store.readQuery<{ event: IEvent }>({ query: FETCH_EVENT, variables: { uuid: this.event.uuid } });
|
||||
if (cachedData == null) return;
|
||||
const { event } = cachedData;
|
||||
if (event === null) {
|
||||
console.error('Cannot update event participant cache, because of null value.');
|
||||
|
||||
const participationCachedData = store.readQuery<{ person: IPerson }>({
|
||||
query: EVENT_PERSON_PARTICIPATION,
|
||||
variables: { eventId: this.event.id, name: this.currentActor.preferredUsername },
|
||||
});
|
||||
if (participationCachedData == null) return;
|
||||
const { person } = participationCachedData;
|
||||
if (person === null) {
|
||||
console.error('Cannot update participation cache, because of null value.');
|
||||
return;
|
||||
}
|
||||
const participation = person.participations[0];
|
||||
person.participations = [];
|
||||
store.writeQuery({
|
||||
query: EVENT_PERSON_PARTICIPATION,
|
||||
variables: { eventId: this.event.id, name: this.currentActor.preferredUsername },
|
||||
data: { person },
|
||||
});
|
||||
|
||||
event.participants = event.participants
|
||||
.filter(p => p.actor.id !== data.leaveEvent.actor.id);
|
||||
event.participantStats.approved = event.participantStats.approved - 1;
|
||||
|
||||
store.writeQuery({ query: FETCH_EVENT, data: { event } });
|
||||
const eventCachedData = store.readQuery<{ event: IEvent }>({ query: FETCH_EVENT, variables: { uuid: this.event.uuid } });
|
||||
if (eventCachedData == null) return;
|
||||
const { event } = eventCachedData;
|
||||
if (event === null) {
|
||||
console.error('Cannot update event cache, because of null value.');
|
||||
return;
|
||||
}
|
||||
if (participation.role === ParticipantRole.NOT_APPROVED) {
|
||||
event.participantStats.unapproved = event.participantStats.unapproved - 1;
|
||||
} else {
|
||||
event.participantStats.approved = event.participantStats.approved - 1;
|
||||
}
|
||||
store.writeQuery({ query: FETCH_EVENT, variables: { uuid: this.uuid }, data: { event } });
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -369,17 +426,14 @@ export default class Event extends EventMixin {
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
|
||||
actorIsParticipant() {
|
||||
if (this.actorIsOrganizer()) return true;
|
||||
get actorIsParticipant() {
|
||||
if (this.actorIsOrganizer) return true;
|
||||
|
||||
return this.currentActor &&
|
||||
this.event.participants
|
||||
.some(participant => participant.actor.id === this.currentActor.id);
|
||||
return this.participations.length > 0 && this.participations[0].role === ParticipantRole.PARTICIPANT;
|
||||
}
|
||||
|
||||
actorIsOrganizer() {
|
||||
return this.currentActor && this.event.organizerActor &&
|
||||
this.currentActor.id === this.event.organizerActor.id;
|
||||
get actorIsOrganizer() {
|
||||
return this.participations.length > 0 && this.participations[0].role === ParticipantRole.CREATOR;
|
||||
}
|
||||
|
||||
get twitterShareUrl(): string {
|
||||
|
||||
@@ -68,6 +68,7 @@ import { IPerson } from '@/types/actor';
|
||||
page: 1,
|
||||
limit: 10,
|
||||
roles: [ParticipantRole.PARTICIPANT].join(),
|
||||
actorId: this.currentActor.id,
|
||||
};
|
||||
},
|
||||
},
|
||||
@@ -79,6 +80,7 @@ import { IPerson } from '@/types/actor';
|
||||
page: 1,
|
||||
limit: 20,
|
||||
roles: [ParticipantRole.CREATOR].join(),
|
||||
actorId: this.currentActor.id,
|
||||
};
|
||||
},
|
||||
update: data => data.event.participants.map(participation => new Participant(participation)),
|
||||
@@ -91,6 +93,7 @@ import { IPerson } from '@/types/actor';
|
||||
page: 1,
|
||||
limit: 20,
|
||||
roles: [ParticipantRole.NOT_APPROVED].join(),
|
||||
actorId: this.currentActor.id,
|
||||
};
|
||||
},
|
||||
update: data => data.event.participants.map(participation => new Participant(participation)),
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
<h3 class="title">
|
||||
{{ $t("Upcoming") }}
|
||||
</h3>
|
||||
<pre>{{ Array.from(goingToEvents.entries()) }}</pre>
|
||||
<b-loading :active.sync="$apollo.loading"></b-loading>
|
||||
<div v-for="row in goingToEvents" class="upcoming-events">
|
||||
<span class="date-component-container" v-if="isInLessThanSevenDays(row[0])">
|
||||
@@ -53,13 +52,12 @@
|
||||
{{ $tc('You have one event in {days} days.', row[1].length, {count: row[1].length, days: calculateDiffDays(row[0])}) }}
|
||||
</h3>
|
||||
</span>
|
||||
<div class="level">
|
||||
<div>
|
||||
<EventListCard
|
||||
v-for="participation in row[1]"
|
||||
v-if="isInLessThanSevenDays(row[0])"
|
||||
:key="participation[1].event.uuid"
|
||||
:participation="participation[1]"
|
||||
class="level-item"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -72,12 +70,11 @@
|
||||
{{ $t("Last week") }}
|
||||
</h3>
|
||||
<b-loading :active.sync="$apollo.loading"></b-loading>
|
||||
<div class="level">
|
||||
<div>
|
||||
<EventListCard
|
||||
v-for="participation in lastWeekEvents"
|
||||
:key="participation.id"
|
||||
:participation="participation"
|
||||
class="level-item"
|
||||
:options="{ hideDate: false }"
|
||||
/>
|
||||
</div>
|
||||
@@ -295,12 +292,6 @@ export default class Home extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
.upcoming-events {
|
||||
.level {
|
||||
margin-left: 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
section.container {
|
||||
margin: auto auto 3rem;
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ export default class Report extends Vue {
|
||||
|
||||
report.notes = report.notes.concat([note]);
|
||||
|
||||
store.writeQuery({ query: REPORT, data: { report } });
|
||||
store.writeQuery({ query: REPORT, variables: { id: this.report.id }, data: { report } });
|
||||
},
|
||||
});
|
||||
|
||||
@@ -235,7 +235,7 @@ export default class Report extends Vue {
|
||||
const updatedReport = data.updateReportStatus;
|
||||
report.status = updatedReport.status;
|
||||
|
||||
store.writeQuery({ query: REPORT, data: { report } });
|
||||
store.writeQuery({ query: REPORT, variables: { id: this.report.id }, data: { report } });
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user