From 62ab9dbb984a45f2e145530b076ba3808c4a4b51 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Thu, 21 Jun 2018 17:18:01 +0100 Subject: [PATCH] Rearrange layout to have the new affiliation form within the affiliations table. --- services/web/app/views/user/settings.pug | 276 ++++++++++-------- .../UserAffiliationsController.coffee | 68 +++-- .../UserAffiliationsDataService.coffee | 14 + .../stylesheets/app/account-settings.less | 48 +-- 4 files changed, 221 insertions(+), 185 deletions(-) diff --git a/services/web/app/views/user/settings.pug b/services/web/app/views/user/settings.pug index 100c6fd293..15bab80385 100644 --- a/services/web/app/views/user/settings.pug +++ b/services/web/app/views/user/settings.pug @@ -14,6 +14,156 @@ block content | #{translate("thanks_settings_updated")} form-messages(for="changePasswordForm") .container-fluid + form.row( + ng-controller="UserAffiliationsController" + name="affiliationsForm" + ) + .col-md-12 + h3 Emails and Affiliations + p.small Add additional email addresses to your account to access any upgrades your university or institution has, to make it easier for collaborators to find you, and to make sure you can recover your account. + + table.table.affiliations-table + thead + tr + th.affiliations-table-email Email + th.affiliations-table-institution Institution and role + th.affiliations-table-inline-actions + tbody + tr( + ng-repeat="userEmail in userEmails" + ) + td {{ userEmail.email + (userEmail.default ? ' (default)' : '') }} + td {{ userEmail.institution }} + td + a( + href + ng-if="!userEmail.default" + ng-click="setDefaultUserEmail(userEmail.email)" + ) Make default + br + a( + href + ng-if="!userEmail.default" + ng-click="removeUserEmail(userEmail.email)" + ) Remove + tr( + ng-if="ui.isLoadingEmails" + ) + td.text-center(colspan="3") + i.fa.fa-fw.fa-spin.fa-refresh + |  Loading... + + tr( + ng-if="!ui.showAddEmailUI && !ui.isLoadingEmails" + ) + td(colspan="3") + a( + href + ng-click="showAddEmailForm()" + ) Add new email + + tr( + ng-if="ui.showAddEmailUI" + ) + td + p + input-suggestions( + ng-model="newAffiliation.email" + ng-model-options="{ allowInvalid: true }" + get-suggestion="getEmailSuggestion(userInput)" + on-blur="handleEmailInputBlur()" + input-id="affilitations-email" + input-name="affilitationsEmail" + input-placeholder="e.g. johndoe@mit.edu" + input-type="email" + input-required="true" + ) + td + p( + ng-if="newAffiliation.university && !ui.showManualUniversitySelectionUI" + ) + | {{ newAffiliation.university.name }} ( + a( + href + ng-click="selectUniversityManually();" + ) change + | ) + p( + ng-if="!newAffiliation.university && !ui.isValidEmail && !ui.showManualUniversitySelectionUI" + ) Start by adding your email address. + p( + ng-if="!newAffiliation.university && ui.isValidEmail && !ui.isBlacklistedEmail && !ui.showManualUniversitySelectionUI" + ) + | Is your email affiliated with an institution? + br + a( + href + ng-click="selectUniversityManually();" + ) Let us know + div( + ng-if="ui.showManualUniversitySelectionUI" + ) + p + ui-select( + ng-model="newAffiliation.country" + ) + ui-select-match( + placeholder="Select your country" + ) {{ $select.selected.name }} + ui-select-choices( + repeat="country in countries | filter: $select.search" + ) + span( + ng-bind="country.name" + ) + p + ui-select( + ng-model="newAffiliation.university" + ng-disabled="!newAffiliation.country" + tagging="addUniversityToSelection" + tagging-label="false" + ) + ui-select-match( + placeholder="Select your university" + ) {{ $select.selected.name }} + ui-select-choices( + repeat="university in universities | filter: $select.search" + ) + span( + ng-bind="university.name" + ) + div( + ng-if="ui.isValidEmail && newAffiliation.university" + ) + p + input.form-control( + type="text" + id="affiliations-role" + placeholder="Role" + ng-model="newAffiliation.role" + ) + p + input.form-control( + type="text" + id="affiliations-department" + placeholder="Department" + ng-model="newAffiliation.department" + ) + td + button.btn.btn-primary( + ng-disabled="affiliationsForm.$invalid || ui.isAddingNewEmail" + ng-click="addNewEmail()" + ) + span( + ng-if="!ui.isAddingNewEmail" + ) Add new email + span( + ng-if="ui.isAddingNewEmail" + ) + i.fa.fa-fw.fa-spin.fa-refresh + |  Adding... + hr + .row .col-md-5 h3 #{translate("update_account_info")} @@ -116,131 +266,7 @@ block content ng-disabled="changePasswordForm.$invalid" ) #{translate("change")} - hr - form( - ng-controller="UserAffiliationsController" - novalidate - name="affiliationsForm" - ) - h3 Emails and affiliations - p Do you use multiple e-mail addresses? If so, add those here. - ul - li You'll retain access to your account even if you lose access to one of your emails - li Others users will be able to find you under different email addresses when sharing projects - li If your e-mail is affiliated with an institution with a group license, your account will be associated with that institution (and you'll gain acess to any benefits the institution may have). - - .affiliations-row - .affiliation-col-4 - label(for="affiliations-email") #{translate("email")} - input-suggestions( - ng-model="newAffiliation.email" - ng-model-options="{ allowInvalid: true }" - get-suggestion="getEmailSuggestion(userInput)" - on-blur="handleEmailInputBlur()" - input-id="affilitations-email" - input-name="affilitationsEmail" - input-placeholder="e.g. johndoe@mit.edu" - input-type="email" - input-required="true" - ) - .affiliation-col-8 - p.affiliation-input-feedback( - ng-if="newAffiliation.university && !showManualUniversitySelectionUI" - ) - | {{ newAffiliation.university.name }} ( - a( - href - ng-click="selectUniversityManually();" - ) change - | ) - p.affiliation-input-feedback( - ng-if="!newAffiliation.university && !isValidEmail && !showManualUniversitySelectionUI" - ) Start by adding your email address. - p.affiliation-input-feedback( - ng-if="!newAffiliation.university && isValidEmail && !isBlacklistedEmail && !showManualUniversitySelectionUI" - ) - | Is your email affiliated with an institution? - a( - href - ng-click="selectUniversityManually();" - ) Let us know - .affiliations-row( - ng-if="isValidEmail && showManualUniversitySelectionUI" - ) - .affiliation-col-4 - label Institution - ui-select( - ng-model="newAffiliation.country" - ) - ui-select-match( - placeholder="Select your country" - ) {{ $select.selected.name }} - ui-select-choices( - repeat="country in countries | filter: $select.search" - ) - span( - ng-bind="country.name" - ) - .affiliation-col-4 - ui-select( - ng-model="newAffiliation.university" - ng-disabled="!newAffiliation.country" - tagging="addUniversityToSelection" - tagging-label="false" - ) - ui-select-match( - placeholder="Select your university" - ) {{ $select.selected.name }} - ui-select-choices( - repeat="university in universities | filter: $select.search" - ) - span( - ng-bind="university.name" - ) - .affiliations-row( - ng-if="isValidEmail && newAffiliation.university" - ) - .affiliation-col-4 - label(for="affiliations-role") Role - input.form-control( - type="text" - id="affiliations-role" - placeholder="e.g. Professor" - ng-model="newAffiliation.role" - ) - .affiliation-col-4 - label(for="affiliations-department") Department - input.form-control( - type="text" - id="affiliations-department" - placeholder="e.g. Mathematics" - ng-model="newAffiliation.department" - ) - .affiliations-row - .affiliation-col-4 - input.btn.btn-primary( - type="submit" - ng-disabled="affiliationsForm.$invalid" - ng-click="handleAffiliationFormSubmit()" - value="Add new email" - ) - - //- p Your current affiliations - - table.table - thead - tr - th Email - th Institution and role - th - tbody - tr( - ng-repeat="userEmail in userEmails" - ) - td {{ userEmail.email + (userEmail.default ? ' (default)' : '') }} - td {{ userEmail.institution }} - td Remove - + | !{moduleIncludes("userSettings", locals)} diff --git a/services/web/public/coffee/main/affiliations/controllers/UserAffiliationsController.coffee b/services/web/public/coffee/main/affiliations/controllers/UserAffiliationsController.coffee index 8e7caa6727..7fcfaa6360 100644 --- a/services/web/public/coffee/main/affiliations/controllers/UserAffiliationsController.coffee +++ b/services/web/public/coffee/main/affiliations/controllers/UserAffiliationsController.coffee @@ -5,18 +5,9 @@ define [ $scope.userEmails = [] $scope.countries = [] $scope.universities = [] - $scope.newAffiliation = - email: "" - country: null - university: null - role: null - department: null - $scope.showManualUniversitySelectionUI = false - $scope.isValidEmail = false - $scope.isBlacklistedEmail = false LOCAL_AND_DOMAIN_REGEX = /([^@]+)@(.+)/ - EMAIL_REGEX = /^([A-Za-z0-9_\-\.]+)@([^\.]+)\.([A-Za-z]+)$/ + EMAIL_REGEX = /^([A-Za-z0-9_\-\.]+)@([^\.]+)\.([A-Za-z0-9_\-\.]+)([^\.])$/ _matchLocalAndDomain = (userEmailInput) -> match = userEmailInput?.match LOCAL_AND_DOMAIN_REGEX @@ -30,14 +21,14 @@ define [ $scope.getEmailSuggestion = (userInput) -> userInputLocalAndDomain = _matchLocalAndDomain(userInput) - $scope.isValidEmail = EMAIL_REGEX.test userInput   - $scope.isBlacklistedEmail = false + $scope.ui.isValidEmail = EMAIL_REGEX.test userInput + $scope.ui.isBlacklistedEmail = false + $scope.ui.showManualUniversitySelectionUI = false if userInputLocalAndDomain.domain? - $scope.isBlacklistedEmail = UserAffiliationsDataService.isDomainBlacklisted userInputLocalAndDomain.domain + $scope.ui.isBlacklistedEmail = UserAffiliationsDataService.isDomainBlacklisted userInputLocalAndDomain.domain UserAffiliationsDataService.getUniversityDomainFromPartialDomainInput(userInputLocalAndDomain.domain) .then (universityDomain) -> - $scope.showManualUniversitySelectionUI = false if userInputLocalAndDomain.domain == universityDomain.hostname $scope.newAffiliation.university = universityDomain.university $scope.newAffiliation.department = universityDomain.department @@ -61,9 +52,13 @@ define [ $scope.selectUniversityManually = () -> $scope.newAffiliation.university = null $scope.newAffiliation.department = null - $scope.showManualUniversitySelectionUI = true + $scope.ui.showManualUniversitySelectionUI = true - $scope.handleAffiliationFormSubmit = () -> + $scope.showAddEmailForm = () -> + $scope.ui.showAddEmailUI = true + + $scope.addNewEmail = () -> + $scope.ui.isAddingNewEmail = true if !$scope.newAffiliation.university? addEmailPromise = UserAffiliationsDataService .addUserEmail $scope.newAffiliation.email @@ -85,14 +80,45 @@ define [ $scope.newAffiliation.role, $scope.newAffiliation.department ) - addEmailPromise.then () -> getUserEmails() - + addEmailPromise.then () -> + _reset() + _getUserEmails() + + $scope.setDefaultUserEmail = (email) -> + UserAffiliationsDataService + .setDefaultUserEmail email + .then () -> _getUserEmails() + + $scope.removeUserEmail = (email) -> + UserAffiliationsDataService + .removeUserEmail email + .then () -> _getUserEmails() + + _reset = () -> + $scope.newAffiliation = + email: "" + country: null + university: null + role: null + department: null + $scope.ui = + showManualUniversitySelectionUI: false + isLoadingEmails: false + isAddingNewEmail: false + showAddEmailUI: false + isValidEmail: false + isBlacklistedEmail: false + _reset() + # Populates the emails table - getUserEmails = () -> + _getUserEmails = () -> + $scope.ui.isLoadingEmails = true UserAffiliationsDataService .getUserEmails() - .then (emails) -> $scope.userEmails = emails - getUserEmails() + .then (emails) -> + $scope.userEmails = emails + $scope.ui.isLoadingEmails = false + _getUserEmails() # Populates the countries dropdown UserAffiliationsDataService diff --git a/services/web/public/coffee/main/affiliations/factories/UserAffiliationsDataService.coffee b/services/web/public/coffee/main/affiliations/factories/UserAffiliationsDataService.coffee index e344909792..563687e3d9 100644 --- a/services/web/public/coffee/main/affiliations/factories/UserAffiliationsDataService.coffee +++ b/services/web/public/coffee/main/affiliations/factories/UserAffiliationsDataService.coffee @@ -72,6 +72,18 @@ define [ _csrf: window.csrfToken } + setDefaultUserEmail = (email) -> + $http.post "/user/emails/default", { + email, + _csrf: window.csrfToken + } + + removeUserEmail = (email) -> + $http.delete "/user/emails/#{ encodeURIComponent(email) }", { + headers: + "X-CSRF-Token": window.csrfToken + } + isDomainBlacklisted = (domain) -> domain.toLowerCase() of domainsBlackList @@ -83,6 +95,8 @@ define [ addUserEmail addUserAffiliationWithUnknownUniversity addUserAffiliation + setDefaultUserEmail + removeUserEmail isDomainBlacklisted } ] \ No newline at end of file diff --git a/services/web/public/stylesheets/app/account-settings.less b/services/web/public/stylesheets/app/account-settings.less index 95f92aa97a..1cd57d3291 100644 --- a/services/web/public/stylesheets/app/account-settings.less +++ b/services/web/public/stylesheets/app/account-settings.less @@ -11,46 +11,16 @@ } } - -.affiliations-row { - display: flex; - margin-left: -(@grid-gutter-width / 2); - margin-right: -(@grid-gutter-width / 2); - @media (min-width: @screen-sm-min) { - align-items: flex-end; - } +.affiliations-table { + table-layout: fixed; } - .affiliation-col-4, - .affiliation-col-8 { - width: 100%; - flex-grow: 0; - flex-shrink: 0; - padding-left: (@grid-gutter-width / 2); - padding-right: (@grid-gutter-width / 2); - margin-bottom: (@grid-gutter-width / 2); + .affiliations-table-email { + width: 40%; } - - .affiliation-col-4 { - @media (min-width: @screen-sm-min) { - width: (4 / 12) * 100%; - } + .affiliations-table-institution { + width: 40%; } - - .affiliation-col-8 { - @media (min-width: @screen-sm-min) { - width: (8 / 12) * 100%; - } + .affiliations-table-inline-actions { + width: 20%; } - - .affiliation-col-align-right { - @media (min-width: @screen-sm-min) { - display: flex; - justify-content: flex-end; - } - } - - .affiliation-input-feedback { - height: @input-height-base; - padding: @padding-base-vertical; - margin: 0; - } \ No newline at end of file + \ No newline at end of file