diff --git a/gui/src/containers/Applications/Overview/index.vue b/gui/src/containers/Applications/Overview/index.vue
index 97795f2..a124006 100644
--- a/gui/src/containers/Applications/Overview/index.vue
+++ b/gui/src/containers/Applications/Overview/index.vue
@@ -7,30 +7,30 @@
{{ application.title }}
+ application.status =='deployed' ? 'bg-success' :
+ application.status =='undeploying' ? 'bg-red-400' : ''"
+ v-if="application.status">
{{application.status}}
+ v-if="!application.status">
unknown
-
-
-
+
-
+
+
@@ -43,11 +43,11 @@
{{ application.latency || 0 }} MS
@@ -58,11 +58,11 @@
{{ application.reconfigurations || 0 }}
@@ -74,11 +74,11 @@
@@ -90,11 +90,11 @@
@@ -113,7 +113,7 @@
+
+const undeployApplication = (application: IApplication) => {
+ applicationStore.undeployApplication(application.uuid).then(() => {
+
+ application.status = "undeploying";
+ applicationStore.startPolling();
+
+ uiStore.setSnackbarMessage({
+ message: `You need to manually undeploy resources.`,
+ type: SNACKBAR_MESSAGE_TYPES.INFO
+ });
+ applicationStore.startPolling();
+
+ }).catch(() => {
+ uiStore.setSnackbarMessage({
+ message: `Failed to undeploy application ${application.title}`,
+ type: SNACKBAR_MESSAGE_TYPES.ERROR
+ });
+ });
+};
+
+onMounted(() => {
+ // Retrieve applications and then start polling
+ applicationStore.getAllApplications().then(() => {
+ applicationStore.startPolling();
+ });
+});
+
+onBeforeUnmount(() => {
+ applicationStore.stopPolling();
+});
+
+
\ No newline at end of file
diff --git a/gui/src/store/api-services/application.service.ts b/gui/src/store/api-services/application.service.ts
index e04e7d5..f9496f7 100644
--- a/gui/src/store/api-services/application.service.ts
+++ b/gui/src/store/api-services/application.service.ts
@@ -141,7 +141,11 @@ export default {
},
async duplicateApplication(uuid: string): Promise {
return axios.post(`/api/v1/application/${uuid}/uuid/duplicate`).then(({data}) => data)
- }
-
-
-}
+ },
+ async undeployApplication(uuid: string): Promise {
+ return axios.post(`/api/v1/application/${uuid}/uuid/undeploy`).then(({data}) => data)
+ },
+ async checkApplicationStatus(uuids: string[]): Promise> {
+ return axios.post("/api/v1/application/status", { uuids }).then(({ data }) => data)
+ },
+}
\ No newline at end of file
diff --git a/gui/src/store/modules/application.ts b/gui/src/store/modules/application.ts
index b401296..6d81715 100644
--- a/gui/src/store/modules/application.ts
+++ b/gui/src/store/modules/application.ts
@@ -1,14 +1,18 @@
import { defineStore } from "pinia"
import applicationService from "@/store/api-services/application.service.ts"
import { IApplication, IApplicationOverview } from "@/interfaces/application.interface.ts"
+import { useUIStore } from "@/store/modules/ui.ts"; // Import the UI store
+import { SNACKBAR_MESSAGE_TYPES } from "@/constants";
interface ApplicationState {
applications: IPagination
+ pollingTimerId?: number;
}
export const useApplicationStore = defineStore("application", {
state: (): ApplicationState => ({
- applications: { pages: 0, currentPage: 0, results: [] }
+ applications: { pages: 0, currentPage: 0, results: [] },
+ pollingTimerId: undefined,
}),
actions: {
async validateApplication(payload: Partial): Promise {
@@ -63,6 +67,87 @@ export const useApplicationStore = defineStore("application", {
const duplicatedApplication: IApplicationOverview = await applicationService.duplicateApplication(uuid)
this.applications.results.unshift(duplicatedApplication)
return duplicatedApplication
- }
- }
-})
+ },
+ async undeployApplication(uuid: string): Promise {
+ return applicationService.undeployApplication(uuid).then((status) => {
+ const app: any = this.applications.results.find((app) => app.uuid === uuid);
+ app.status = status.status;
+ return status.status;
+ });
+ },
+
+ async checkApplicationStatus(uuids: string[]): Promise {
+ console.log("Checking status for applications:", uuids);
+
+ const response = await applicationService.checkApplicationStatus(uuids);
+ console.log("Received status updates:", response);
+
+ response.forEach((updatedApp) => {
+ const appIndex = this.applications.results.findIndex((app) => app.uuid === updatedApp.uuid);
+ if (appIndex !== -1) {
+ const app = this.applications.results[appIndex];
+ const previousStatus = app.status;
+ app.status = updatedApp.status;
+
+ if (previousStatus !== "draft" && updatedApp.status === "draft") {
+ const uiStore = useUIStore();
+ uiStore.setSnackbarMessage({
+ message: `Application ${app.title} has been unlocked successfully`,
+ type: SNACKBAR_MESSAGE_TYPES.SUCCESS,
+ });
+ }
+
+ console.log(`Updated application ${updatedApp.uuid} to status ${updatedApp.status}`);
+ }
+ });
+ },
+
+ startPolling() {
+ console.log("Polling started...");
+
+ const batchSize = 100;
+ let interval = 10000; //10 sec
+ //const maxInterval = 60000;
+
+ const pollStatus = async () => {
+ const deployingApps = this.applications.results.filter(
+ (app) => app.status === "deploying" || app.status === "undeploying"
+ );
+
+ if (deployingApps.length === 0) {
+ console.log("No applications to poll for.");
+ return;
+ }
+
+ console.log(`Polling for ${deployingApps.length} deploying/undeploying applications.`);
+
+ for (let i = 0; i < deployingApps.length; i += batchSize) {
+ const batch = deployingApps.slice(i, i + batchSize);
+ await this.checkApplicationStatus(batch.map((app) => app.uuid));
+ }
+
+ const stillDeploying = this.applications.results.some(
+ (app) => app.status === "deploying" || app.status === "undeploying"
+ );
+
+ if (stillDeploying) {
+ console.log(`Some applications are still deploying. Polling again.`);
+ this.pollingTimerId = window.setTimeout(pollStatus, interval);
+ } else {
+ console.log("All applications have completed. Stopping polling.");
+ this.stopPolling();
+ }
+ };
+
+ pollStatus();
+ },
+
+ stopPolling() {
+ if (this.pollingTimerId) {
+ clearTimeout(this.pollingTimerId);
+ this.pollingTimerId = undefined;
+ console.log("Polling stopped.");
+ }
+ },
+ },
+});
\ No newline at end of file