Skip to content

Commit

Permalink
Redesign license selection using vue-multiselect for improved usabi…
Browse files Browse the repository at this point in the history
…lity

Updated the `LicenseSelector` component to enhance user experience by replace a `Multiselect` form `vue-multiselect` dropdown and simplifying the license handling steps and logic.
  • Loading branch information
itisAliRH committed Oct 11, 2024
1 parent 0d7b165 commit 024bf21
Showing 1 changed file with 49 additions and 99 deletions.
148 changes: 49 additions & 99 deletions client/src/components/License/LicenseSelector.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
<script setup lang="ts">
import { faEdit, faSave, faTimes } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { BAlert, BButton, BFormSelect } from "bootstrap-vue";
import { BAlert } from "bootstrap-vue";
import { computed, ref, watch } from "vue";
import Multiselect from "vue-multiselect";
import { GalaxyApi } from "@/api";
import { type components } from "@/api/schema";
import { errorMessageAsString } from "@/utils/simple-error";
import License from "./License.vue";
import License from "@/components/License/License.vue";
import LoadingSpan from "@/components/LoadingSpan.vue";
const defaultLicense: LicenseType = {
licenseId: null,
name: "*Do not specify a license.*",
};
type LicenseMetadataModel = components["schemas"]["LicenseMetadataModel"];
type LicenseType = {
licenseId: string | null;
name: string;
};
interface Props {
inputLicense: string;
Expand All @@ -20,56 +28,33 @@ interface Props {
const props = defineProps<Props>();
const emit = defineEmits<{
(e: "onLicense", license: string): void;
(e: "onLicense", license: string | null): void;
}>();
const editLicense = ref(false);
const licensesLoading = ref(true);
const errorMessage = ref<string>("");
const currentLicense = ref<string>(props.inputLicense);
const currentLicense = ref<LicenseType>();
const licenses = ref<LicenseMetadataModel[] | undefined>([]);
const currentLicenseInfo = computed(() => {
for (const l of licenses.value || []) {
if (l.licenseId == currentLicense.value) {
return l;
}
}
return null;
});
const licenseOptions = computed(() => {
const options = [];
const options: LicenseType[] = [];
options.push({
value: null,
text: "*Do not specify a license.*",
});
options.push(defaultLicense);
for (const l of licenses.value || []) {
if (l.licenseId == currentLicense.value || l.recommended) {
for (const license of licenses.value || []) {
if (license.licenseId == currentLicense.value?.licenseId || license.recommended) {
options.push({
value: l.licenseId,
text: l.name,
licenseId: license.licenseId,
name: license.name,
});
}
}
return options;
});
function onSave() {
onLicense(currentLicense.value);
disableEdit();
}
function disableEdit() {
editLicense.value = false;
errorMessage.value = "";
}
function onLicense(l: string) {
emit("onLicense", l);
function onLicense(license: LicenseType) {
emit("onLicense", license.licenseId);
}
async function fetchLicenses() {
Expand All @@ -84,78 +69,43 @@ async function fetchLicenses() {
licensesLoading.value = false;
}
async function setCurrentLicense() {
if (!licenses.value?.length) {
await fetchLicenses();
}
const inputLicense = props.inputLicense;
currentLicense.value = (licenses.value || []).find((l) => l.licenseId == inputLicense) || defaultLicense;
}
watch(
() => props.inputLicense,
(newLicense) => {
currentLicense.value = newLicense;
() => {
setCurrentLicense();
}
);
fetchLicenses();
setCurrentLicense();
</script>

<template>
<div v-if="editLicense" class="license-selector">
<LoadingSpan v-if="licensesLoading" message="Loading licenses" />
<div>
<BAlert v-if="licensesLoading" variant="info" class="m-0" show>
<LoadingSpan message="Loading licenses" />
</BAlert>
<BAlert v-else-if="errorMessage" variant="danger" class="m-0" show>
{{ errorMessage }}
</BAlert>
<BFormSelect v-else v-model="currentLicense" data-description="license select" :options="licenseOptions" />

<License v-if="currentLicenseInfo" :license-id="currentLicense" :input-license-info="currentLicenseInfo">
<template v-slot:buttons>
<BButton v-b-tooltip.hover variant="outline-danger" title="Cancel Edit" @click="disableEdit">
<FontAwesomeIcon :icon="faTimes" data-description="license cancel" />
Cancel
</BButton>
<BButton v-b-tooltip.hover variant="primary" title="Save License" @click="onSave">
<FontAwesomeIcon :icon="faSave" data-description="license save" />
Save License
</BButton>
</template>
</License>
<div v-else>
<BButton variant="outline-danger" @click="editLicense = false">
<FontAwesomeIcon :icon="faTimes" data-description="license cancel" />
Cancel
</BButton>
<BButton variant="primary" @click="onSave">
<FontAwesomeIcon :icon="faSave" data-description="license save" />
Save without license
</BButton>
</div>
</div>
<div
v-else-if="currentLicense"
data-description="license selector"
:data-license="currentLicense"
class="license-selector-edit">
<License :license-id="currentLicense">
<template v-slot:inline-buttons>
<BButton
v-b-tooltip.hover
class="inline-icon-button"
variant="link"
size="sm"
title="Edit License"
@click="editLicense = true">
<FontAwesomeIcon :icon="faEdit" data-description="edit license link" fixed-width />
</BButton>
</template>
</License>
</div>
<div v-else data-description="license selector" data-license="null">
<i>
<a href="#" data-description="edit license link" @click.prevent="editLicense = true">
Specify a license for this workflow.
</a>
</i>
<Multiselect
v-else
v-model="currentLicense"
data-description="license select"
track-by="licenseId"
:options="licenseOptions"
label="name"
placeholder="Select a license"
@select="onLicense" />
<License v-if="currentLicense?.licenseId" :license-id="currentLicense.licenseId" />
</div>
</template>

<style scoped lang="scss">
.license-selector {
display: grid;
gap: 0.5em;
}
</style>

0 comments on commit 024bf21

Please sign in to comment.