From 6d8b26ff8e36bb9f7703a3ce49900e69bac47e12 Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Tue, 20 Oct 2026 13:21:58 +0800 Subject: [PATCH 1/8] functionality to call removeAmendments --- src/Frontend/src/assets/main.css | 3 -- .../src/stores/LicenseDetailsStore.ts | 30 ++++++++++++++++++- .../licenseDetails/LicenseDetails.vue | 29 ++++++++++++++---- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/Frontend/src/assets/main.css b/src/Frontend/src/assets/main.css index 8d749df20..35ec15b28 100644 --- a/src/Frontend/src/assets/main.css +++ b/src/Frontend/src/assets/main.css @@ -245,7 +245,6 @@ pre { } .btn-default { - padding: 8px 16px; color: #333; background-color: #fff; border-color: #ccc; @@ -266,7 +265,6 @@ pre { } .btn.btn-primary { - padding: 8px 16px; background-color: var(--sp-blue); border-color: #0686aa; color: #fff; @@ -416,7 +414,6 @@ span.metadata.metadata-link i.fa { .btn.btn-retry-dismiss { border-radius: 4px; - padding: 8px 16px; } .btn.btn-xs { diff --git a/src/Frontend/src/stores/LicenseDetailsStore.ts b/src/Frontend/src/stores/LicenseDetailsStore.ts index 561e5c055..bc58d6868 100644 --- a/src/Frontend/src/stores/LicenseDetailsStore.ts +++ b/src/Frontend/src/stores/LicenseDetailsStore.ts @@ -222,13 +222,32 @@ export const useLicenseDetailsStore = defineStore("LicenseDetailsStore", () => { useShowToast(TYPE.SUCCESS, "Saved", "", false, { timeout: 1000 }); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (err: any) { - useShowToast(TYPE.ERROR, "Error", "Failed to save changes to endpoint metadata."); + useShowToast(TYPE.ERROR, "Error", "Failed to save changes to endpoint metadata"); logger.error("Failed to save changes to endpoint metadata.", err); } finally { saving.value = false; } } + async function removeAmendments() { + saving.value = true; + try { + const response = await serviceControlClient.postToServiceControl("license/removeAmendments"); + if (!response.ok) { + const text = await response.text(); + throw new Error(`Remove Amendments Failed: ${response.status} ${response.statusText} - ${text}`); + } + await refresh(); + useShowToast(TYPE.SUCCESS, "Amendments Removed", "", false, { timeout: 1000 }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (err: any) { + useShowToast(TYPE.ERROR, "Error", "Failed to remove endpoint metadata amendments"); + logger.error("Failed to remove endpoint metadata amendments.", err); + } finally { + saving.value = false; + } + } + const compare = (q1: Queue, q2: Queue) => { const name1 = q1.details?.name; const name2 = q2.details?.name; @@ -252,6 +271,14 @@ export const useLicenseDetailsStore = defineStore("LicenseDetailsStore", () => { validId, hasLicenseDetails, hasChanges, + hasAmendments: computed( + () => + !hasChanges.value && + (endpoints.value.some((endpoint) => endpoint.queues.some((queue) => queue.originalLocation !== endpoint.clientId)) || + infrastructureQueues.value.some((queue) => queue.originalLocation !== "infrastructure") || + excludedQueues.value.some((queue) => queue.originalLocation !== "excluded") || + unassignedQueues.value.some((queue) => queue.originalLocation != null)) + ), saving, error, uploadEndpointMetadata, @@ -267,6 +294,7 @@ export const useLicenseDetailsStore = defineStore("LicenseDetailsStore", () => { reclassifyEndpoint, discardChanges, saveChanges, + removeAmendments, }; }); diff --git a/src/Frontend/src/views/throughputreport/licenseDetails/LicenseDetails.vue b/src/Frontend/src/views/throughputreport/licenseDetails/LicenseDetails.vue index 8393e6d7f..b0c49e6e0 100644 --- a/src/Frontend/src/views/throughputreport/licenseDetails/LicenseDetails.vue +++ b/src/Frontend/src/views/throughputreport/licenseDetails/LicenseDetails.vue @@ -3,7 +3,7 @@ import routeLinks from "@/router/routeLinks"; import isRouteSelected from "@/composables/isRouteSelected"; import { useLicenseDetailsStore } from "@/stores/LicenseDetailsStore"; import { storeToRefs } from "pinia"; -import { computed } from "vue"; +import { computed, ref } from "vue"; import DataView from "@/components/DataView.vue"; import ColumnHeader from "@/components/ColumnHeader.vue"; import ExclamationMark from "@/components/ExclamationMark.vue"; @@ -17,11 +17,14 @@ import DetailsItem from "@/components/DetailsItem.vue"; import ExternalLink from "@/components/ExternalLink.vue"; import { EndpointClassification } from "@/resources/LicenseDetails.ts"; import ActionButton from "@/components/ActionButton.vue"; +import ConfirmDialog from "@/components/ConfirmDialog.vue"; const isLicenseDetailsSupported = useIsLicenseDetailsSupported(); const licenseDetailsStore = useLicenseDetailsStore(); -const { endpoints, endpointSizes, serviceEndDate, validId, hasLicenseDetails, error, infrastructureQueues, excludedQueues, unassignedQueues, hasChanges, saving } = storeToRefs(licenseDetailsStore); +const { endpoints, endpointSizes, serviceEndDate, validId, hasLicenseDetails, error, infrastructureQueues, excludedQueues, unassignedQueues, hasChanges, hasAmendments, saving } = storeToRefs(licenseDetailsStore); + +const confirmReset = ref(false); const sizes = computed(() => endpoints.value @@ -43,6 +46,11 @@ const licensedCounts = computed(() => sizes.value.licensed); const currentCounts = computed(() => sizes.value.current); const allSizes = computed(() => [...new Set([...licensedCounts.value.keys(), ...currentCounts.value.keys()])].sort((a, b) => endpointSizes.value.findIndex((size) => size.name === a) - endpointSizes.value.findIndex((size) => size.name === b))); const estimateUrlParams = computed(() => [...currentCounts.value.entries().map(([endpointSize, count]) => `${endpointSize}=${count}`)].join("&")); + +async function removeAmendments() { + confirmReset.value = false; + await licenseDetailsStore.removeAmendments(); +}