Bug 32030: Improve form UI
authorJonathan Druart <jonathan.druart@bugs.koha-community.org>
Thu, 28 Jul 2022 15:26:46 +0000 (17:26 +0200)
committerTomas Cohen Arazi <tomascohen@theke.io>
Tue, 8 Nov 2022 12:44:19 +0000 (09:44 -0300)
* Align inputs, textareas and selects
* Use vue-select for dropdown lists

Note that the only way I found to make the select required is to follow
what is on their doc https://vue-select.org/guide/validation.html#required

However we need our own vue-select-required component to avoid the
repetition (the #search slot). I've tried (but failed) on
https://gitlab.com/joubu/Koha/-/commits/erm-v-select-required

Signed-off-by: Jonathan Field <jonathan.field@ptfs-europe.com>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
15 files changed:
cypress/integration/Agreements_spec.ts
cypress/integration/Licenses_spec.ts
cypress/integration/Packages_spec.ts
koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementLicenses.vue
koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementRelationships.vue
koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementUserRoles.vue
koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementsFormAdd.vue
koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/EHoldingsLocalPackageAgreements.vue
koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/EHoldingsLocalPackagesFormAdd.vue
koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/EHoldingsLocalTitlesFormAdd.vue
koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/EHoldingsLocalTitlesFormAddResources.vue
koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/ERMMain.vue
koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/LicensesFormAdd.vue
koha-tmpl/intranet-tmpl/prog/js/vue/main-erm.ts
package.json

index a592628..928b201 100644 (file)
@@ -102,7 +102,7 @@ describe("Agreement CRUD operations", () => {
             "have.length",
             1
         ); // name, description, status
-        cy.get("#agreement_status").select(agreement.status);
+        cy.get("#agreement_status .vs__search").type(agreement.status + '{enter}',{force:true});
 
         cy.contains("Add new period").click();
         cy.get("#agreements_add").contains("Submit").click();
@@ -215,7 +215,7 @@ describe("Agreement CRUD operations", () => {
             "have.value",
             agreements[0].description
         );
-        cy.get("#agreement_status").should("have.value", agreement.status);
+        cy.get("#agreement_status .vs__selected").contains("Active");
         cy.get("#agreement_is_perpetual_no").should("be.checked");
         cy.get("#started_on_0").invoke("val").should("eq", dates["today_us"]);
         cy.get("#ended_on_0").invoke("val").should("eq", dates["tomorrow_us"]);
index 068fafe..f2498bb 100644 (file)
@@ -77,8 +77,8 @@ describe("License CRUD operations", () => {
         cy.get("#license_name").type(license.name);
         cy.get("#license_description").type(license.description);
         cy.get("#licenses_add").contains("Submit").click();
-        cy.get("#license_type").select(license.type);
-        cy.get("#license_status").select(license.status);
+        cy.get("#license_type .vs__search").type(license.type + '{enter}',{force:true});
+        cy.get("#license_status .vs__search").type(license.status + '{enter}',{force:true});
 
         cy.get("#started_on").click();
         cy.get(".flatpickr-calendar")
@@ -143,8 +143,8 @@ describe("License CRUD operations", () => {
             "have.value",
             license.description
         );
-        cy.get("#license_type").should("have.value", license.type);
-        cy.get("#license_status").should("have.value", license.status);
+        cy.get("#license_type .vs__selected").contains("Local");
+        cy.get("#license_status .vs__selected").contains("Active");
         cy.get("#started_on").invoke("val").should("eq", dates["today_us"]);
         cy.get("#ended_on").invoke("val").should("eq", dates["tomorrow_us"]);
 
index 9bce51f..55b6813 100644 (file)
@@ -67,8 +67,8 @@ describe("Package CRUD operations", () => {
             1
         );
         cy.get("#package_name").type(erm_package.name);
-        cy.get("#package_type").select(erm_package.package_type);
-        cy.get("#package_content_type").select(erm_package.content_type);
+        cy.get("#package_type .vs__search").type(erm_package.package_type + '{enter}',{force:true});
+        cy.get("#package_content_type .vs__search").type(erm_package.content_type + '{enter}',{force:true});
 
         // Submit the form, get 500
         cy.intercept("POST", "/api/v1/erm/eholdings/local/packages", {
@@ -116,8 +116,8 @@ describe("Package CRUD operations", () => {
 
         // Form has been correctly filled in
         cy.get("#package_name").should("have.value", erm_package.name);
-        cy.get("#package_type").should("have.value", erm_package.package_type);
-        cy.get("#package_content_type").should("have.value", erm_package.content_type);
+        cy.get("#package_type .vs__selected").contains("Complete");
+        cy.get("#package_content_type .vs__selected").contains("Print");
 
         // Submit the form, get 500
         cy.intercept("PUT", "/api/v1/erm/eholdings/local/packages/*", {
index 813faf7..995abc8 100644 (file)
                     <label :for="`license_id_${counter}`"
                         >{{ $t("License") }}:</label
                     >
-                    <select
+                    <v-select
                         :id="`license_id_${counter}`"
                         v-model="agreement_license.license_id"
-                        required
+                        label="name"
+                        :reduce="(l) => l.license_id"
+                        :options="licenses"
                     >
-                        <option value=""></option>
-                        <option
-                            v-for="license in licenses"
-                            :key="license.license_id"
-                            :value="license.license_id"
-                            :selected="
-                                license.license_id ==
-                                agreement_license.license_id
-                                    ? true
-                                    : false
-                            "
-                        >
-                            {{ license.name }}
-                        </option>
-                    </select>
+                        <template #search="{ attributes, events }">
+                            <input
+                                :required="!agreement_license.license_id"
+                                class="vs__search"
+                                v-bind="attributes"
+                                v-on="events"
+                            />
+                        </template>
+                    </v-select>
                     <span class="required">{{ $t("Required") }}</span>
                 </li>
                 <li>
                     <label :for="`license_status_${counter}`"
                         >{{ $t("Status") }}:</label
                     >
-                    <select v-model="agreement_license.status" required>
-                        <option value=""></option>
-                        <option
-                            v-for="r in av_agreement_license_statuses"
-                            :key="r.authorised_values"
-                            :value="r.authorised_value"
-                            :selected="
-                                r.authorised_value == agreement_license.status
-                                    ? true
-                                    : false
-                            "
-                        >
-                            {{ r.lib }}
-                        </option>
-                    </select>
+                    <v-select
+                        :id="`license_status_${counter}`"
+                        v-model="agreement_license.status"
+                        label="lib"
+                        :reduce="(av) => av.authorised_value"
+                        :options="av_agreement_license_statuses"
+                    >
+                        <template #search="{ attributes, events }">
+                            <input
+                                :required="!agreement_license.status"
+                                class="vs__search"
+                                v-bind="attributes"
+                                v-on="events"
+                            />
+                        </template>
+                    </v-select>
                     <span class="required">{{ $t("Required") }}</span>
                 </li>
                 <li>
                     <label :for="`license_location_${counter}`"
                         >{{ $t("Physical location") }}:
                     </label>
-                    <select v-model="agreement_license.physical_location">
-                        <option value=""></option>
-                        <option
-                            v-for="r in av_agreement_license_location"
-                            :key="r.authorised_values"
-                            :value="r.authorised_value"
-                            :selected="
-                                r.authorised_value ==
-                                agreement_license.physical_location
-                                    ? true
-                                    : false
-                            "
-                        >
-                            {{ r.lib }}
-                        </option>
-                    </select>
+                    <v-select
+                        :id="`license_location_${counter}`"
+                        v-model="agreement_license.physical_location"
+                        label="lib"
+                        :reduce="(av) => av.authorised_value"
+                        :options="av_agreement_license_location"
+                    />
                 </li>
                 <li>
                     <label :for="`license_notes_${counter}`"
index 1ee2edc..ac57dc3 100644 (file)
                     <label :for="`related_agreement_id_${counter}`"
                         >{{ $t("Related agreement") }}:
                     </label>
-                    <select
-                        v-model="relationship.related_agreement_id"
+                    <v-select
                         :id="`related_agreement_id_${counter}`"
+                        v-model="relationship.related_agreement_id"
+                        label="name"
+                        :reduce="(a) => a.agreement_id"
+                        :options="agreements"
                     >
-                        <option value=""></option>
-                        <option
-                            v-for="agreement in agreements"
-                            :key="agreement.agreement_id"
-                            :value="agreement.agreement_id"
-                            :selected="
-                                agreement.agreement_id ==
-                                relationship.related_agreement_id
-                                    ? true
-                                    : false
-                            "
-                        >
-                            {{ agreement.name }}
-                        </option>
-                    </select>
+                        <template #search="{ attributes, events }">
+                            <input
+                                :required="!relationship.related_agreement_id"
+                                class="vs__search"
+                                v-bind="attributes"
+                                v-on="events"
+                            />
+                        </template>
+                    </v-select>
+                    <span class="required">{{ $t("Required") }}</span>
                 </li>
                 <li>
                     <label :for="`related_agreement_relationship_${counter}`"
                         >{{ $t("Relationship") }}:
                     </label>
-                    <select
-                        v-model="relationship.relationship"
+                    <v-select
                         :id="`related_agreement_relationship_${counter}`"
-                        required
+                        v-model="relationship.relationship"
+                        label="lib"
+                        :reduce="(av) => av.authorised_value"
+                        :options="av_agreement_relationships"
                     >
-                        <option value=""></option>
-                        <option
-                            v-for="r in av_agreement_relationships"
-                            :key="r.authorised_values"
-                            :value="r.authorised_value"
-                            :selected="
-                                r.authorised_value == relationship.relationship
-                                    ? true
-                                    : false
-                            "
-                        >
-                            {{ r.lib }}
-                        </option>
-                    </select>
+                        <template #search="{ attributes, events }">
+                            <input
+                                :required="!relationship.relationship"
+                                class="vs__search"
+                                v-bind="attributes"
+                                v-on="events"
+                            />
+                        </template>
+                    </v-select>
                     <span class="required">{{ $t("Required") }}</span>
                 </li>
                 <li>
index 62a6a52..5dbc2ad 100644 (file)
                     <label :for="`user_role_${counter}`"
                         >{{ $t("Role") }}:</label
                     >
-                    <select v-model="user_role.role" required>
-                        <option value=""></option>
-                        <option
-                            v-for="r in av_agreement_user_roles"
-                            :key="r.authorised_values"
-                            :value="r.authorised_value"
-                            :selected="
-                                r.authorised_value == user_role.role
-                                    ? true
-                                    : false
-                            "
-                        >
-                            {{ r.lib }}
-                        </option>
-                    </select>
+                    <v-select
+                        :id="`user_role_${counter}`"
+                        v-model="user_role.role"
+                        label="lib"
+                        :reduce="(av) => av.authorised_value"
+                        :options="av_agreement_user_roles"
+                    >
+                        <template #search="{ attributes, events }">
+                            <input
+                                :required="!user_role.role"
+                                class="vs__search"
+                                v-bind="attributes"
+                                v-on="events"
+                            />
+                        </template>
+                    </v-select>
                     <span class="required">{{ $t("Required") }}</span>
                 </li>
             </ol>
index cfe5696..1df13c1 100644 (file)
                             <label for="agreement_vendor_id"
                                 >{{ $t("Vendor") }}:</label
                             >
-                            <select
+                            <v-select
                                 id="agreement_vendor_id"
                                 v-model="agreement.vendor_id"
-                            >
-                                <option value=""></option>
-                                <option
-                                    v-for="vendor in vendors"
-                                    :key="vendor.vendor_id"
-                                    :value="vendor.id"
-                                    :selected="
-                                        vendor.id == agreement.vendor_id
-                                            ? true
-                                            : false
-                                    "
-                                >
-                                    {{ vendor.name }}
-                                </option>
-                            </select>
+                                label="name"
+                                :reduce="(vendor) => vendor.id"
+                                :options="vendors"
+                            />
                         </li>
                         <li>
                             <label for="agreement_description"
                             <label for="agreement_status"
                                 >{{ $t("Status") }}:</label
                             >
-                            <select
+                            <v-select
                                 id="agreement_status"
                                 v-model="agreement.status"
-                                @change="onStatusChange($event)"
-                                required
+                                label="lib"
+                                :reduce="(av) => av.authorised_value"
+                                :options="av_agreement_statuses"
+                                @option:selected="onStatusChanged"
+                                :required="!agreement.status"
                             >
-                                <option value=""></option>
-                                <option
-                                    v-for="status in av_agreement_statuses"
-                                    :key="status.authorised_values"
-                                    :value="status.authorised_value"
-                                    :selected="
-                                        status.authorised_value ==
-                                        agreement.status
-                                            ? true
-                                            : false
-                                    "
-                                >
-                                    {{ status.lib }}
-                                </option>
-                            </select>
+                                <template #search="{ attributes, events }">
+                                    <input
+                                        :required="!agreement.status"
+                                        class="vs__search"
+                                        v-bind="attributes"
+                                        v-on="events"
+                                    />
+                                </template>
+                            </v-select>
                             <span class="required">{{ $t("Required") }}</span>
                         </li>
                         <li>
                             <label for="agreement_closure_reason"
                                 >{{ $t("Closure reason") }}:</label
                             >
-                            <select
+                            <v-select
                                 id="agreement_closure_reason"
                                 v-model="agreement.closure_reason"
+                                label="lib"
+                                :reduce="(av) => av.authorised_value"
+                                :options="av_agreement_closure_reasons"
                                 :disabled="
                                     agreement.status == 'closed' ? false : true
                                 "
-                            >
-                                <option value=""></option>
-                                <option
-                                    v-for="r in av_agreement_closure_reasons"
-                                    :key="r.authorised_values"
-                                    :value="r.authorised_value"
-                                    :selected="
-                                        r.authorised_value ==
-                                        agreement.closure_reason
-                                            ? true
-                                            : false
-                                    "
-                                >
-                                    {{ r.lib }}
-                                </option>
-                            </select>
+                            />
                         </li>
                         <li>
                             <label for="agreement_is_perpetual" class="radio"
                             <label for="agreement_renewal_priority"
                                 >{{ $t("Renewal priority") }}:</label
                             >
-                            <select v-model="agreement.renewal_priority">
-                                <option value=""></option>
-                                <option
-                                    v-for="p in av_agreement_renewal_priorities"
-                                    :key="p.authorised_values"
-                                    :value="p.authorised_value"
-                                    :selected="
-                                        p.authorised_value ==
-                                        agreement.renewal_priority
-                                            ? true
-                                            : false
-                                    "
-                                >
-                                    {{ p.lib }}
-                                </option>
-                            </select>
+                            <v-select
+                                id="agreement_renewal_priority"
+                                v-model="agreement.renewal_priority"
+                                label="lib"
+                                :reduce="(av) => av.authorised_value"
+                                :options="av_agreement_renewal_priorities"
+                            />
                         </li>
                         <li>
                             <label for="agreement_license_info"
@@ -382,8 +347,8 @@ export default {
                     }
                 )
         },
-        onStatusChange(event) {
-            if (event.target.value != 'closed') {
+        onStatusChanged(e) {
+            if (e.authorised_value != 'closed') {
                 this.agreement.closure_reason = ''
             }
         }
index d4fa981..d4ae15f 100644 (file)
             </legend>
             <ol>
                 <li>
-                    <label :for="`agreement_id_${counter}`"
+                    <label :for="`agreement_id_${counter}`" class="required"
                         >{{ $t("Agreement") }}:
                     </label>
-                    <select
-                        v-model="package_agreement.agreement_id"
+                    <v-select
                         :id="`agreement_id_${counter}`"
-                        required
+                        v-model="package_agreement.agreement_id"
+                        label="name"
+                        :reduce="(a) => a.agreement_id"
+                        :options="agreements"
                     >
-                        <option value=""></option>
-                        <option
-                            v-for="agreement in agreements"
-                            :key="agreement.agreement_id"
-                            :value="agreement.agreement_id"
-                            :selected="
-                                agreement.agreement_id ==
-                                package_agreement.agreement_id
-                                    ? true
-                                    : false
-                            "
-                        >
-                            {{ agreement.name }}
-                        </option>
-                    </select>
+                        <template #search="{ attributes, events }">
+                            <input
+                                :required="!package_agreement.agreement_id"
+                                class="vs__search"
+                                v-bind="attributes"
+                                v-on="events"
+                            />
+                        </template>
+                    </v-select>
                     <span class="required">{{ $t("Required") }}</span>
                 </li>
             </ol>
index 514b693..1a1b743 100644 (file)
                             <label for="package_vendor_id"
                                 >{{ $t("Vendor") }}:</label
                             >
-                            <select
+                            <v-select
                                 id="package_vendor_id"
                                 v-model="erm_package.vendor_id"
-                            >
-                                <option value=""></option>
-                                <option
-                                    v-for="vendor in vendors"
-                                    :key="vendor.vendor_id"
-                                    :value="vendor.id"
-                                    :selected="
-                                        vendor.id == erm_package.vendor_id
-                                            ? true
-                                            : false
-                                    "
-                                >
-                                    {{ vendor.name }}
-                                </option>
-                            </select>
+                                label="name"
+                                :reduce="(vendor) => vendor.id"
+                                :options="vendors"
+                            />
                         </li>
                         <li>
                             <label for="package_type">{{ $t("Type") }}:</label>
-                            <select
+                            <v-select
                                 id="package_type"
                                 v-model="erm_package.package_type"
-                            >
-                                <option value=""></option>
-                                <option
-                                    v-for="type in av_package_types"
-                                    :key="type.authorised_values"
-                                    :value="type.authorised_value"
-                                    :selected="
-                                        type.authorised_value ==
-                                        erm_package.package_type
-                                            ? true
-                                            : false
-                                    "
-                                >
-                                    {{ type.lib }}
-                                </option>
-                            </select>
+                                label="lib"
+                                :reduce="(av) => av.authorised_value"
+                                :options="av_package_types"
+                            />
                         </li>
                         <li>
                             <label for="package_content_type">{{
                                 $t("Content type: ")
                             }}</label>
-                            <select
+                            <v-select
                                 id="package_content_type"
                                 v-model="erm_package.content_type"
-                            >
-                                <option value=""></option>
-                                <option
-                                    v-for="type in av_package_content_types"
-                                    :key="type.authorised_values"
-                                    :value="type.authorised_value"
-                                    :selected="
-                                        type.authorised_value ==
-                                        erm_package.content_type
-                                            ? true
-                                            : false
-                                    "
-                                >
-                                    {{ type.lib }}
-                                </option>
-                            </select>
+                                label="lib"
+                                :reduce="(av) => av.authorised_value"
+                                :options="av_package_content_types"
+                            />
                         </li>
 
                         <EHoldingsPackageAgreements
index 1a9d5ff..8d8c993 100644 (file)
                             <label for="title_publication_type"
                                 >{{ $t("Publication type") }}:</label
                             >
-                            <select
+                            <v-select
                                 id="title_publication_type"
                                 v-model="title.publication_type"
-                            >
-                                <option value=""></option>
-                                <option
-                                    v-for="type in av_title_publication_types"
-                                    :key="type.authorised_values"
-                                    :value="type.authorised_value"
-                                    :selected="
-                                        type.authorised_value ==
-                                        title.publication_type
-                                            ? true
-                                            : false
-                                    "
-                                >
-                                    {{ type.lib }}
-                                </option>
-                            </select>
+                                label="lib"
+                                :reduce="(av) => av.authorised_value"
+                                :options="av_title_publication_types"
+                            />
                         </li>
 
                         <li>
index 77a6ff4..52c1877 100644 (file)
             </legend>
             <ol>
                 <li>
-                    <label :for="`resource_id_${counter}`" class="required"
+                    <label
+                        :for="`resource_package_id_${counter}`"
+                        class="required"
                         >{{ $t("Package") }}:
                     </label>
-                    <select
+                    <!-- Parse to integer, resource.package_id is an integer, but GET /packages return package_id as string -->
+                    <v-select
+                        :id="`resource_package_id_${counter}`"
                         v-model="resource.package_id"
-                        :id="`resource_id_${counter}`"
-                        required
+                        label="name"
+                        :reduce="(p) => parseInt(p.package_id)"
+                        :options="packages"
                     >
-                        <option value=""></option>
-                        <option
-                            v-for="p in packages"
-                            :key="p.package_id"
-                            :value="p.package_id"
-                            :selected="
-                                p.package_id == resource.package_id
-                                    ? true
-                                    : false
-                            "
-                        >
-                            {{ p.name }}
-                        </option>
-                    </select>
+                        <template #search="{ attributes, events }">
+                            <input
+                                :required="!resource.package_id"
+                                class="vs__search"
+                                v-bind="attributes"
+                                v-on="events"
+                            />
+                        </template>
+                    </v-select>
                     <span class="required">{{ $t("Required") }}</span>
                 </li>
                 <li>
-                    <label for="title_vendor_id">{{ $t("Vendor") }}:</label>
-                    <select id="title_vendor_id" v-model="resource.vendor_id">
-                        <option value=""></option>
-                        <option
-                            v-for="vendor in vendors"
-                            :key="vendor.vendor_id"
-                            :value="vendor.id"
-                            :selected="
-                                vendor.id == resource.vendor_id ? true : false
-                            "
-                        >
-                            {{ vendor.name }}
-                        </option>
-                    </select>
+                    <label :for="`resource_vendor_id_${counter}`"
+                        >{{ $t("Vendor") }}:</label
+                    >
+                    <v-select
+                        :id="`resource_vendor_id_${counter}`"
+                        v-model="resource.vendor_id"
+                        label="name"
+                        :reduce="(vendor) => vendor.id"
+                        :options="vendors"
+                    />
                 </li>
 
                 <li>
index bccf63e..d01174e 100644 (file)
@@ -161,8 +161,22 @@ export default {
 };
 </script>
 
-<style scoped>
+<style src="vue-select/dist/vue-select.css"></style>
+<style>
 a.router-link-active {
     font-weight: 700;
 }
-</style>
+
+form .v-select {
+    display: inline-block;
+    background-color: white;
+    width: 30%;
+}
+
+.v-select, input:not([type=submit]):not([type=search]):not([type=button]), textarea {
+    border-color: rgba(60,60,60,0.26);
+    border-width: 1px;
+    border-radius: 4px;
+    min-width: 30%;
+}
+</style>
\ No newline at end of file
index 4dcf88c..2c8d1ff 100644 (file)
                             <label for="license_vendor_id"
                                 >{{ $t("Vendor") }}:</label
                             >
-                            <select
+                            <v-select
                                 id="license_vendor_id"
                                 v-model="license.vendor_id"
-                            >
-                                <option value=""></option>
-                                <option
-                                    v-for="vendor in vendors"
-                                    :key="vendor.vendor_id"
-                                    :value="vendor.id"
-                                    :selected="
-                                        vendor.id == license.vendor_id
-                                            ? true
-                                            : false
-                                    "
-                                >
-                                    {{ vendor.name }}
-                                </option>
-                            </select>
+                                label="name"
+                                :reduce="(vendor) => vendor.id"
+                                :options="vendors"
+                            />
                         </li>
-
                         <li>
                             <label for="license_description"
                                 >{{ $t("Description") }}:
                         </li>
                         <li>
                             <label for="license_type">{{ $t("Type") }}:</label>
-                            <select
+                            <v-select
                                 id="license_type"
                                 v-model="license.type"
-                                required
+                                label="lib"
+                                :reduce="(av) => av.authorised_value"
+                                :options="av_license_types"
                             >
-                                <option value=""></option>
-                                <option
-                                    v-for="type in av_license_types"
-                                    :key="type.authorised_values"
-                                    :value="type.authorised_value"
-                                    :selected="
-                                        type.authorised_value == license.type
-                                            ? true
-                                            : false
-                                    "
-                                >
-                                    {{ type.lib }}
-                                </option>
-                            </select>
+                                <template #search="{ attributes, events }">
+                                    <input
+                                        :required="!license.type"
+                                        class="vs__search"
+                                        v-bind="attributes"
+                                        v-on="events"
+                                    />
+                                </template>
+                            </v-select>
                             <span class="required">{{ $t("Required") }}</span>
                         </li>
                         <li>
                             <label for="license_status"
                                 >{{ $t("Status") }}:</label
                             >
-                            <select
+                            <v-select
                                 id="license_status"
                                 v-model="license.status"
-                                required
+                                :reduce="(av) => av.authorised_value"
+                                :options="av_license_statuses"
+                                label="lib"
                             >
-                                <option value=""></option>
-                                <option
-                                    v-for="status in av_license_statuses"
-                                    :key="status.authorised_values"
-                                    :value="status.authorised_value"
-                                    :selected="
-                                        status.authorised_value ==
-                                        license.status
-                                            ? true
-                                            : false
-                                    "
-                                >
-                                    {{ status.lib }}
-                                </option>
-                            </select>
+                                <template #search="{ attributes, events }">
+                                    <input
+                                        :required="!license.status"
+                                        class="vs__search"
+                                        v-bind="attributes"
+                                        v-on="events"
+                                    />
+                                </template>
+                            </v-select>
                             <span class="required">{{ $t("Required") }}</span>
                         </li>
                         <li>
index 7656bbf..21ae72e 100644 (file)
@@ -5,6 +5,7 @@ import { createPinia } from "pinia";
 import { library } from "@fortawesome/fontawesome-svg-core";
 import { faPlus, faPencil, faTrash } from "@fortawesome/free-solid-svg-icons";
 import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
+import vSelect from "vue-select";
 
 library.add(faPlus, faPencil, faTrash);
 
@@ -31,7 +32,8 @@ const app = createApp(App)
     .use(createPinia())
     .use(router)
     .use(i18n)
-    .component("font-awesome-icon", FontAwesomeIcon);
+    .component("font-awesome-icon", FontAwesomeIcon)
+    .component("v-select", vSelect);
 app.config.unwrapInjectedRef = true;
 app.mount("#erm");
 const mainStore = useMainStore();
index 395a4fa..54ebc3f 100644 (file)
@@ -38,7 +38,8 @@
     "vue": "^3.2.31",
     "vue-flatpickr-component": "^9",
     "vue-i18n": "^9.1.10",
-    "vue-router": "^4.0.14"
+    "vue-router": "^4.0.14",
+    "vue-select": "^4.0.0-beta.5"
   },
   "scripts": {
     "build": "node_modules/.bin/gulp build",