Improve participation section and test

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2020-12-04 16:44:37 +01:00
parent 96938a5511
commit ee849e55c1
No known key found for this signature in database
GPG Key ID: A061B9DDE0CA0773
3 changed files with 134 additions and 12 deletions

View File

@ -24,16 +24,13 @@
> >
<small v-if="!actorIsParticipant && anonymousParticipation"> <small v-if="!actorIsParticipant && anonymousParticipation">
{{ $t("You are participating in this event anonymously") }} {{ $t("You are participating in this event anonymously") }}
<b-tooltip <b-tooltip :label="$t('Click for more information')">
:label=" <span
$t( class="is-clickable"
'This information is saved only on your computer. Click for details' @click="isAnonymousParticipationModalOpen = true"
) >
" <b-icon size="is-small" icon="information-outline" />
> </span>
<router-link :to="{ name: RouteName.TERMS }">
<b-icon size="is-small" icon="help-circle-outline" />
</router-link>
</b-tooltip> </b-tooltip>
</small> </small>
<small <small
@ -65,10 +62,62 @@
<b-icon icon="menu-down" /> <b-icon icon="menu-down" />
</button> </button>
</div> </div>
<b-modal
:active.sync="isAnonymousParticipationModalOpen"
has-modal-card
ref="anonymous-participation-modal"
>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">
{{ $t("About anonymous participation") }}
</p>
</header>
<section class="modal-card-body">
<b-notification
type="is-primary"
:closable="false"
v-if="event.joinOptions === EventJoinOptions.RESTRICTED"
>
{{
$t(
"As the event organiser has chosen to manually validate participation requests, your participation will be really confirmed only once you receive an email stating it's being accepted."
)
}}
</b-notification>
<p>
{{
$t(
"Your participation status is saved only on this device and will be deleted one month after the event's passed."
)
}}
</p>
<p v-if="isSecureContext">
{{
$t(
"You may clear all participation information for this device with the buttons below."
)
}}
</p>
<div class="buttons" v-if="isSecureContext">
<b-button
type="is-danger is-outlined"
@click="clearEventParticipationData"
>
{{ $t("Clear participation data for this event") }}
</b-button>
<b-button type="is-danger" @click="clearAllParticipationData">
{{ $t("Clear participation data for all events") }}
</b-button>
</div>
</section>
</div>
</b-modal>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { EventStatus, ParticipantRole } from "@/types/enums"; import { EventJoinOptions, EventStatus, ParticipantRole } from "@/types/enums";
import { IParticipant } from "@/types/participant.model"; import { IParticipant } from "@/types/participant.model";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Component, Prop, Vue } from "vue-property-decorator";
import RouteName from "@/router/name"; import RouteName from "@/router/name";
@ -77,6 +126,10 @@ import { CURRENT_ACTOR_CLIENT } from "@/graphql/actor";
import { IPerson } from "@/types/actor"; import { IPerson } from "@/types/actor";
import { IConfig } from "@/types/config.model"; import { IConfig } from "@/types/config.model";
import { CONFIG } from "@/graphql/config"; import { CONFIG } from "@/graphql/config";
import {
removeAllAnonymousParticipations,
removeAnonymousParticipation,
} from "@/services/AnonymousParticipationStorage";
import ParticipationButton from "../Event/ParticipationButton.vue"; import ParticipationButton from "../Event/ParticipationButton.vue";
@Component({ @Component({
@ -103,6 +156,10 @@ export default class ParticipationSection extends Vue {
RouteName = RouteName; RouteName = RouteName;
EventJoinOptions = EventJoinOptions;
isAnonymousParticipationModalOpen = false;
get actorIsParticipant(): boolean { get actorIsParticipant(): boolean {
if (this.actorIsOrganizer) return true; if (this.actorIsOrganizer) return true;
@ -163,5 +220,21 @@ export default class ParticipationSection extends Vue {
? this.event.endsOn ? this.event.endsOn
: this.event.beginsOn; : this.event.beginsOn;
} }
// eslint-disable-next-line class-methods-use-this
get isSecureContext(): boolean {
return window.isSecureContext;
}
async clearEventParticipationData(): Promise<void> {
await removeAnonymousParticipation(this.event.uuid);
window.location.reload();
}
// eslint-disable-next-line class-methods-use-this
clearAllParticipationData(): void {
removeAllAnonymousParticipations();
window.location.reload();
}
} }
</script> </script>

View File

@ -160,11 +160,16 @@ async function removeAnonymousParticipation(eventUUID: string): Promise<void> {
); );
} }
function removeAllAnonymousParticipations(): void {
localStorage.removeItem(ANONYMOUS_PARTICIPATIONS_LOCALSTORAGE_KEY);
}
export { export {
addLocalUnconfirmedAnonymousParticipation, addLocalUnconfirmedAnonymousParticipation,
confirmLocalAnonymousParticipation, confirmLocalAnonymousParticipation,
getLeaveTokenForParticipation, getLeaveTokenForParticipation,
isParticipatingInThisEvent, isParticipatingInThisEvent,
removeAnonymousParticipation, removeAnonymousParticipation,
removeAllAnonymousParticipations,
AnonymousParticipationNotFoundError, AnonymousParticipationNotFoundError,
}; };

View File

@ -3,7 +3,7 @@ import ParticipationSection from "@/components/Participation/ParticipationSectio
import Buefy from "buefy"; import Buefy from "buefy";
import VueRouter from "vue-router"; import VueRouter from "vue-router";
import { routes } from "@/router"; import { routes } from "@/router";
import { CommentModeration } from "@/types/enums"; import { CommentModeration, EventJoinOptions } from "@/types/enums";
import { import {
createMockClient, createMockClient,
MockApolloClient, MockApolloClient,
@ -112,6 +112,50 @@ describe("ParticipationSection", () => {
expect(cancelAnonymousParticipationButton.text()).toBe( expect(cancelAnonymousParticipationButton.text()).toBe(
"Cancel anonymous participation" "Cancel anonymous participation"
); );
wrapper.find(".event-participation small .is-clickable").trigger("click");
expect(
wrapper
.findComponent({ ref: "anonymous-participation-modal" })
.isVisible()
).toBeTruthy();
cancelAnonymousParticipationButton.trigger("click");
await wrapper.vm.$nextTick();
expect(wrapper.emitted("cancel-anonymous-participation")).toBeTruthy();
});
it("renders the participation section with existing confimed anonymous participation but event moderation", async () => {
generateWrapper(
{},
{
anonymousParticipation: true,
event: { ...eventData, joinOptions: EventJoinOptions.RESTRICTED },
}
);
expect(wrapper.find(".event-participation > small").text()).toContain(
"You are participating in this event anonymously"
);
const cancelAnonymousParticipationButton = wrapper.find(
".event-participation > button.button.is-text"
);
expect(cancelAnonymousParticipationButton.text()).toBe(
"Cancel anonymous participation"
);
wrapper.find(".event-participation small .is-clickable").trigger("click");
await wrapper.vm.$nextTick();
const modal = wrapper.findComponent({
ref: "anonymous-participation-modal",
});
expect(modal.isVisible()).toBeTruthy();
expect(modal.find("article.notification.is-primary").text()).toBe(
"As the event organiser has chosen to manually validate participation requests, your participation will be really confirmed only once you receive an email stating it's being accepted."
);
cancelAnonymousParticipationButton.trigger("click"); cancelAnonymousParticipationButton.trigger("click");
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
expect(wrapper.emitted("cancel-anonymous-participation")).toBeTruthy(); expect(wrapper.emitted("cancel-anonymous-participation")).toBeTruthy();