Skip to content
Snippets Groups Projects
Verified Commit b2a4f374 authored by Daniel Göbel's avatar Daniel Göbel
Browse files

Add update resource modal

#88
parent a73d2ca1
No related branches found
No related tags found
1 merge request!85Resolve "Add UI for viewing and managing Resources"
...@@ -241,6 +241,7 @@ watch( ...@@ -241,6 +241,7 @@ watch(
modal-i-d="advancedUsageModal" modal-i-d="advancedUsageModal"
modal-label="Advanced Usage Modal" modal-label="Advanced Usage Modal"
v-if="store.authenticated" v-if="store.authenticated"
size-modifier="lg"
> >
<template v-slot:header> <template v-slot:header>
<h3>Advanced Usage</h3> <h3>Advanced Usage</h3>
......
...@@ -27,12 +27,15 @@ let refreshTimeout: NodeJS.Timeout | undefined = undefined; ...@@ -27,12 +27,15 @@ let refreshTimeout: NodeJS.Timeout | undefined = undefined;
const emit = defineEmits<{ const emit = defineEmits<{
(e: "click-info", resourceVersion: ResourceVersionOut): void; (e: "click-info", resourceVersion: ResourceVersionOut): void;
(e: "click-update", resource: ResourceOut): void;
}>(); }>();
const resourceVersionS3Ready = ref<Record<string, boolean>>({}); const resourceVersionS3Ready = ref<Record<string, boolean>>({});
const resourceVersions = computed<ResourceVersionOut[]>( const resourceVersions = computed<ResourceVersionOut[]>(() =>
() => props.resource.versions, [...props.resource.versions].sort((a, b) =>
a.created_at < b.created_at ? 1 : -1,
),
); );
function checkS3Resource(resourceVersion: ResourceVersionOut) { function checkS3Resource(resourceVersion: ResourceVersionOut) {
...@@ -92,6 +95,17 @@ onMounted(() => { ...@@ -92,6 +95,17 @@ onMounted(() => {
<div v-else> <div v-else>
<span>{{ props.resource.name }}</span> <span>{{ props.resource.name }}</span>
</div> </div>
<button
v-if="props.extended"
:disabled="props.loading"
class="btn btn-primary"
type="button"
data-bs-toggle="modal"
data-bs-target="#updateResourceModal"
@click="emit('click-update', props.resource)"
>
Update
</button>
</div> </div>
<p class="card-text"> <p class="card-text">
<span v-if="props.loading" class="placeholder-glow" <span v-if="props.loading" class="placeholder-glow"
......
<script setup lang="ts">
import { reactive, onMounted, ref } from "vue";
import BootstrapModal from "@/components/modals/BootstrapModal.vue";
import { Modal } from "bootstrap";
import { useResourceStore } from "@/stores/resources";
import type { ResourceVersionIn, ResourceOut } from "@/client/resource";
import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
import { Tooltip } from "bootstrap";
const resourceRepository = useResourceStore();
const resourceUpdateForm = ref<HTMLFormElement | undefined>(undefined);
const resourceUpdate = reactive<ResourceVersionIn>({
release: "",
});
const formState = reactive<{
validated: boolean;
loading: boolean;
}>({
validated: false,
loading: false,
});
const props = defineProps<{
modalId: string;
resource: ResourceOut;
}>();
let updateResourceModal: Modal | null = null;
function updateResource() {
formState.validated = true;
resourceUpdate.release = resourceUpdate.release.trim();
if (resourceUpdateForm.value?.checkValidity()) {
formState.loading = true;
resourceRepository
.updateResource(props.resource.resource_id, resourceUpdate)
.then(() => {
updateResourceModal?.hide();
resourceUpdate.release = "";
formState.validated = false;
})
.finally(() => {
formState.loading = false;
});
}
}
function modalClosed() {
formState.validated = false;
}
onMounted(() => {
updateResourceModal = new Modal("#" + props.modalId);
new Tooltip("#tooltip-update-resource-release");
});
</script>
<template>
<bootstrap-modal
:modalID="modalId"
static-backdrop
modal-label="Update Resource Modal"
v-on="{ 'hidden.bs.modal': modalClosed }"
>
<template #header>
Update Resource <b>{{ props.resource.name }}</b></template
>
<template #body>
<form
id="resourceUpdateForm"
:class="{ 'was-validated': formState.validated }"
ref="resourceUpdateForm"
>
<div class="mb-3">
<label for="resourceUpdateReleaseInput" class="form-label">
Release
</label>
<div class="input-group">
<div class="input-group-text">
<font-awesome-icon icon="fa-solid fa-tag" />
</div>
<input
class="form-control"
id="resourceUpdateReleaseInput"
required
minlength="3"
maxlength="32"
v-model="resourceUpdate.release"
placeholder="Next release name"
/>
<div
class="input-group-text hover-info"
id="tooltip-update-resource-release"
data-bs-toggle="tooltip"
data-bs-title="The name of the next resource version"
>
<font-awesome-icon icon="fa-solid fa-circle-question" />
</div>
</div>
</div>
</form>
</template>
<template v-slot:footer>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
Close
</button>
<button
type="submit"
form="resourceUpdateForm"
class="btn btn-primary"
:disabled="formState.loading || !props.resource.resource_id"
@click.prevent="updateResource"
>
<span
v-if="formState.loading"
class="spinner-border spinner-border-sm"
role="status"
aria-hidden="true"
></span>
Save
</button>
</template>
</bootstrap-modal>
</template>
<style scoped></style>
...@@ -2,6 +2,7 @@ import { defineStore } from "pinia"; ...@@ -2,6 +2,7 @@ import { defineStore } from "pinia";
import type { import type {
ResourceIn, ResourceIn,
ResourceOut, ResourceOut,
ResourceVersionIn,
ResourceVersionOut, ResourceVersionOut,
} from "@/client/resource"; } from "@/client/resource";
import { ResourceService, ResourceVersionService } from "@/client/resource"; import { ResourceService, ResourceVersionService } from "@/client/resource";
...@@ -96,6 +97,7 @@ export const useResourceStore = defineStore({ ...@@ -96,6 +97,7 @@ export const useResourceStore = defineStore({
undefined undefined
) { ) {
this.fetchOwnResource(resourceVersion.resource_id); this.fetchOwnResource(resourceVersion.resource_id);
return changedResourceVersion;
} }
const versionIndex = this.ownResourceMapping[ const versionIndex = this.ownResourceMapping[
changedResourceVersion.resource_id changedResourceVersion.resource_id
...@@ -116,5 +118,23 @@ export const useResourceStore = defineStore({ ...@@ -116,5 +118,23 @@ export const useResourceStore = defineStore({
return changedResourceVersion; return changedResourceVersion;
}); });
}, },
updateResource(
resource_id: string,
version: ResourceVersionIn,
): Promise<ResourceVersionOut> {
return ResourceVersionService.resourceVersionRequestResourceVersion(
resource_id,
version,
).then((versionOut) => {
if (this.ownResourceMapping[versionOut.resource_id] == undefined) {
this.fetchOwnResource(versionOut.resource_id);
return versionOut;
}
this.ownResourceMapping[versionOut.resource_id].versions.push(
versionOut,
);
return versionOut;
});
},
}, },
}); });
...@@ -3,11 +3,12 @@ import { onMounted, reactive } from "vue"; ...@@ -3,11 +3,12 @@ import { onMounted, reactive } from "vue";
import { useResourceStore } from "@/stores/resources"; import { useResourceStore } from "@/stores/resources";
import CardTransitionGroup from "@/components/transitions/CardTransitionGroup.vue"; import CardTransitionGroup from "@/components/transitions/CardTransitionGroup.vue";
import ResourceCard from "@/components/resources/ResourceCard.vue"; import ResourceCard from "@/components/resources/ResourceCard.vue";
import CreateResourceModal from "@/components/resources/CreateResourceModal.vue"; import CreateResourceModal from "@/components/resources/modals/CreateResourceModal.vue";
import UploadResourceInfoModal from "@/components/resources/UploadResourceInfoModal.vue"; import UploadResourceInfoModal from "@/components/resources/modals/UploadResourceInfoModal.vue";
import { useS3KeyStore } from "@/stores/s3keys"; import { useS3KeyStore } from "@/stores/s3keys";
import type { ResourceVersionOut } from "@/client/resource"; import type { ResourceVersionOut, ResourceOut } from "@/client/resource";
import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
import UpdateResourceModal from "@/components/resources/modals/UpdateResourceModal.vue";
const resourceRepository = useResourceStore(); const resourceRepository = useResourceStore();
const s3KeyRepository = useS3KeyStore(); const s3KeyRepository = useS3KeyStore();
...@@ -15,15 +16,28 @@ const s3KeyRepository = useS3KeyStore(); ...@@ -15,15 +16,28 @@ const s3KeyRepository = useS3KeyStore();
const resourceState = reactive<{ const resourceState = reactive<{
loading: boolean; loading: boolean;
resourceVersionInfo?: ResourceVersionOut; resourceVersionInfo?: ResourceVersionOut;
updateResource: ResourceOut;
}>({ }>({
loading: true, loading: true,
resourceVersionInfo: undefined, resourceVersionInfo: undefined,
updateResource: {
name: "",
description: "",
source: "",
resource_id: "",
versions: [],
maintainer_id: "",
},
}); });
function setResourceVersionInfo(resourceVersionInfo?: ResourceVersionOut) { function setResourceVersionInfo(resourceVersionInfo?: ResourceVersionOut) {
resourceState.resourceVersionInfo = resourceVersionInfo; resourceState.resourceVersionInfo = resourceVersionInfo;
} }
function setResourceUpdate(resource: ResourceOut) {
resourceState.updateResource = resource;
}
onMounted(() => { onMounted(() => {
let fetchedResources = false; let fetchedResources = false;
s3KeyRepository.fetchS3Keys(() => { s3KeyRepository.fetchS3Keys(() => {
...@@ -43,6 +57,10 @@ onMounted(() => { ...@@ -43,6 +57,10 @@ onMounted(() => {
modal-id="uploadResourceInfoModal" modal-id="uploadResourceInfoModal"
:resource-version="resourceState.resourceVersionInfo" :resource-version="resourceState.resourceVersionInfo"
/> />
<update-resource-modal
:resource="resourceState.updateResource"
modal-id="updateResourceModal"
/>
<div <div
class="row m-2 border-bottom mb-4 justify-content-between align-items-center pb-2" class="row m-2 border-bottom mb-4 justify-content-between align-items-center pb-2"
> >
...@@ -90,6 +108,7 @@ onMounted(() => { ...@@ -90,6 +108,7 @@ onMounted(() => {
style="width: 48%" style="width: 48%"
extended extended
@click-info="setResourceVersionInfo" @click-info="setResourceVersionInfo"
@click-update="setResourceUpdate"
/> />
</CardTransitionGroup> </CardTransitionGroup>
</div> </div>
...@@ -110,6 +129,7 @@ onMounted(() => { ...@@ -110,6 +129,7 @@ onMounted(() => {
}" }"
style="min-width: 48%" style="min-width: 48%"
loading loading
extended
/> />
</div> </div>
</template> </template>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment