Skip to content
Snippets Groups Projects

Resolve "Add UI for viewing and managing Resources"

Merged Daniel Göbel requested to merge feature/88-add-ui-for-viewing-and-managing-resources into main
7 files
+ 189
5
Compare changes
  • Side-by-side
  • Inline
Files
7
 
<script setup lang="ts">
 
import { reactive, onMounted, ref } from "vue";
 
import BootstrapModal from "@/components/modals/BootstrapModal.vue";
 
import { Modal } from "bootstrap";
 
import { useResourceStore } from "@/stores/resources";
 
import type { ResourceIn } from "@/client/resource";
 
import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
 
import { Tooltip } from "bootstrap";
 
 
const resourceRepository = useResourceStore();
 
 
const resourceCreateForm = ref<HTMLFormElement | undefined>(undefined);
 
const resourceNameElement = ref<HTMLInputElement | undefined>(undefined);
 
 
const resource = reactive<ResourceIn>({
 
name: "",
 
description: "",
 
release: "",
 
source: "",
 
});
 
 
const formState = reactive<{
 
validated: boolean;
 
resourceNameTaken: boolean;
 
loading: boolean;
 
}>({
 
validated: false,
 
resourceNameTaken: false,
 
loading: false,
 
});
 
 
const props = defineProps<{
 
modalID: string;
 
}>();
 
 
let createResourceModal: Modal | null = null;
 
 
function createResource() {
 
formState.validated = true;
 
formState.resourceNameTaken = false;
 
resource.description = resource.description.trim();
 
resource.name = resource.name.trim();
 
resourceNameElement.value?.setCustomValidity("");
 
if (resourceCreateForm.value?.checkValidity()) {
 
formState.loading = true;
 
resourceRepository
 
.createResource(resource)
 
.then(() => {
 
createResourceModal?.hide();
 
resource.name = "";
 
resource.description = "";
 
resource.source = "";
 
resource.release = "";
 
formState.resourceNameTaken = false;
 
formState.validated = false;
 
})
 
.catch((error) => {
 
if (
 
error.status === 400 &&
 
error.body["detail"] ===
 
`Resource with name '${resource.name}' already exists`
 
) {
 
formState.resourceNameTaken = true;
 
resourceNameElement.value?.setCustomValidity(
 
"Resource name is already taken",
 
);
 
}
 
})
 
.finally(() => {
 
formState.loading = false;
 
});
 
}
 
}
 
 
function modalClosed() {
 
formState.validated = false;
 
formState.resourceNameTaken = false;
 
resourceNameElement.value?.setCustomValidity("");
 
}
 
 
onMounted(() => {
 
createResourceModal = new Modal("#" + props.modalID);
 
new Tooltip("#tooltip-new-resource-source");
 
new Tooltip("#tooltip-new-resource-release");
 
});
 
</script>
 
 
<template>
 
<bootstrap-modal
 
:modalId="modalID"
 
static-backdrop
 
modal-label="Create Resource Modal"
 
v-on="{ 'hidden.bs.modal': modalClosed }"
 
>
 
<template #header> Create new Resource</template>
 
<template #body>
 
<form
 
id="resourceCreateForm"
 
:class="{ 'was-validated': formState.validated }"
 
ref="resourceCreateForm"
 
>
 
<div class="mb-3">
 
<label for="resourceNameInput" class="form-label"
 
>Resource Name</label
 
>
 
<div class="input-group">
 
<input
 
type="text"
 
class="form-control"
 
id="resourceNameInput"
 
required
 
minlength="3"
 
maxlength="32"
 
v-model="resource.name"
 
ref="resourceNameElement"
 
/>
 
<div class="invalid-feedback">
 
<div v-if="formState.resourceNameTaken">
 
Resource name already taken.
 
</div>
 
<div>
 
Requirements
 
<ul>
 
<li>At least 3 Characters long</li>
 
<li>Unique in CloWM</li>
 
</ul>
 
</div>
 
</div>
 
</div>
 
</div>
 
<div class="mb-3">
 
<label for="resourceDescriptionInput" class="form-label">
 
Description
 
</label>
 
<div class="input-group">
 
<textarea
 
class="form-control"
 
id="resourceDescriptionInput"
 
required
 
rows="3"
 
minlength="16"
 
maxlength="256"
 
v-model="resource.description"
 
placeholder="Describe the purpose of the resource"
 
></textarea>
 
<div class="invalid-feedback">
 
Requirements
 
<ul>
 
<li>At least 16 Characters long</li>
 
</ul>
 
</div>
 
</div>
 
</div>
 
<div class="mb-3">
 
<label for="resourceSourceInput" class="form-label"> Source </label>
 
<div class="input-group">
 
<div class="input-group-text">
 
<font-awesome-icon icon="fa-solid fa-link" />
 
</div>
 
<input
 
class="form-control"
 
id="resourceSourceInput"
 
required
 
minlength="8"
 
maxlength="264"
 
v-model="resource.source"
 
placeholder="The source of the resource (e.g. a link)"
 
/>
 
<div
 
class="input-group-text hover-info"
 
id="tooltip-new-resource-source"
 
data-bs-toggle="tooltip"
 
data-bs-title="The source from where the resource comes"
 
>
 
<font-awesome-icon icon="fa-solid fa-circle-question" />
 
</div>
 
</div>
 
</div>
 
<div class="mb-3">
 
<label for="resourceReleaseInput" class="form-label"> Release </label>
 
<div class="input-group">
 
<div class="input-group-text">
 
<font-awesome-icon icon="fa-solid fa-tag" />
 
</div>
 
<input
 
class="form-control"
 
id="resourceReleaseInput"
 
required
 
minlength="3"
 
maxlength="32"
 
v-model="resource.release"
 
placeholder="Initial release name"
 
/>
 
<div
 
class="input-group-text hover-info"
 
id="tooltip-new-resource-release"
 
data-bs-toggle="tooltip"
 
data-bs-title="The name of the first resource version"
 
>
 
<font-awesome-icon icon="fa-solid fa-circle-question" />
 
</div>
 
</div>
 
</div>
 
</form>
 
</template>
 
<template v-slot:footer>
 
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
 
Close
 
</button>
 
<button
 
type="submit"
 
form="resourceCreateForm"
 
class="btn btn-primary"
 
:disabled="formState.loading"
 
@click.prevent="createResource"
 
>
 
<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>
Loading