From 384c3ff26c9985a5fa82585f43bbab0f9213a0a5 Mon Sep 17 00:00:00 2001 From: Petar Hristov <hristov@itc.rwth-aachen.de> Date: Tue, 31 May 2022 09:55:26 +0200 Subject: [PATCH] Fix: Retrun objects for institutes and organizations (coscine/issues#1963) --- src/modules/user/pages/UserProfile.vue | 118 ++++++++++++------------- src/modules/user/store.ts | 4 +- src/plugins/deprecated/_custom.css | 51 ++++++----- 3 files changed, 86 insertions(+), 87 deletions(-) diff --git a/src/modules/user/pages/UserProfile.vue b/src/modules/user/pages/UserProfile.vue index 83822c24..2c6f2482 100644 --- a/src/modules/user/pages/UserProfile.vue +++ b/src/modules/user/pages/UserProfile.vue @@ -62,7 +62,9 @@ <b-form-input id="givenname" v-model="$v.form.givenname.$model" - :state="$v.form.givenname.$dirty ? !$v.form.givenname.$error : null" + :state=" + $v.form.givenname.$dirty ? !$v.form.givenname.$invalid : null + " :placeholder=" $t('page.userprofile.form.personalInformation.givenName') " @@ -81,7 +83,7 @@ <b-form-input id="surname" v-model="$v.form.surname.$model" - :state="$v.form.surname.$dirty ? !$v.form.surname.$error : null" + :state="$v.form.surname.$dirty ? !$v.form.surname.$invalid : null" :placeholder=" $t('page.userprofile.form.personalInformation.surname') " @@ -101,7 +103,9 @@ id="Email" v-model="$v.form.emailAddress.$model" :state=" - $v.form.emailAddress.$dirty ? !$v.form.emailAddress.$error : null + $v.form.emailAddress.$dirty || !form.emailAddress + ? !$v.form.emailAddress.$invalid + : null " :placeholder="$t('page.userprofile.form.personalInformation.email')" /> @@ -126,8 +130,6 @@ :options="ror" :multiple="false" :loading="loadingOrganizations" - label="displayName" - track-by="displayName" :show-labels="false" :placeholder=" $t( @@ -136,12 +138,6 @@ " @search-change="triggerFetchOptions" > - <template slot="singleLabel" slot-scope="props"> - {{ props.option.displayName }} - </template> - <template slot="option" slot-scope="props"> - {{ props.option.displayName }} - </template> <template slot="noOptions"> {{ $t( @@ -251,6 +247,7 @@ <CoscineHeadline :headline="$t('page.userprofile.form.userPreferences.header')" /> + <!-- Language --> <coscine-form-group :mandatory="true" label-for="language" @@ -263,7 +260,10 @@ <b-form-radio-group id="language" class="bv-no-focus-ring" - :checked="form.language !== undefined ? form.language.id : false" + :checked=" + form.language && form.language.id ? form.language.id : false + " + :state="form.language && form.language.id ? null : false" :options="languages" name="radios-stacked" text-field="displayName" @@ -330,38 +330,8 @@ :disabled="$v.form.$invalid || savingProfile || !$v.form.$anyDirty" @click.prevent="clickSave" > - <b-iconstack - v-if="savingProfile" - animation="spin" - aria-hidden="true" - > - <b-icon - stacked - icon="dot" - aria-hidden="true" - shift-v="4" - ></b-icon> - <b-icon - stacked - icon="dot" - aria-hidden="true" - shift-v="-4" - ></b-icon> - <b-icon - stacked - icon="dot" - aria-hidden="true" - shift-h="4" - ></b-icon> - <b-icon - stacked - icon="dot" - aria-hidden="true" - shift-h="-4" - ></b-icon> - </b-iconstack> - {{ $t("buttons.save") }}</b-button - > + {{ $t("buttons.save") }} + </b-button> </coscine-form-group> </b-form> </div> @@ -422,9 +392,15 @@ export default defineComponent({ email, required, }, - organization: {}, - institute: {}, - disciplines: {}, + organization: { + required, + }, + institute: { + required, + }, + disciplines: { + required, + }, language: { id: {}, }, @@ -469,11 +445,12 @@ export default defineComponent({ this.institutes.length > 0 ); }, - institutes(): OrganizationObject[] { + institutes(): string[] { if (this.memberOrganizations) { - return this.memberOrganizations.filter( - (organization) => organization.url?.indexOf("#") !== -1 - ); + return this.memberOrganizations + .filter((organization) => organization.url?.indexOf("#") !== -1) // If does contain "#" it's a sub level organization, otherwise top level + .map((org) => (org.displayName ? org.displayName : "")) // Extract organization display name, could contain empty strings + .filter((n) => n); // Filter out empty strings, if any;; } return []; }, @@ -493,16 +470,22 @@ export default defineComponent({ } return false; }, - organizations(): OrganizationObject[] { + organizations(): string[] { if (this.memberOrganizations) { - this.memberOrganizations.filter( - (organization) => !(organization.url?.indexOf("#") !== -1) - ); + return this.memberOrganizations + .filter((organization) => !(organization.url?.indexOf("#") !== -1)) // If does contain "#" it's a sub level organization, otherwise top level + .map((org) => (org.displayName ? org.displayName : "")) // Extract organization display name, could contain empty strings + .filter((n) => n); // Filter out empty strings, if any; } return []; }, - ror(): null | OrganizationObject[] { - return this.userStore.userProfile.organizations; + ror(): null | string[] { + const organizations = this.userStore.userProfile.organizations; + if (organizations) { + return organizations + .map((org) => (org.displayName ? org.displayName : "")) // Extract organization display name, could contain empty strings + .filter((n) => n); // Filter out empty strings, if any + } else return null; }, shibbolethConnected(): boolean { if (this.user.externalAuthenticators) { @@ -552,6 +535,9 @@ export default defineComponent({ this.$v.form.$anyDirty ) { this.savingProfile = true; + // SECTION FOR SAVING ANY EMAIL CHANGES + // SIDE EFFECT: NO OTHER FIELD CHANGE CAN BE SAVED TOGETHER WITH A CHANGE OF THE EMAIL ADDRESS + // TODO if ( this.form.emailAddress && this.form.emailAddress !== this.user.emailAddress @@ -570,22 +556,28 @@ export default defineComponent({ ).toString(), }); } - try { - await this.userStore.updateUser(this.form); - this.$v.form.$reset(); + // SECTION FOR SAVING THE REST OF THE FIELDS + const updatedUser = await this.userStore.updateUser(this.form); + if (updatedUser) { + // On Success + this.$v.form.$reset() this.notificationStore.postNotification({ title: this.$t("toast.onSave.success.title").toString(), body: this.$t("toast.onSave.success.message").toString(), }); - } catch { + } else { + this.savingProfile = false; + // On Failure this.notificationStore.postNotification({ title: this.$t("toast.onSave.failure.title").toString(), body: this.$t("toast.onSave.failure.message").toString(), variant: "danger", }); - } finally { - this.savingProfile = false; } + await Promise.all([ + this.userStore.retrieveContactChange(), + this.userStore.retrieveUser(), + ]); } }, triggerFetchOptions(search: string) { diff --git a/src/modules/user/store.ts b/src/modules/user/store.ts index 6af09e98..f4058017 100644 --- a/src/modules/user/store.ts +++ b/src/modules/user/store.ts @@ -254,13 +254,15 @@ export const useUserStore = defineStore({ } }, - async updateUser(user: UserObject) { + async updateUser(user: UserObject): Promise<boolean> { const notificationStore = useNotificationStore(); try { await UserApi.userUpdateUser(user); + return true; } catch (error) { // Handle other Status Codes notificationStore.postApiErrorNotification(error as AxiosError); + return false; } }, diff --git a/src/plugins/deprecated/_custom.css b/src/plugins/deprecated/_custom.css index 730c3b06..2b69513e 100644 --- a/src/plugins/deprecated/_custom.css +++ b/src/plugins/deprecated/_custom.css @@ -1,10 +1,10 @@ .multiselect__placeholder { - color: var(--gray) !important; + color: var(--gray); /* Value taken from bootstrap */ font-size: 1rem; /* All bellow is to center the gray placeholder vertically */ - padding: 0px !important; - margin: 0 !important; + padding: 0px; + margin: 0; position: absolute; top: 50%; -ms-transform: translateY(-50%); @@ -13,59 +13,64 @@ .multiselect__option--highlight { /* Color for when an option IS NOT selected and hovered on */ - background: var(--primary) !important; + background: var(--primary); } .multiselect__option--selected.multiselect__option--highlight, .multiselect__option--highlight:after { /* Color for when an option IS selected and hovered on */ - background: var(--primary) !important; + background: var(--primary); } .multiselect__input, .multiselect__single { - padding: 0px !important; - margin: 0px !important; + padding: 0px; + margin: 0px; /* All bellow is to center the placeholder vertically when active */ - -ms-transform: translateY(15%) !important; - transform: translateY(15%) !important; + -ms-transform: translateY(15%); + transform: translateY(15%); } .multiselect__tags { /* Values taken from bootstrap */ - padding-left: 0.75rem !important; - padding-top: 0.375rem !important; - padding-bottom: 0.375rem !important; - min-height: calc(1.5rem + 0.75rem + 2px) !important; + padding-left: 0.75rem; + padding-top: 0.375rem; + padding-bottom: 0.375rem; + min-height: calc(1.5rem + 0.75rem + 2px); + background-color: transparent; } .multiselect__tags-wrap { - margin: 0 !important; - padding: 0 !important; + margin: 0; + padding: 0; } .multiselect__tag { - background: var(--primary) !important; - color: var(--white) !important; - margin-bottom: 0px !important; - margin-right: 5px !important; + background: var(--primary); + color: var(--white); + margin-bottom: 0px; + margin-right: 5px; } .multiselect__tag-icon:after { - color: var(--secondary) !important; + color: var(--secondary); } .multiselect__spinner:before, .multiselect__spinner:after { - border-color: var(--primary) transparent transparent !important; + border-color: var(--primary) transparent transparent; } .multiselect__tag-icon:focus, .multiselect__tag-icon:hover { - background: transparent !important; + background: transparent; } .multiselect__tag-icon:focus:after, .multiselect__tag-icon:hover:after { - color: var(--white) !important; + color: var(--white); +} + +.multiselect--disabled { + border-radius: 0.25rem; } \ No newline at end of file -- GitLab