-
Daniel Göbel authored
#88
Daniel Göbel authored#88
ReviewResourceView.vue 4.81 KiB
<script setup lang="ts">
import { useResourceStore } from "@/stores/resources";
import { computed, onMounted, reactive } from "vue";
import { type ResourceVersionOut, Status } from "@/client/resource";
import CopyToClipboardIcon from "@/components/CopyToClipboardIcon.vue";
import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
import { Tooltip } from "bootstrap";
const resourceRepository = useResourceStore();
let refreshTimeout: NodeJS.Timeout | undefined = undefined;
const resourceState = reactive<{
sendingRequest: boolean;
loading: boolean;
}>({
sendingRequest: false,
loading: true,
});
const countItems = computed<number>(() =>
resourceRepository.reviewableResources.reduce(
(previousValue, currentValue) =>
previousValue + currentValue.versions.length,
0,
),
);
function fetchResources() {
resourceRepository.fetchReviewableResources().finally(() => {
resourceState.loading = false;
});
}
function clickRefreshResources() {
clearTimeout(refreshTimeout);
refreshTimeout = setTimeout(() => {
fetchResources();
}, 500);
}
function syncResource(resourceVersion: ResourceVersionOut) {
resourceState.sendingRequest = true;
resourceRepository.syncResource(resourceVersion).finally(() => {
resourceState.sendingRequest = false;
});
}
onMounted(() => {
fetchResources();
new Tooltip("#refreshReviewableResourcesButton");
});
</script>
<template>
<div
class="row m-2 border-bottom mb-4 justify-content-between align-items-center"
>
<h2 class="w-fit">Resource Requests</h2>
<span
class="w-fit"
tabindex="0"
data-bs-title="Refresh Reviewable Resources"
data-bs-toggle="tooltip"
id="refreshReviewableResourcesButton"
>
<button
type="button"
class="btn btn-primary btn-light me-2 shadow-sm border w-fit"
:disabled="resourceState.loading"
@click="clickRefreshResources"
>
<font-awesome-icon icon="fa-solid fa-arrow-rotate-right" />
<span class="visually-hidden">Refresh Reviewable Resources</span>
</button>
</span>
</div>
<div v-if="resourceState.loading" class="text-center mt-5">
<div class="spinner-border" style="width: 3rem; height: 3rem" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<table
class="table caption-top table-striped table-hover align-middle"
v-else-if="resourceRepository.reviewableResources.length > 0"
>
<caption>
Display
{{
countItems
}}
resource versions
</caption>
<thead>
<tr>
<th scope="col">Resource</th>
<th scope="col">Release</th>
<th scope="col">Status</th>
<th scope="col">S3 Path</th>
<th scope="col" class="text-end">Action</th>
</tr>
</thead>
<tbody>
<template
v-for="resource in resourceRepository.reviewableResources"
:key="resource.resource_id"
>
<tr
v-for="version in resource.versions"
:key="version.resource_version_id"
>
<th>{{ resource.name }}</th>
<th>{{ version.release }}</th>
<th>{{ version.status }}</th>
<th>
<div class="input-group">
<input
class="form-control form-control-sm"
type="text"
:value="version.s3_path"
aria-label="S3 Access Path"
readonly
/>
<span class="input-group-text"
><copy-to-clipboard-icon :text="version.s3_path"
/></span>
</div>
</th>
<th class="text-end">
<div
v-if="version.status === Status.SYNC_REQUESTED"
class="btn-group"
>
<button
type="button"
class="btn btn-success btn-sm"
:disabled="resourceState.sendingRequest"
@click="syncResource(version)"
>
Synchronize
</button>
<button type="button" class="btn btn-danger btn-sm" disabled>
Deny
</button>
</div>
<div
v-else-if="version.status === Status.SYNCHRONIZING"
class="progress"
role="progressbar"
aria-label="Animated striped example"
aria-valuenow="100"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar progress-bar-striped progress-bar-animated"
style="width: 100%"
></div>
</div>
</th>
</tr>
</template>
</tbody>
</table>
<div v-else class="text-center mt-5 fs-4">
There are currently no Resources to review
</div>
</template>
<style scoped></style>