diff --git a/gui/src/components/Application/Resources.vue b/gui/src/components/Application/Resources.vue index 26f6b46..4077654 100644 --- a/gui/src/components/Application/Resources.vue +++ b/gui/src/components/Application/Resources.vue @@ -54,18 +54,21 @@ const props = withDefaults(defineProps(), { const resources = computed>(() => - resourceStore.resources.results.map((resource) => { - // prettier-ignore - const isEnabled = props.payload.appResources + resourceStore.resources.results.map((resource) => { + const regions = Array.isArray(resource.regions) + ? resource.regions.map((region) => region.region).join(', ') + : resource.regions; + + const isEnabled = props.payload.appResources .find((appResource: IAppResource) => appResource.uuid === resource.uuid)?.enabled ?? false - return { - uuid: resource.uuid, - title: resource.title, - platform: resource.platform.title, - regions: resource.regions, - enabled: isEnabled + return { + uuid: resource.uuid, + title: resource.title, + platform: resource.platform.title, + regions: regions, + enabled: isEnabled } - }) + }) ) const retrieveAllResources = async () => { diff --git a/gui/src/components/Modal/DuplicationConfirmation.vue b/gui/src/components/Modal/DuplicationConfirmation.vue new file mode 100644 index 0000000..4c02f5b --- /dev/null +++ b/gui/src/components/Modal/DuplicationConfirmation.vue @@ -0,0 +1,52 @@ + + + diff --git a/gui/src/components/Modal/ResourceCreation.vue b/gui/src/components/Modal/ResourceCreation.vue index 280c490..11c6a6f 100644 --- a/gui/src/components/Modal/ResourceCreation.vue +++ b/gui/src/components/Modal/ResourceCreation.vue @@ -24,6 +24,7 @@ import {SNACKBAR_MESSAGE_TYPES} from "@/constants" import {IResourcePayload} from "@/types/resource.ts" import ResourceForm from "@/components/Modal/ResourceForm.vue"; import {IPlatform} from "@/interfaces/platform.interface.ts"; +import { IRegion } from "@/interfaces/resources.interface.ts" const resourceStore = useResourceStore() const uiStore = useUIStore() @@ -67,24 +68,30 @@ const closeModal = (skipConfirmation: boolean = false) => { const createResource = async () => { - if (!(await v$.value.$validate())){ - console.log("Failed validation") - return + // Map regions from objects to string (comma-separated region identifiers) + if (Array.isArray(resourceData.regions)) { + resourceData.regions = resourceData.regions.map((region: IRegion) => region.region).join(','); + } + + if (!(await v$.value.$validate())) { + console.log("Failed validation"); + return; } resourceStore - .createResource(resourceData) - .then((createdResource) => { - closeModal(true) - uiStore.setSnackbarMessage({ - message: `Successfully created resource ${createdResource.title}`, - type: SNACKBAR_MESSAGE_TYPES.SUCCESS + .createResource(resourceData) + .then((createdResource) => { + closeModal(true); + uiStore.setSnackbarMessage({ + message: `Successfully created resource ${createdResource.title}`, + type: SNACKBAR_MESSAGE_TYPES.SUCCESS + }); }) - }) - .catch((error) => { - const errors = extractExternalResults(error) - Object.assign($externalResults, errors) - }) -} + .catch((error) => { + const errors = extractExternalResults(error); + Object.assign($externalResults, errors); + }); +}; + diff --git a/gui/src/components/Modal/ResourceEditing.vue b/gui/src/components/Modal/ResourceEditing.vue index f129963..524a25b 100644 --- a/gui/src/components/Modal/ResourceEditing.vue +++ b/gui/src/components/Modal/ResourceEditing.vue @@ -10,7 +10,7 @@ + \ No newline at end of file diff --git a/gui/src/components/Modal/index.vue b/gui/src/components/Modal/index.vue index 3a302f1..ee92863 100644 --- a/gui/src/components/Modal/index.vue +++ b/gui/src/components/Modal/index.vue @@ -5,9 +5,16 @@ @@ -26,6 +33,7 @@ import UserEditing from "@/components/Modal/UserEditing.vue" import ResourceCreation from "@/components/Modal/ResourceCreation.vue" import ResourceEditing from "@/components/Modal/ResourceEditing.vue" import DeleteConfirmation from "@/components/Modal/DeleteConfirmation.vue" +import DuplicationConfirmation from "@/components/Modal/DuplicationConfirmation.vue" import ExitConfirmation from "@/components/Modal/ExitConfirmation.vue" import Snackbar from "@/components/Snackbar" @@ -38,6 +46,7 @@ const components: Record = { [MODAL_WINDOW_NAMES.RESOURCE_CREATION]: ResourceCreation, [MODAL_WINDOW_NAMES.RESOURCE_EDITING]: ResourceEditing, [MODAL_WINDOW_NAMES.CONFIRM_DELETING_MODAL]: DeleteConfirmation, + [MODAL_WINDOW_NAMES.CONFIRM_DUPLICATION_MODAL]: DuplicationConfirmation, [MODAL_WINDOW_NAMES.EXIT_MESSAGE_MODAL]: ExitConfirmation } diff --git a/gui/src/constants/modalWindowNames.ts b/gui/src/constants/modalWindowNames.ts index 79d85a5..2432027 100644 --- a/gui/src/constants/modalWindowNames.ts +++ b/gui/src/constants/modalWindowNames.ts @@ -4,5 +4,6 @@ export default { RESOURCE_EDITING: "resourceEditing", USER_EDITING: "userEditing", CONFIRM_DELETING_MODAL: "confirmDeletingModal", + CONFIRM_DUPLICATION_MODAL: "confirmDuplicationModal", EXIT_MESSAGE_MODAL: "exitMessageModal" } diff --git a/gui/src/containers/Applications/Overview/index.vue b/gui/src/containers/Applications/Overview/index.vue index 25a4934..97795f2 100644 --- a/gui/src/containers/Applications/Overview/index.vue +++ b/gui/src/containers/Applications/Overview/index.vue @@ -30,6 +30,7 @@ + @@ -171,5 +172,27 @@ const deployApplication = (application: IApplication) =>{ applicationStore.deployApplication(application.uuid) +} +const duplicateApplication = (application: IApplication) => { + uiStore.setModalWindowState({ + name: MODAL_WINDOW_NAMES.CONFIRM_DUPLICATION_MODAL, + payload: { + confirmAction: () => { + applicationStore.duplicateApplication(application.uuid).then((newApp: IApplicationOverview) => { + const newAppUuid = newApp.uuid; + uiStore.setSnackbarMessage({ + message: "Successfully duplicated application", + type: SNACKBAR_MESSAGE_TYPES.SUCCESS + }) + }).catch(() => { + uiStore.setSnackbarMessage({ + message: "Failed to duplicate application", + type: SNACKBAR_MESSAGE_TYPES.ERROR + }) + }) + }, + cancelAction: () => {} + } + }) } diff --git a/gui/src/containers/Users/index.vue b/gui/src/containers/Users/index.vue index 9916b3b..e926d5d 100644 --- a/gui/src/containers/Users/index.vue +++ b/gui/src/containers/Users/index.vue @@ -2,7 +2,8 @@

Users

- + +
@@ -80,9 +81,20 @@ import { usePagination } from "@/composables/usePagination.ts" const userStore = useUserStore() const uiStore = useUIStore() - +const isAdmin = ref(false) const users = computed>(() => userStore.users) +// const retrieveMe = async () => { +// const currentUser = await userStore.retrieveUserInfo() +// console.log("Current User:", currentUser) +// +// isAdmin.value = currentUser?.role === 'admin' +// console.log("Is Admin:", isAdmin.value) +// } +// +// retrieveMe() + +// Pagination settings const currentPage = ref(1) const rowsPerPage = ref(10) diff --git a/gui/src/interfaces/resources.interface.ts b/gui/src/interfaces/resources.interface.ts index ed34cf1..2ef1260 100644 --- a/gui/src/interfaces/resources.interface.ts +++ b/gui/src/interfaces/resources.interface.ts @@ -18,7 +18,7 @@ export interface ICredentials{ export interface IResource { uuid: string title: string - regions: string + regions: string | Array securityGroup: string subnet: string endpoint: string diff --git a/gui/src/store/api-services/application.service.ts b/gui/src/store/api-services/application.service.ts index 351f57e..e04e7d5 100644 --- a/gui/src/store/api-services/application.service.ts +++ b/gui/src/store/api-services/application.service.ts @@ -138,6 +138,9 @@ export default { async publishPolicies(policies:string): Promise { console.log("Publishing policies" , policies) return axios.post(`/api/v1/policies/publish`,{policies:policies}).then(({data}) => data) + }, + async duplicateApplication(uuid: string): Promise { + return axios.post(`/api/v1/application/${uuid}/uuid/duplicate`).then(({data}) => data) } diff --git a/gui/src/store/api-services/user.service.ts b/gui/src/store/api-services/user.service.ts index 9f81d71..d5c8b82 100644 --- a/gui/src/store/api-services/user.service.ts +++ b/gui/src/store/api-services/user.service.ts @@ -7,7 +7,7 @@ export default { return axios.post("/api/v1/@apostrophecms/login/login", payload).then(({ data }) => data) }, async getUserProfileData(): Promise { - return axios.get("/api/v1/userapi/me").then(({ data }) => data) + return axios.get("/api/v1/@apostrophecms/settings").then(({ data }) => data) }, async editUserProfileData(payload: Omit): Promise { return axios.patch("/api/v1/userapi/profile-update", payload).then(({ data }) => data) diff --git a/gui/src/store/modules/application.ts b/gui/src/store/modules/application.ts index 0f30041..b401296 100644 --- a/gui/src/store/modules/application.ts +++ b/gui/src/store/modules/application.ts @@ -58,6 +58,11 @@ export const useApplicationStore = defineStore("application", { }, async invokeYamlComponents(content: string): Promise> { return await applicationService.getYamlComponents({ content }) + }, + async duplicateApplication(uuid: string): Promise { + const duplicatedApplication: IApplicationOverview = await applicationService.duplicateApplication(uuid) + this.applications.results.unshift(duplicatedApplication) + return duplicatedApplication } } })