diff --git a/app/assets/javascripts/darkswarm/directives/auth.js.coffee b/app/assets/javascripts/darkswarm/directives/auth.js.coffee deleted file mode 100644 index aaa8be0def..0000000000 --- a/app/assets/javascripts/darkswarm/directives/auth.js.coffee +++ /dev/null @@ -1,11 +0,0 @@ -angular.module('Darkswarm').directive 'auth', (AuthenticationService) -> - restrict: 'A' - link: (scope, elem, attrs) -> - elem.bind "click", -> - AuthenticationService.open '/' + attrs.auth - - window.addEventListener "login:modal:open", -> - AuthenticationService.open '/login' - - scope.$on "$destroy", -> - window.removeEventListener "login:modal:open" diff --git a/app/views/layouts/_alert.html.haml b/app/views/layouts/_alert.html.haml new file mode 100644 index 0000000000..539031e1fd --- /dev/null +++ b/app/views/layouts/_alert.html.haml @@ -0,0 +1,5 @@ +.alert-box{ class: "#{type}" } + = message + - if local_assigns[:unconfirmed] + %a{ "data-action": "login-modal#resend_confirmation" } + = t('devise.confirmations.resend_confirmation_email') \ No newline at end of file diff --git a/app/views/layouts/_forgot_tab.html.haml b/app/views/layouts/_forgot_tab.html.haml new file mode 100644 index 0000000000..47ad3c03d2 --- /dev/null +++ b/app/views/layouts/_forgot_tab.html.haml @@ -0,0 +1,12 @@ +#forgot-tab + = form_with url: spree_user_password_path, scope: :spree_user, data: { remote: "true" } do |form| + .row + .large-12.columns#forgot-feedback + + .row + .large-12.columns + = form.label :email, t(:signup_email) + = form.email_field :email, { tabindex: 1, inputmode: "email", "data-login-modal-target": "email", "data-action": "input->login-modal#emailOnInput" } + .row + .large-12.columns + = form.submit t(:reset_password), { class: "button primary", tabindex: 2 } diff --git a/app/views/layouts/_login_modal.html.haml b/app/views/layouts/_login_modal.html.haml new file mode 100644 index 0000000000..b5fda75568 --- /dev/null +++ b/app/views/layouts/_login_modal.html.haml @@ -0,0 +1,24 @@ +%div{"data-controller": "login-modal" } + .reveal-modal-bg.fade{ "data-login-modal-target": "background", "data-action": "click->login-modal#close" } + + .reveal-modal.fade.login-modal.medium{ "data-login-modal-target": "modal" } + %div{ "data-controller": "tabs" } + %dl.tabs + %dd + %a{ data: { "tabs-target": "tab", "action": "tabs#select" } }= t(:label_login) + %dd + %a{ data: { "tabs-target": "tab", "action": "tabs#select" } }= t(:label_signup) + %dd + %a{ data: { "tabs-target": "tab", "action": "tabs#select" } }= t(:forgot_password) + + .tabs-content + .content.active + %div{ data: { "tabs-target": "content" } } + = render "layouts/login_tab" + %div{ data: { "tabs-target": "content" } } + = render "layouts/signup_tab" + %div{ data: { "tabs-target": "content" } } + = render "layouts/forgot_tab" + + %a.close-reveal-modal{ "data-action": "click->login-modal#close" } + %i.ofn-i_009-close diff --git a/app/views/layouts/_login_tab.html.haml b/app/views/layouts/_login_tab.html.haml new file mode 100644 index 0000000000..06a09b1d85 --- /dev/null +++ b/app/views/layouts/_login_tab.html.haml @@ -0,0 +1,24 @@ +#login-content + = form_with url: spree.spree_user_session_path, scope: :spree_user, data: { remote: "true" } do |form| + .row + .large-12.columns#login-feedback + - confirmation_result = request.query_parameters[:validation] + - if confirmation_result.in? ["confirmed", "not_confirmed"] + .alert-box{ class: "#{confirmation_result == "confirmed" ? "success" : "alert" }" } + = t("devise.confirmations.#{confirmation_result}") + + .row + .large-12.columns + = form.label :email, t(:email) + = form.email_field :email, { tabindex: 1, inputmode: "email", autocomplete: "off", "data-login-modal-target": "email", "data-action": "input->login-modal#emailOnInput" } + .row + .large-12.columns + = form.label :password, t(:password) + = form.password_field :password, { tabindex: 2, inputmode: "password" } + .row + .large-12.columns + = form.check_box :remember_me, { tabindex: 3 } + = form.label :remember_me, t(:remember_me) + .row + .large-12.columns + = form.submit t(:label_login), { class: "button primary", tabindex: 4 } diff --git a/app/views/layouts/_signup_tab.html.haml b/app/views/layouts/_signup_tab.html.haml new file mode 100644 index 0000000000..5d2af646e5 --- /dev/null +++ b/app/views/layouts/_signup_tab.html.haml @@ -0,0 +1,25 @@ +- signup_form_user = Spree::User.new if local_assigns[:signup_form_user].nil? + +#signup-tab + = form_with model: signup_form_user, url: spree.account_path, scope: :user, data: { remote: "true" } do |form| + .row + .large-12.columns#signup-feedback + + .row + .large-12.columns + = form.label :email, t(:signup_email) + = form.email_field :email, { tabindex: 1, "data-login-modal-target": "email", "data-action": "input->login-modal#emailOnInput" } + = form.error_message_on :email + .row + .large-12.columns + = form.label :password, t(:choose_password) + = form.password_field :password, { tabindex: 2, autocomplete: "off" } + = form.error_message_on :password + .row + .large-12.columns + = form.label :password_confirmation, t(:confirm_password) + = form.password_field :password_confirmation, { tabindex: 3, autocomplete: "off" } + = form.error_message_on :password_confirmation + .row + .large-12.columns + = form.submit t(:action_signup), { class: "button primary", tabindex: 4 } diff --git a/app/views/layouts/darkswarm.html.haml b/app/views/layouts/darkswarm.html.haml index fedbcdddfc..23a0aeda5e 100644 --- a/app/views/layouts/darkswarm.html.haml +++ b/app/views/layouts/darkswarm.html.haml @@ -57,3 +57,5 @@ = yield :injection_data = render "layouts/matomo_tag" + + = render "layouts/login_modal" diff --git a/app/webpacker/controllers/login_modal_controller.js b/app/webpacker/controllers/login_modal_controller.js index 34ca4b92ab..ab0643e48d 100644 --- a/app/webpacker/controllers/login_modal_controller.js +++ b/app/webpacker/controllers/login_modal_controller.js @@ -1,8 +1,74 @@ import { Controller } from "stimulus" +import CableReady from "cable_ready" export default class extends Controller { + static targets = ["background", "modal", "email"] + static values = { email: String } + + connect() { + if(this.hasModalTarget) { + window.addEventListener("login:modal:open", this.open) + + if(location.hash.substr(1).includes("/login")) { + this.open() + } + } + } + call(event) { event.preventDefault() window.dispatchEvent(new Event("login:modal:open")) } + + emailOnInput(event) { + this.emailValue = event.currentTarget.value + this.emailTargets.forEach((element) => { + element.value = this.emailValue + }) + } + + open = () => { + if(!location.hash.substr(1).includes("/login")) { + history.pushState({}, "", "#/login") + } + + this.backgroundTarget.style.display = "block" + this.modalTarget.style.display = "block" + + document.querySelector("body").classList.add("modal-open") + + setTimeout(() => { + this.modalTarget.classList.add("in") + this.backgroundTarget.classList.add("in") + }) + } + + close() { + history.pushState({}, "", window.location.pathname + window.location.search) + + this.modalTarget.classList.remove("in") + this.backgroundTarget.classList.remove("in") + + document.querySelector("body").classList.remove("modal-open") + + setTimeout(() => { + this.backgroundTarget.style.display = "none" + this.modalTarget.style.display = "none" + }, 200) + } + + resend_confirmation() { + fetch("/user/spree_user/confirmation", { + method: "POST", + body: JSON.stringify({ + spree_user: { email: this.emailValue } + }) + }).then(data => data.json()).then(CableReady.perform) + } + + disconnect() { + if(this.hasModalTarget) { + window.removeEventListener("login:modal:open", this.open) + } + } } diff --git a/app/webpacker/controllers/tabs_controller.js b/app/webpacker/controllers/tabs_controller.js new file mode 100644 index 0000000000..46f6935c57 --- /dev/null +++ b/app/webpacker/controllers/tabs_controller.js @@ -0,0 +1,27 @@ +import { Controller } from "stimulus"; + +export default class extends Controller { + static targets = ["tab", "content"] + + connect() { + this.setCurrentTab() + } + + select(event) { + this.setCurrentTab(this.tabTargets.indexOf(event.currentTarget)) + } + + setCurrentTab(tabIndex = 0) { + this.contentTargets.forEach((element, index) => { + element.hidden = index !== tabIndex + }) + + this.tabTargets.forEach((element, index) => { + if(index === tabIndex) { + element.classList.add("active") + } else { + element.classList.remove("active") + } + }) + } +} diff --git a/app/webpacker/css/darkswarm/pages/login_modal.scss b/app/webpacker/css/darkswarm/pages/login_modal.scss index 98ee4730c7..b72763eb13 100644 --- a/app/webpacker/css/darkswarm/pages/login_modal.scss +++ b/app/webpacker/css/darkswarm/pages/login_modal.scss @@ -5,6 +5,21 @@ .login-modal { background: $modal-background-color; + visibility: visible; + position: fixed; + top: 3em; + + a.active { + background-color: white; + + &:hover { + background-color: white; + } + } + + span.formError { + @extend .error; + } .tabs-content { background: $modal-content-background-color; diff --git a/spec/support/request/ui_component_helper.rb b/spec/support/request/ui_component_helper.rb index b48cfe16e0..f6bf0e41b2 100644 --- a/spec/support/request/ui_component_helper.rb +++ b/spec/support/request/ui_component_helper.rb @@ -111,8 +111,8 @@ module UIComponentHelper end def fill_in_using_keyboard - page.find('#email').send_keys(user.email, :tab, user.password, :tab, :space) - expect(page.find('#remember_me')).to be_checked - page.find('#remember_me').send_keys(:tab, :enter) + page.find('#spree_user_email').send_keys(user.email, :tab, user.password, :tab, :space) + expect(page.find('#spree_user_remember_me')).to be_checked + page.find('#spree_user_remember_me').send_keys(:tab, :enter) end end