From 8235f8301571a9b55a14b94b2ed687e53cbc2f4e Mon Sep 17 00:00:00 2001
From: Jacopo <beschi.jacopo@gmail.com>
Date: Sun, 6 Nov 2016 19:41:23 +0100
Subject: [PATCH] Fixed Wrong Tab Selected When Loggin Fails And Multiple Login
 Tabs Exists

When ldap is enabled and use "Standard" authentication method, if authentication fails
the correct tab remain selected.
This is done by saving into localStorage when the active tab changes and by always selecting that tab when
the page is loaded.
---
 .eslintrc                                     |  3 +-
 app/assets/javascripts/dispatcher.js.es6      |  1 +
 .../javascripts/signin_tabs_memoizer.js.es6   | 49 +++++++++++++++++
 app/views/devise/sessions/new.html.haml       |  1 +
 .../15081-wrong-login-tab-ldap-frontend.yml   |  4 ++
 .../fixtures/signin_tabs.html.haml            |  5 ++
 .../signin_tabs_memoizer_spec.js.es6          | 53 +++++++++++++++++++
 7 files changed, 115 insertions(+), 1 deletion(-)
 create mode 100644 app/assets/javascripts/signin_tabs_memoizer.js.es6
 create mode 100644 changelogs/unreleased/15081-wrong-login-tab-ldap-frontend.yml
 create mode 100644 spec/javascripts/fixtures/signin_tabs.html.haml
 create mode 100644 spec/javascripts/signin_tabs_memoizer_spec.js.es6

diff --git a/.eslintrc b/.eslintrc
index b80dcec9d1d..e13f76b213c 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -8,7 +8,8 @@
   "globals": {
     "_": false,
     "gl": false,
-    "gon": false
+    "gon": false,
+    "localStorage": false
   },
   "plugins": [
     "filenames"
diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6
index 16df4b0b005..fb366e2eb88 100644
--- a/app/assets/javascripts/dispatcher.js.es6
+++ b/app/assets/javascripts/dispatcher.js.es6
@@ -24,6 +24,7 @@
       switch (page) {
         case 'sessions:new':
           new UsernameValidator();
+          new ActiveTabMemoizer();
           break;
         case 'projects:boards:show':
         case 'projects:boards:index':
diff --git a/app/assets/javascripts/signin_tabs_memoizer.js.es6 b/app/assets/javascripts/signin_tabs_memoizer.js.es6
new file mode 100644
index 00000000000..d811d1cd53a
--- /dev/null
+++ b/app/assets/javascripts/signin_tabs_memoizer.js.es6
@@ -0,0 +1,49 @@
+/* eslint no-param-reassign: ["error", { "props": false }]*/
+/* eslint no-new: "off" */
+((global) => {
+  /**
+   * Memorize the last selected tab after reloading a page.
+   * Does that setting the current selected tab in the localStorage
+   */
+  class ActiveTabMemoizer {
+    constructor({ currentTabKey = 'current_signin_tab', tabSelector = 'ul.nav-tabs' } = {}) {
+      this.currentTabKey = currentTabKey;
+      this.tabSelector = tabSelector;
+      this.bootstrap();
+    }
+
+    bootstrap() {
+      const tabs = document.querySelectorAll(this.tabSelector);
+      if (tabs.length > 0) {
+        tabs[0].addEventListener('click', (e) => {
+          if (e.target && e.target.nodeName === 'A') {
+            const anchorName = e.target.getAttribute('href');
+            this.saveData(anchorName);
+          }
+        });
+      }
+
+      this.showTab();
+    }
+
+    showTab() {
+      const anchorName = this.readData();
+      if (anchorName) {
+        const tab = document.querySelector(`${this.tabSelector} a[href="${anchorName}"]`);
+        if (tab) {
+          tab.click();
+        }
+      }
+    }
+
+    saveData(val) {
+      localStorage.setItem(this.currentTabKey, val);
+    }
+
+    readData() {
+      return localStorage.getItem(this.currentTabKey);
+    }
+  }
+
+  global.ActiveTabMemoizer = ActiveTabMemoizer;
+})(window);
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index fa8e7979461..af87129e49e 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -1,4 +1,5 @@
 - page_title "Sign in"
+
 %div
   - if form_based_providers.any?
     = render 'devise/shared/tabs_ldap'
diff --git a/changelogs/unreleased/15081-wrong-login-tab-ldap-frontend.yml b/changelogs/unreleased/15081-wrong-login-tab-ldap-frontend.yml
new file mode 100644
index 00000000000..19c76b5b437
--- /dev/null
+++ b/changelogs/unreleased/15081-wrong-login-tab-ldap-frontend.yml
@@ -0,0 +1,4 @@
+---
+title: Fix wrong tab selected when loggin fails and multiple login tabs exists
+merge_request: 7314
+author: Jacopo Beschi @jacopo-beschi 
diff --git a/spec/javascripts/fixtures/signin_tabs.html.haml b/spec/javascripts/fixtures/signin_tabs.html.haml
new file mode 100644
index 00000000000..12b8d423cbe
--- /dev/null
+++ b/spec/javascripts/fixtures/signin_tabs.html.haml
@@ -0,0 +1,5 @@
+%ul.nav-tabs
+  %li
+    %a.active{ id: 'standard', href: '#standard'} Standard
+  %li
+    %a{ id: 'ldap', href: '#ldap'} Ldap
diff --git a/spec/javascripts/signin_tabs_memoizer_spec.js.es6 b/spec/javascripts/signin_tabs_memoizer_spec.js.es6
new file mode 100644
index 00000000000..9a9fb22255b
--- /dev/null
+++ b/spec/javascripts/signin_tabs_memoizer_spec.js.es6
@@ -0,0 +1,53 @@
+/*= require signin_tabs_memoizer */
+
+((global) => {
+  describe('SigninTabsMemoizer', () => {
+    const fixtureTemplate = 'signin_tabs.html';
+    const tabSelector = 'ul.nav-tabs';
+    const currentTabKey = 'current_signin_tab';
+    let memo;
+
+    function createMemoizer() {
+      memo = new global.ActiveTabMemoizer({
+        currentTabKey,
+        tabSelector,
+      });
+      return memo;
+    }
+
+    fixture.preload(fixtureTemplate);
+
+    beforeEach(() => {
+      fixture.load(fixtureTemplate);
+    });
+
+    it('does nothing if no tab was previously selected', () => {
+      createMemoizer();
+
+      expect(document.querySelector('li a.active').getAttribute('id')).toEqual('standard');
+    });
+
+    it('shows last selected tab on boot', () => {
+      createMemoizer().saveData('#ldap');
+      const fakeTab = {
+        click: () => {},
+      };
+      spyOn(document, 'querySelector').and.returnValue(fakeTab);
+      spyOn(fakeTab, 'click');
+
+      memo.bootstrap();
+
+      // verify that triggers click on the last selected tab
+      expect(document.querySelector).toHaveBeenCalledWith(`${tabSelector} a[href="#ldap"]`);
+      expect(fakeTab.click).toHaveBeenCalled();
+    });
+
+    it('saves last selected tab on change', () => {
+      createMemoizer();
+
+      document.getElementById('standard').click();
+
+      expect(memo.readData()).toEqual('#standard');
+    });
+  });
+})(window);
-- 
GitLab