Skip to content
Snippets Groups Projects
CreateBucketComponent.vue 4.57 KiB
<script setup lang="ts">
import { BucketService } from "@/client";
import type { BucketIn } from "@/client";
import { reactive, onMounted } from "vue";
import BootstrapModal from "@/components/BootstrapModal.vue";
import { useRouter } from "vue-router";
import { Modal } from "bootstrap";

const router = useRouter();
const emit = defineEmits(["bucketCreated"]);
const bucket = reactive({ name: "", description: "" } as BucketIn);
const formState = reactive({
  validated: false,
  bucketNameTaken: false,
  loading: false,
} as {
  validated: boolean;
  bucketNameTaken: boolean;
  loading: boolean;
});

const props = defineProps<{
  modalID: string;
  modalLabel: string;
}>();

let createBucketModal: Modal | null = null;

onMounted(() => {
  createBucketModal = new Modal("#" + props.modalID);
  console.log("Modal ID", props.modalID);
});

function createBucket() {
  formState.validated = true;
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
  const form = document.getElementById("bucketCreateForm")! as HTMLFormElement;
  formState.bucketNameTaken = false;
  if (form.checkValidity()) {
    formState.loading = true;
    BucketService.bucketCreateBucket(bucket)
      .then((createdBucket) => {
        emit("bucketCreated", createdBucket);
        createBucketModal?.hide();
        bucket.name = "";
        bucket.description = "";
        formState.bucketNameTaken = false;
        formState.validated = false;
        router.push({
          name: "bucket",
          params: { bucketName: createdBucket.name, subFolders: [] },
        });
      })
      .catch((error) => {
        if (
          error.status === 400 &&
          error.body["detail"] === "Bucket name is already taken"
        ) {
          formState.bucketNameTaken = true;
        }
      })
      .finally(() => {
        formState.loading = false;
      });
  }
}

function modalClosed() {
  formState.validated = false;
  formState.bucketNameTaken = false;
}
</script>

<template>
  <bootstrap-modal
    :modal-id="modalID"
    :static-backdrop="true"
    :modal-label="modalLabel"
    v-on="{ 'hidden.bs.modal': modalClosed }"
  >
    <template v-slot:header> Create new Bucket </template>
    <template v-slot:body>
      <form
        id="bucketCreateForm"
        :class="{ 'was-validated': formState.validated }"
        novalidate
      >
        <div class="mb-3">
          <label for="bucketNameInput" class="form-label">Bucket Name</label>
          <div class="input-group">
            <input
              type="text"
              class="form-control"
              id="bucketNameInput"
              required
              minlength="3"
              maxlength="63"
              pattern="(?!(^((2(5[0-5]|[0-4]\d)|[01]?\d{1,2})\.){3}(2(5[0-5]|[0-4]\d)|[01]?\d{1,2})$))^[a-z\d][a-z\d.-]{1,61}[a-z\d]$"
              v-model.trim="bucket.name"
            />
            <div class="invalid-feedback">
              Requirements
              <ul>
                <li>At least 3 Characters long</li>
                <li>Lowercase</li>
                <li>Only [a-z][0-9].-</li>
                <li>No IP address</li>
              </ul>
            </div>
          </div>
        </div>
        <div class="mb-3">
          <label for="bucketDescriptionInput" class="form-label">
            Description
          </label>
          <div class="input-group">
            <textarea
              class="form-control"
              id="bucketDescriptionInput"
              required
              rows="5"
              minlength="126"
              maxlength="65536"
              v-model.trim="bucket.description"
              placeholder="Describe the purpose of the bucket"
            ></textarea>
            <div class="invalid-feedback">
              Requirements
              <ul>
                <li>At least 126 Characters long</li>
              </ul>
            </div>
          </div>
        </div>
      </form>
      <div v-if="formState.bucketNameTaken" class="text-danger">
        Bucket name already taken.
      </div>
    </template>
    <template v-slot:footer>
      <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
        Close
      </button>
      <button
        type="submit"
        form="bucketCreateForm"
        class="btn btn-primary"
        :disabled="formState.loading"
        @click.prevent="createBucket"
      >
        <span
          v-if="formState.loading"
          class="spinner-border spinner-border-sm"
          role="status"
          aria-hidden="true"
        ></span>
        Save
      </button>
    </template>
  </bootstrap-modal>
</template>

<style scoped></style>