Skip to content
Snippets Groups Projects
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>