Skip to content
Snippets Groups Projects
ReviewResourceView.vue 7.21 KiB
Newer Older
  • Learn to ignore specific revisions
  • <script setup lang="ts">
    import { useResourceStore } from "@/stores/resources";
    import { computed, onMounted, reactive } from "vue";
    import {
      type ResourceOut,
      type ResourceVersionOut,
      Status,
    } from "@/client/resource";
    import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
    
    import { Modal, Toast, Tooltip } from "bootstrap";
    import ResourceVersionInfoModal from "@/components/resources/modals/ResourceVersionInfoModal.vue";
    
    import { useNameStore } from "@/stores/names";
    
    import BootstrapToast from "@/components/BootstrapToast.vue";
    import ReasonModal from "@/components/modals/ReasonModal.vue";
    
    
    const resourceRepository = useResourceStore();
    const nameRepository = useNameStore();
    let refreshTimeout: NodeJS.Timeout | undefined = undefined;
    
    let rejectReasonModal: Modal | null = null;
    let successToast: Toast | null = null;
    let rejectToast: Toast | null = null;
    
    
    const resourceState = reactive<{
      sendingRequest: boolean;
      loading: boolean;
      inspectResource?: ResourceOut;
    
      rejectResource?: ResourceVersionOut;
    
      inspectVersionIndex: number;
    }>({
      sendingRequest: false,
      loading: true,
      inspectResource: undefined,
    
      rejectResource: undefined,
    
      inspectVersionIndex: 0,
    });
    
    const countItems = computed<number>(() =>
      resourceRepository.reviewableResources.reduce(
        (previousValue, currentValue) =>
          previousValue + currentValue.versions.length,
        0,
      ),
    );
    
    function fetchResources() {
      resourceRepository.fetchReviewableResources(() => {
        resourceState.loading = false;
      });
    }
    
    function clickRefreshResources() {
      clearTimeout(refreshTimeout);
      refreshTimeout = setTimeout(() => {
        fetchResources();
      }, 500);
    }
    
    
    function acceptReview(resourceVersion: ResourceVersionOut) {
    
      resourceState.sendingRequest = true;
    
      resourceRepository
        .reviewResource(resourceVersion, { deny: false })
        .then(() => {
          successToast?.show();
        })
        .finally(() => {
          resourceState.sendingRequest = false;
        });
    
    function rejectReview(reason: string, resourceVersion?: ResourceVersionOut) {
      if (resourceVersion) {
        resourceState.sendingRequest = true;
        resourceRepository
          .reviewResource(resourceVersion, { deny: true, reason: reason })
          .then(() => {
            rejectReasonModal?.hide();
            rejectToast?.show();
          })
          .finally(() => {
            resourceState.sendingRequest = false;
          });
      }
    
    onMounted(() => {
      fetchResources();
      new Tooltip("#refreshReviewableResourcesButton");
    
      rejectReasonModal = new Modal("#review-reject-modal");
      successToast = new Toast("#accept-resource-review-toast");
      rejectToast = new Toast("#reject-resource-review-toast");
    
      <bootstrap-toast
        toast-id="accept-resource-review-toast"
        color-class="success"
      >
        Accepted resource review
      </bootstrap-toast>
      <bootstrap-toast toast-id="reject-resource-review-toast" color-class="danger">
        Rejected resource review
      </bootstrap-toast>
    
      <resource-version-info-modal
        modal-id="review-resource-version-info-modal"
        :resource-version-index="resourceState.inspectVersionIndex"
        :resource="resourceState.inspectResource"
      />
    
      <reason-modal
        modal-id="review-reject-modal"
        modal-label="Resource Review Reject Modal"
        :loading="resourceState.sendingRequest"
        purpose="rejection"
        @save="(reason) => rejectReview(reason, resourceState.rejectResource)"
      >
        <template #header>
          Reject Resource Review <b>{{ resourceState.rejectResource?.release }}</b>
        </template>
      </reason-modal>
    
        class="row 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">Maintainer</th>
            <th scope="col"></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, index) in resource.versions"
              :key="version.resource_version_id"
            >
              <th>{{ resource.name }}</th>
              <th>{{ version.release }}</th>
              <th>{{ version.status }}</th>
              <th>{{ nameRepository.getName(resource.maintainer_id) }}</th>
              <th>
                <button
                  type="button"
                  class="btn btn-secondary"
                  data-bs-toggle="modal"
                  data-bs-target="#review-resource-version-info-modal"
                  @click="
                    resourceState.inspectResource = resource;
                    resourceState.inspectVersionIndex = index;
                  "
                >
                  Inspect
                </button>
              </th>
              <th class="text-end">
                <div
    
                  v-if="version.status === Status.WAIT_FOR_REVIEW"
    
                  class="btn-group"
                >
                  <button
                    type="button"
                    class="btn btn-success btn-sm"
                    :disabled="resourceState.sendingRequest"
    
                    @click="acceptReview(version)"
    
                  <button
                    type="button"
                    class="btn btn-danger btn-sm"
    
                    @click="resourceState.rejectResource = version"
                    data-bs-toggle="modal"
                    data-bs-target="#review-reject-modal"
    
                    :disabled="resourceState.sendingRequest"
                  >
    
                  </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>