Skip to content
Snippets Groups Projects
ArbitraryWorkflowView.vue 5.47 KiB
<script setup lang="ts">
import WorkflowDocumentationTabs from "@/components/workflows/WorkflowDocumentationTabs.vue";
import { onMounted, reactive, ref } from "vue";
import { GitRepository, requiredRepositoryFiles } from "@/utils/GitRepository";
import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
import ParameterSchemaFormComponent from "@/components/parameter-schema/ParameterSchemaFormComponent.vue";
import { WorkflowExecutionService } from "@/client/workflow";
import { useRouter } from "vue-router";
import { Toast } from "bootstrap";

const props = defineProps<{
  repository?: string;
  commit_hash?: string;
  token?: string;
}>();

const router = useRouter();

const workflowState = reactive<{
  loading: boolean;
  changelogMarkdown?: string;
  descriptionMarkdown?: string;
  usageMarkdown?: string;
  outputMarkdown?: string;
  parameterSchema?: Record<string, never>;
}>({
  loading: true,
});

const workflowExecutionState = reactive<{
  loading: boolean;
  errorType?: string;
}>({
  loading: false,
  errorType: undefined,
});

const showDocumentation = ref<boolean>(true);
let errorToast: Toast | null = null;

function downloadVersionFiles(
  repository: string,
  commit_hash: string,
  token?: string,
) {
  workflowState.loading = true;
  const repo = GitRepository.buildRepository(repository, commit_hash, token);
  Promise.all(
    requiredRepositoryFiles([]).map((file) =>
      repo.downloadFile(file).then((response) => {
        if (file.includes("README")) {
          workflowState.descriptionMarkdown = response.data;
        } else if (file.includes("CHANGELOG")) {
          workflowState.changelogMarkdown = response.data;
        } else if (file.includes("schema")) {
          workflowState.parameterSchema = response.data;
        } else if (file.includes("usage")) {
          workflowState.usageMarkdown = response.data;
        } else if (file.includes("output")) {
          workflowState.outputMarkdown = response.data;
        }
      }),
    ),
  ).finally(() => {
    workflowState.loading = false;
  });
}

function startWorkflow(
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  parameters: Record<string, any>,
  notes?: string,
  report_output_bucket?: string,
) {
  if (props.repository && props.commit_hash) {
    errorToast?.hide();
    workflowExecutionState.loading = true;
    WorkflowExecutionService.workflowExecutionStartArbitraryWorkflow({
      git_commit_hash: props.commit_hash,
      parameters: parameters,
      report_output_bucket: report_output_bucket,
      repository_url: props.repository,
      token: props.token,
    })
      .then(() => {
        router.push({
          name: "workflow-executions",
        });
      })
      .catch((err) => {
        console.error(err);
        if (err.body["detail"].includes("workflow execution limit")) {
          workflowExecutionState.errorType = "limit";
        }
        errorToast?.show();
      })
      .finally(() => {
        workflowExecutionState.loading = false;
      });
  }
}

onMounted(() => {
  errorToast = new Toast("#arbitraryWorkflowExecutionViewErrorToast");
  if (props.commit_hash && props.repository) {
    downloadVersionFiles(props.repository, props.commit_hash, props.token);
  }
});
</script>

<template>
  <div class="toast-container position-fixed top-toast end-0 p-3">
    <div
      role="alert"
      aria-live="assertive"
      aria-atomic="true"
      class="toast text-bg-danger align-items-center border-0"
      data-bs-autohide="true"
      id="arbitraryWorkflowExecutionViewErrorToast"
    >
      <div class="d-flex p-2 justify-content-between align-items-center">
        <div class="toast-body">
          <template v-if="workflowExecutionState.errorType === 'limit'">
            You have too many active workflow executions to start a new one.
          </template>
          <template v-else>
            There was an error with starting the workflow execution. Look in the
            console for more information.
          </template>
        </div>
        <button
          type="button"
          class="btn-close btn-close-white"
          data-bs-dismiss="toast"
          aria-label="Close"
        ></button>
      </div>
    </div>
  </div>
  <div class="row m-1 border-bottom mb-4">
    <h1 class="mb-2">Arbitrary Workflow</h1>
  </div>
  <h4>
    Git Repository: <a target="_blank" :href="repository">{{ repository }}</a>
  </h4>
  <h4 class="mb-5">Git Commit Hash: {{ commit_hash }}</h4>
  <div class="d-flex justify-content-center mb-5" v-if="showDocumentation">
    <a
      role="button"
      href="#"
      class="btn btn-success btn-lg mx-auto fs-4"
      :class="{ disabled: !workflowState.parameterSchema }"
      @click="showDocumentation = false"
    >
      <font-awesome-icon icon="fa-solid fa-rocket" class="me-2" />
      <span class="align-middle">Launch</span>
    </a>
  </div>
  <template v-if="repository && commit_hash">
    <workflow-documentation-tabs
      v-if="showDocumentation"
      :loading="workflowState.loading"
      :output-markdown="workflowState.outputMarkdown"
      :usage-markdown="workflowState.usageMarkdown"
      :description-markdown="workflowState.descriptionMarkdown"
      :changelog-markdown="workflowState.changelogMarkdown"
      :parameter-schema="workflowState.parameterSchema"
    />
    <parameter-schema-form-component
      v-else
      :loading="workflowExecutionState.loading"
      :schema="workflowState.parameterSchema"
      @start-workflow="startWorkflow"
    />
  </template>
  <p v-else>Nope</p>
</template>

<style scoped></style>