Skip to content
Snippets Groups Projects
ArbitraryWorkflowModal.vue 6.21 KiB
Newer Older
  • Learn to ignore specific revisions
  • <script setup lang="ts">
    import BootstrapModal from "@/components/modals/BootstrapModal.vue";
    import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
    import { computed, onMounted, reactive, ref } from "vue";
    import { useRouter } from "vue-router";
    import {
      GitRepository,
      requiredRepositoryFiles,
      determineGitIcon,
    } from "@/utils/GitRepository";
    import { Modal } from "bootstrap";
    
    const props = defineProps<{
      modalID: string;
    }>();
    
    let createWorkflowModal: Modal | null = null;
    const arbitraryWorkflowForm = ref<HTMLFormElement | undefined>(undefined);
    const workflowRepositoryElement = ref<HTMLInputElement | undefined>(undefined);
    const router = useRouter();
    
    const workflow = reactive<{
      repository_url: string;
      git_commit_hash: string;
    }>({
      repository_url: "",
      git_commit_hash: "",
    });
    
    const formState = reactive<{
      loading: boolean;
      checkRepoLoading: boolean;
      validated: boolean;
      allowUpload: boolean;
      missingFiles: string[];
      unsupportedRepository: boolean;
    }>({
      validated: false,
      allowUpload: false,
      loading: false,
      checkRepoLoading: false,
      missingFiles: [],
      unsupportedRepository: false,
    });
    
    function modalClosed() {
      formState.validated = false;
    }
    
    function viewWorkflow() {
      console.log("View", workflow);
      createWorkflowModal?.hide();
      router.push({
        name: "arbitrary-workflow",
        query: {
          repository: encodeURI(workflow.repository_url),
          commit_hash: workflow.git_commit_hash,
        },
      });
    }
    
    function checkRepository() {
      formState.validated = true;
      if (arbitraryWorkflowForm.value?.checkValidity() && !formState.allowUpload) {
        formState.unsupportedRepository = false;
        formState.missingFiles = [];
        workflowRepositoryElement.value?.setCustomValidity("");
        try {
          const repo = GitRepository.buildRepository(
            workflow.repository_url,
            workflow.git_commit_hash
          );
          repo
            .checkFilesExist(requiredRepositoryFiles, true)
            .then(() => {
              formState.allowUpload = true;
            })
            .catch((e: Error) => {
              formState.missingFiles = e.message.split(",");
              // Allow execution of the workflow if main.nf and parameter schema are not missing
              if (
                formState.missingFiles.findIndex(
                  (file) => file === "main.nf" || file === "nextflow_schema.json"
                ) < 0
              ) {
                formState.allowUpload = true;
              }
            });
        } catch (e) {
          formState.unsupportedRepository = true;
          workflowRepositoryElement.value?.setCustomValidity(
            "Repository is not supported"
          );
        }
      }
    }
    const gitIcon = computed<string>(() =>
      determineGitIcon(workflow.repository_url)
    );
    
    onMounted(() => {
      createWorkflowModal = new Modal("#" + props.modalID);
    });
    </script>
    
    <template>
      <bootstrap-modal
        :modalID="modalID"
        :static-backdrop="false"
        modal-label="Create Workflow Modal"
        v-on="{ 'hidden.bs.modal': modalClosed }"
      >
        <template v-slot:header>Start arbitrary Workflow</template>
        <template v-slot:body>
          <form
            id="arbitraryWorkflowForm"
            :class="{ 'was-validated': formState.validated }"
            ref="arbitraryWorkflowForm"
          >
            <div class="mb-3">
              <label for="workflowRepositoryInput" class="form-label"
                >Git Repository URL</label
              >
              <div class="input-group">
                <div class="input-group-text">
                  <font-awesome-icon :icon="gitIcon" />
                </div>
                <input
                  type="url"
                  class="form-control"
                  id="workflowRepositoryInput"
                  placeholder="https://..."
                  required
                  ref="workflowRepositoryElement"
                  v-model="workflow.repository_url"
                  @change="formState.allowUpload = false"
                  aria-describedby="gitRepoProviderHelp"
                />
              </div>
              <div id="gitRepoProviderHelp" class="form-text">
                We support Github and GitLab Repositories
              </div>
              <div class="text-danger">
                <div v-if="formState.unsupportedRepository">
                  Repository is not supported
                </div>
              </div>
            </div>
            <div class="mb-3">
              <label for="workflowGitCommitInput" class="form-label"
                >Git Commit Hash</label
              >
              <div class="input-group">
                <div class="input-group-text">
                  <font-awesome-icon icon="fa-solid fa-code-commit" />
                </div>
                <input
                  type="text"
                  class="form-control text-lowercase"
                  id="workflowGitCommitInput"
                  placeholder="ba8bcd9..."
                  required
                  ref="workflowGitCommitHashElement"
                  maxlength="40"
                  minlength="40"
                  pattern="[0-9a-f]{40}"
                  v-model="workflow.git_commit_hash"
                  @change="formState.allowUpload = false"
                />
              </div>
            </div>
            <div v-if="formState.missingFiles.length > 0" class="text-danger">
              The following files are missing in the repository
              <ul>
                <li v-for="file in formState.missingFiles" :key="file">
                  {{ file }}
                </li>
              </ul>
            </div>
          </form>
        </template>
        <template v-slot:footer>
          <button
            type="button"
            class="btn btn-info me-auto"
            @click="checkRepository"
            :disabled="formState.allowUpload"
          >
            <span
              v-if="formState.checkRepoLoading"
              class="spinner-border spinner-border-sm"
              role="status"
              aria-hidden="true"
            ></span>
            Check Repository
          </button>
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
            Close
          </button>
          <button
            type="submit"
            form="workflowCreateForm"
            class="btn btn-primary"
            :disabled="formState.loading || !formState.allowUpload"
            @click.prevent="viewWorkflow"
          >
            <span
              v-if="formState.loading"
              class="spinner-border spinner-border-sm"
              role="status"
              aria-hidden="true"
            ></span>
    
          </button>
        </template>
      </bootstrap-modal>
    </template>
    
    <style scoped></style>