From 71aa418dc694410ce6d5d10efda18d369e9d331a Mon Sep 17 00:00:00 2001 From: Martin Artnik Date: Mon, 19 Jul 2021 12:39:18 +0200 Subject: [PATCH 1/3] Fixed UX issues in user invites modal [SCI-5898] --- .../users/settings/teams/invite_users_modal.js | 10 +++++++++- app/assets/stylesheets/shared/dropdown_selector.scss | 1 - app/assets/stylesheets/themes/scinote.scss | 11 ++++------- app/javascript/src/config/locales/messages.js | 2 +- config/locales/en.yml | 2 +- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/users/settings/teams/invite_users_modal.js b/app/assets/javascripts/users/settings/teams/invite_users_modal.js index 84764aace..163fbdef6 100644 --- a/app/assets/javascripts/users/settings/teams/invite_users_modal.js +++ b/app/assets/javascripts/users/settings/teams/invite_users_modal.js @@ -61,6 +61,14 @@ } }); + dropdownSelector.init('#role', { + noEmptyOption: true, + singleSelect: true, + closeOnSelect: true, + selectAppearance: 'simple', + disableSearch: true + }); + modal.off('show.bs.modal').on('show.bs.modal', function() { // This cannot be scoped outside this function // because it is generated via JS @@ -121,7 +129,7 @@ var data = { emails: dropdownSelector.getValues(emailsInput), team_ids: dropdownSelector.getValues(teamsInput), - role: roleInput.val(), + role: dropdownSelector.getValues(roleInput), 'g-recaptcha-response': $('#recaptcha-invite-modal').val() }; diff --git a/app/assets/stylesheets/shared/dropdown_selector.scss b/app/assets/stylesheets/shared/dropdown_selector.scss index 060a3805e..31fda90b6 100644 --- a/app/assets/stylesheets/shared/dropdown_selector.scss +++ b/app/assets/stylesheets/shared/dropdown_selector.scss @@ -18,7 +18,6 @@ .dropdown-selector-container { display: inline-block; - float: left; position: relative; width: 100%; diff --git a/app/assets/stylesheets/themes/scinote.scss b/app/assets/stylesheets/themes/scinote.scss index c7c635a00..d5cc796ab 100644 --- a/app/assets/stylesheets/themes/scinote.scss +++ b/app/assets/stylesheets/themes/scinote.scss @@ -133,6 +133,10 @@ body { } } +.modal-header h4 { + font-size: 18px; +} + .jumbotron { background-color: inherit; } @@ -1349,14 +1353,7 @@ body > .loading-overlay { margin-top: 20px; } - h4 { - font-size: 14px; - margin-bottom: 5px; - } - .select-container--with-blank { - overflow: hidden; - .search-field::placeholder { color: $color-black; opacity: 1; diff --git a/app/javascript/src/config/locales/messages.js b/app/javascript/src/config/locales/messages.js index bef33aaef..aa3aad2ce 100644 --- a/app/javascript/src/config/locales/messages.js +++ b/app/javascript/src/config/locales/messages.js @@ -44,7 +44,7 @@ export default { info_label: "Info" }, invite_users: { - modal_title: "Invite users to team {team}", + modal_title: "Invite members to {team}", input_text: "Invite more people to team {team} and start using SciNote.", input_help: "Input one or multiple emails, confirm each email with ENTER key.", diff --git a/config/locales/en.yml b/config/locales/en.yml index 48f1e799f..cef639afc 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2204,7 +2204,7 @@ en: invite_users: to_team: - title: "Invite users to team %{team}" + title: "Invite members to %{team}" heading: "Invite more people to team %{team} and start using SciNote." no_team: title: "Invite users to SciNote" From f55761a4918d78b6293a7b01b519e17c8e49154d Mon Sep 17 00:00:00 2001 From: Martin Artnik Date: Mon, 19 Jul 2021 15:42:26 +0200 Subject: [PATCH 2/3] Invite member search design fixes [SCI-5892] --- .../javascripts/sitewide/dropdown_selector.js | 55 +++++++++++-------- app/assets/stylesheets/projects.scss | 10 ++-- app/assets/stylesheets/settings/teams.scss | 9 +-- .../stylesheets/shared/dropdown_selector.scss | 8 ++- 4 files changed, 49 insertions(+), 33 deletions(-) diff --git a/app/assets/javascripts/sitewide/dropdown_selector.js b/app/assets/javascripts/sitewide/dropdown_selector.js index 51cac3ab1..6c470fa6c 100644 --- a/app/assets/javascripts/sitewide/dropdown_selector.js +++ b/app/assets/javascripts/sitewide/dropdown_selector.js @@ -77,13 +77,13 @@ var dropdownSelector = (function() { if ((modalContainerBottom + bottomSpace) < bottomTreshold) { container.addClass('inverse'); - container.find('.dropdown-container').css('max-height', `${(containerPosition - 122 + maxHeight)}px`) + container.find('.dropdown-container') .css('margin-bottom', `${(containerPosition * -1)}px`) .css('left', `${containerPositionLeft}px`) .css('width', `${containerWidth}px`); } else { container.removeClass('inverse'); - container.find('.dropdown-container').css('max-height', `${(bottomSpace - 32 + maxHeight)}px`) + container.find('.dropdown-container') .css('width', `${containerWidth}px`) .css('left', `${containerPositionLeft}px`) .css('margin-top', `${(bottomSpace * -1)}px`); @@ -254,8 +254,8 @@ var dropdownSelector = (function() { updateTags(selector, container, { select: true }); } - // intialization keyboard control - function initKeyboardControl(container) { + // initialize keyboard control + function initKeyboardControl(selector, container) { container.find('.search-field').keydown(function(e) { var dropdownContainer = container.find('.dropdown-container'); var pressedKey = e.keyCode; @@ -265,20 +265,22 @@ var dropdownSelector = (function() { dropdownContainer.find('.dropdown-option').first().addClass('highlight'); } - if (pressedKey === 38) { + if (pressedKey === 38) { // arrow up if (selectedOption.prev('.dropdown-option').length) { selectedOption.removeClass('highlight').prev().addClass('highlight'); } if (selectedOption.prev('.delimiter').length) { selectedOption.removeClass('highlight').prev().prev().addClass('highlight'); } - } else if (pressedKey === 40) { + } else if (pressedKey === 40) { // arrow down if (selectedOption.next('.dropdown-option').length) { selectedOption.removeClass('highlight').next().addClass('highlight'); } if (selectedOption.next('.delimiter').length) { selectedOption.removeClass('highlight').next().next().addClass('highlight'); } + } else if (pressedKey === 8 && e.target.value === '') { // backspace + deleteTag(selector, container, container.find('.ds-tags .fa-times').last()); } }); } @@ -485,10 +487,10 @@ var dropdownSelector = (function() { dropdownContainer.addClass('disable-search'); } - // initialization keyboard controll - initKeyboardControl(dropdownContainer); + // initialization keyboard control + initKeyboardControl(selector, dropdownContainer); - // In some case dropdown position not correclty calculated + // In some case dropdown position not correctly calculated updateDropdownDirection(selectElement, dropdownContainer); } @@ -663,6 +665,25 @@ var dropdownSelector = (function() { updateTags(selector, container, { select: true }); } + function deleteTag(selector, container, target) { + var tagLabel = target.prev(); + + // Start delete animation + target.parent().addClass('closing'); + + // Add timeout for deleting animation + setTimeout(() => { + if (selector.data('combine-tags')) { + // if we use combine-tags options we simply clear all values + container.find('.data-field').val('[]'); + updateTags(selector, container); + } else { + // Or delete specific one + deleteValue(selector, container, tagLabel.data('ds-tag-id'), tagLabel.data('ds-tag-group')); + } + }, 350); + } + // Refresh tags in input field function updateTags(selector, container, config = {}) { var selectedOptions = getCurrentData(container); @@ -696,22 +717,8 @@ var dropdownSelector = (function() { // Now we need add delete action to tag tag.find('.fa-times').click(function(e) { - var tagLabel = $(this).prev(); - var toDelete; e.stopPropagation(); - // Start delete animation - $(this).parent().addClass('closing'); - // Add timeout for deleting animation - setTimeout(() => { - if (selector.data('combine-tags')) { - // if we use combine-tags optons we simply clear all values - container.find('.data-field').val('[]'); - updateTags(selector, container); - } else { - // Or delete specific one - deleteValue(selector, container, tagLabel.data('ds-tag-id'), tagLabel.data('ds-tag-group')); - } - }, 350); + deleteTag(selector, container, $(this)); }); } diff --git a/app/assets/stylesheets/projects.scss b/app/assets/stylesheets/projects.scss index 9648f569f..93ffbb266 100644 --- a/app/assets/stylesheets/projects.scss +++ b/app/assets/stylesheets/projects.scss @@ -514,12 +514,14 @@ li.module-hover { } } - .users-dropdown-list { + .dropdown-option.users-dropdown-list { + padding: 8px 10px; + .item-avatar { border-radius: 50%; - height: 20px; - margin: 0 .5em 0 0; - width: 20px; + height: 32px; + margin: 0 16px 0 0; + width: 32px; } } } diff --git a/app/assets/stylesheets/settings/teams.scss b/app/assets/stylesheets/settings/teams.scss index b62739149..3f610a944 100644 --- a/app/assets/stylesheets/settings/teams.scss +++ b/app/assets/stylesheets/settings/teams.scss @@ -189,14 +189,15 @@ } } - .users-dropdown-list { + .dropdown-option.users-dropdown-list { border-top: 1px solid $color-gainsboro; + padding: 8px 10px; .item-avatar { border-radius: 50%; - height: 20px; - margin: 0 .5em 0 0; - width: 20px; + height: 32px; + margin: 0 16px 0 0; + width: 32px; } .item-email { diff --git a/app/assets/stylesheets/shared/dropdown_selector.scss b/app/assets/stylesheets/shared/dropdown_selector.scss index 31fda90b6..6acc4a19c 100644 --- a/app/assets/stylesheets/shared/dropdown_selector.scss +++ b/app/assets/stylesheets/shared/dropdown_selector.scss @@ -103,7 +103,6 @@ .tag-label { display: inline-block; margin-right: 5px; - margin-top: 1px; max-width: 240px; overflow: hidden; text-align: left; @@ -114,6 +113,12 @@ &[data-ds-tag-id=""] { opacity: .7; } + + .item-avatar { + height: 16px; + margin-right: 8px; + width: 16px; + } } .fas { @@ -134,6 +139,7 @@ bottom: calc(100% - 30px); box-shadow: $flyout-shadow; display: none; + max-height: 320px; overflow: hidden; position: fixed; transition: .2s; From d54a743e64ec8038a6d5634c55a73d828fcc5212 Mon Sep 17 00:00:00 2001 From: Martin Artnik Date: Thu, 22 Jul 2021 09:37:25 +0200 Subject: [PATCH 3/3] Fixed handling of dropdown-selector max height [SCI-5898] --- app/assets/javascripts/sitewide/dropdown_selector.js | 8 ++++++-- app/assets/stylesheets/shared/dropdown_selector.scss | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/sitewide/dropdown_selector.js b/app/assets/javascripts/sitewide/dropdown_selector.js index 6c470fa6c..17e937d30 100644 --- a/app/assets/javascripts/sitewide/dropdown_selector.js +++ b/app/assets/javascripts/sitewide/dropdown_selector.js @@ -48,10 +48,12 @@ */ + var dropdownSelector = (function() { // ///////////////////// // Support functions // // //////////////////// + const MAX_DROPDOWN_HEIGHT = 320; // Change direction of dropdown depends of container position function updateDropdownDirection(selector, container) { @@ -77,13 +79,15 @@ var dropdownSelector = (function() { if ((modalContainerBottom + bottomSpace) < bottomTreshold) { container.addClass('inverse'); - container.find('.dropdown-container') + maxHeight = Math.min(containerPosition - 122 + maxHeight, MAX_DROPDOWN_HEIGHT); + container.find('.dropdown-container').css('max-height', `${maxHeight}px`) .css('margin-bottom', `${(containerPosition * -1)}px`) .css('left', `${containerPositionLeft}px`) .css('width', `${containerWidth}px`); } else { container.removeClass('inverse'); - container.find('.dropdown-container') + maxHeight = Math.min(bottomSpace - 32 + maxHeight, MAX_DROPDOWN_HEIGHT); + container.find('.dropdown-container').css('max-height', `${maxHeight}px`) .css('width', `${containerWidth}px`) .css('left', `${containerPositionLeft}px`) .css('margin-top', `${(bottomSpace * -1)}px`); diff --git a/app/assets/stylesheets/shared/dropdown_selector.scss b/app/assets/stylesheets/shared/dropdown_selector.scss index 6acc4a19c..2f3d1aee2 100644 --- a/app/assets/stylesheets/shared/dropdown_selector.scss +++ b/app/assets/stylesheets/shared/dropdown_selector.scss @@ -139,7 +139,6 @@ bottom: calc(100% - 30px); box-shadow: $flyout-shadow; display: none; - max-height: 320px; overflow: hidden; position: fixed; transition: .2s;