From 953917626a9ee4112d544c0bda26326004071f77 Mon Sep 17 00:00:00 2001 From: Carson McManus Date: Tue, 30 Apr 2024 08:15:42 -0400 Subject: [PATCH] client: only submit changed settings to the server when changing settings --- client/src/components/RoomSettingsForm.vue | 48 +++++++++++++++------ tests/e2e/integration/room-settings.spec.ts | 5 +-- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/client/src/components/RoomSettingsForm.vue b/client/src/components/RoomSettingsForm.vue index e7784d309..1215f992e 100644 --- a/client/src/components/RoomSettingsForm.vue +++ b/client/src/components/RoomSettingsForm.vue @@ -3,14 +3,14 @@
@@ -138,6 +138,7 @@ @click="submitRoomSettings" role="submit" :loading="isLoadingRoomSettings" + :disabled="dirtySettings.length === 0" data-cy="save" > {{ $t("common.save") }} @@ -155,13 +156,14 @@ import { API } from "@/common-http"; import { Visibility, QueueMode, RoomSettings, Role, BehaviorOption } from "ott-common/models/types"; import { Grants } from "ott-common/permissions"; import toast from "@/util/toast"; -import { onMounted, Ref, ref } from "vue"; +import { Ref, onMounted, reactive, ref, toRefs } from "vue"; import { useStore } from "@/store"; import { useI18n } from "vue-i18n"; import { OttApiResponseGetRoom } from "ott-common/models/rest-api"; import { ALL_SKIP_CATEGORIES } from "ott-common/constants"; import { useGrants } from "./composables/grants"; import { useRoute } from "vue-router"; +import { watch } from "vue"; const store = useStore(); const { t } = useI18n(); @@ -169,7 +171,7 @@ const granted = useGrants(); const route = useRoute(); const isLoadingRoomSettings = ref(false); -const inputRoomSettings = ref({ +const inputRoomSettings = reactive({ title: "", description: "", visibility: Visibility.Public, @@ -178,7 +180,17 @@ const inputRoomSettings = ref({ autoSkipSegmentCategories: Array.from([]), restoreQueueBehavior: BehaviorOption.Prompt, enableVoteSkip: false, -}) as Ref; +}); + +const settings = toRefs(inputRoomSettings); +const dirtySettings: Ref<(keyof RoomSettings)[]> = ref([]); +for (const key of Object.keys(inputRoomSettings) as (keyof RoomSettings)[]) { + watch(settings[key], () => { + if (!dirtySettings.value.includes(key)) { + dirtySettings.value.push(key); + } + }); +} onMounted(async () => { await loadRoomSettings(); @@ -198,8 +210,12 @@ async function loadRoomSettings() { const res = await API.get( `/room/${route.params.roomId ?? store.state.room.name}` ); - inputRoomSettings.value = intoSettings(res.data); + Object.assign(inputRoomSettings, intoSettings(res.data)); + setTimeout(() => { + dirtySettings.value = []; + }, 0); } catch (err) { + console.error(err); toast.add({ content: t("room-settings.load-failed"), duration: 5000, @@ -221,11 +237,14 @@ function getRoomSettingsSubmit(): Partial { }; const blocked: (keyof RoomSettings)[] = []; for (const prop of Object.keys(propsToGrants)) { - if (!granted(`configure-room.${propsToGrants[prop]}`)) { + if ( + !dirtySettings.value.includes(prop as keyof typeof propsToGrants) || + !granted(`configure-room.${propsToGrants[prop]}`) + ) { blocked.push(prop as keyof typeof propsToGrants); } } - return _.omit(inputRoomSettings.value, blocked); + return _.omit(inputRoomSettings, blocked); } /** Take room settings from the UI and submit them to the server. */ @@ -241,6 +260,7 @@ async function submitRoomSettings() { content: t("room-settings.settings-applied").toString(), duration: 4000, }); + dirtySettings.value = []; } catch (e) { console.log(e); toast.add({ diff --git a/tests/e2e/integration/room-settings.spec.ts b/tests/e2e/integration/room-settings.spec.ts index 227480697..3c31f4946 100644 --- a/tests/e2e/integration/room-settings.spec.ts +++ b/tests/e2e/integration/room-settings.spec.ts @@ -44,8 +44,7 @@ describe("Room settings", () => { .should("exist") .scrollIntoView() .should("be.visible") - .should("not.be.disabled") - .should("not.have.css", "pointer-events", "none"); + .should("be.disabled"); }); it("should apply title", () => { @@ -71,7 +70,7 @@ describe("Room settings", () => { it("should apply visibility", () => { cy.get("[data-cy=select-visibility]").click(); - cy.contains("Unlisted").click(); + cy.contains("Public").click(); cy.contains("button", "Save") .should("exist") .should("be.visible")