From 23e852f9d943326b7fe379387cfb4b09026f5c7f Mon Sep 17 00:00:00 2001 From: David Ludwig Date: Mon, 10 May 2021 21:06:04 +0000 Subject: [PATCH] Implement movie request canceling in web UI --- .../src/app/components/modals/MovieModal.vue | 47 +++++++++++++++---- services/webui/src/app/store/actions.ts | 25 +++++++--- services/webui/src/app/store/getters.ts | 7 +++ 3 files changed, 63 insertions(+), 16 deletions(-) diff --git a/services/webui/src/app/components/modals/MovieModal.vue b/services/webui/src/app/components/modals/MovieModal.vue index 37c3816..1022687 100644 --- a/services/webui/src/app/components/modals/MovieModal.vue +++ b/services/webui/src/app/components/modals/MovieModal.vue @@ -26,10 +26,14 @@ @@ -43,10 +47,14 @@
Watch Now - + + :disabled="isRequesting" @click="request">{{isRequesting ? "Processing..." : "Request"}}
@@ -62,12 +70,14 @@ import { defineComponent } from "vue"; import { getAverageRgb } from "../../util"; import { useStore, Mutation, Action } from "../../store"; import MoviePoster from "../MoviePoster.vue"; +import { mapGetters } from "vuex"; export default defineComponent({ components: { MoviePoster }, computed: { + ...mapGetters(["userId"]), backdropOverlayStyle(): string { let { r, g, b } = this.rgb; return `background-image: linear-gradient(to right, rgba(${r}, ${g}, ${b}, 1.0), rgba(${r}, ${g}, ${b}, 0.84)`; @@ -166,18 +176,37 @@ export default defineComponent({ } this.movie = response.result; }, + async cancel() { + if (this.isRequesting || this.movie == null || this.movie.ticketId == null || this.movie.requestedBy?.id != this.userId) { + return; + } + this.isRequesting = true; + let [status, response] = await this.$store.dispatch(Action.CancelMovieRequest, this.movie.ticketId); + this.isRequesting = false; + if (status != Status.Ok) { + console.error("Failed to cancel movie request"); + return; + } + this.movie.ticketId = null; + this.movie.requestedBy = null; + }, async request() { if (this.isRequesting || this.movie == null || this.movie.tmdbId == null) { return; } this.isRequesting = true; - let [status, response] = await this.$store.dispatch(Action.RequestMovie, this.movie.tmdbId); + let [status, response] = await this.$store.dispatch(Action.CreateMovieRequest, this.movie.tmdbId); this.isRequesting = false; if (status == Status.Forbidden) { - console.log("Failed to add movie: quota has been met"); + console.error("Failed to add movie: quota has been met"); return; } this.movie.ticketId = response.result.ticketId; + this.movie.requestedBy = { + id : this.$store.state.user!.id, + isAdmin: this.$store.state.user!.isAdmin, + name : this.$store.state.user!.name, + } } }, mounted() { @@ -194,7 +223,7 @@ export default defineComponent({ } }, watch: { - tmdbId(newId: number|string|undefined, oldId: number|string|undefined) { + tmdbId() { this.fetchMovieDetails(); } } diff --git a/services/webui/src/app/store/actions.ts b/services/webui/src/app/store/actions.ts index b8fe847..138e37d 100644 --- a/services/webui/src/app/store/actions.ts +++ b/services/webui/src/app/store/actions.ts @@ -35,7 +35,8 @@ export enum Action { // Movies Methods ActiveMovieRequests = "ACTIVE_MOVIE_REQUESTS", MovieDetails = "MOVIE_DETAILS", - RequestMovie = "REQUEST_MOVIE", + CancelMovieRequest = "CANCEL_MOVIE_REQUEST", + CreateMovieRequest = "CREATE_MOVIE_REQUEST", SearchMovies = "SEARCH_MOVIES" } @@ -60,7 +61,8 @@ export type ActionsTypes = { [Action.ActiveMovieRequests]: () => Promise<[number, IApiDataResponse]>, [Action.MovieDetails] : (tmdbId: number | string) => Promise<[number, IApiDataResponse]>, [Action.SearchMovies] : (query: string) => Promise<[number, IPaginatedResponse]>, - [Action.RequestMovie] : (tmdbId: number | string) => Promise<[number, IApiDataResponse<{ ticketId: number }>]> + [Action.CancelMovieRequest] : (ticketId: number) => Promise<[number, IApiResponse]>, + [Action.CreateMovieRequest] : (tmdbId: number | string) => Promise<[number, IApiDataResponse<{ ticketId: number }>]> } /** @@ -232,7 +234,7 @@ export const actions: Actions = { return state.user?.token ?? null; }, + /** + * Retrieve the user's ID + */ + userId(state: IState) { + return state.user?.id; + }, + /** * Get the user's name (assumes authenticated) */