From f610f69ab92827c49e9cbb528cacc26af10be081 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Mon, 8 Aug 2016 16:19:46 -0500 Subject: [PATCH] Add todo toggle event --- CHANGELOG.md | 1 + app/assets/javascripts/header.js | 9 ++++ .../javascripts/lib/utils/text_utility.js | 3 ++ app/assets/javascripts/right_sidebar.js | 11 ++-- app/assets/javascripts/sidebar.js.es6 | 7 ++- app/assets/javascripts/todos.js.es6 | 3 +- app/views/layouts/nav/_dashboard.html.haml | 2 +- spec/features/todos/todos_spec.rb | 1 - spec/javascripts/dashboard_spec.js.es6 | 38 +++++++++++++ spec/javascripts/fixtures/dashboard.html.haml | 45 ++++++++++++++++ spec/javascripts/fixtures/header.html.haml | 35 ++++++++++++ .../fixtures/right_sidebar.html.haml | 4 ++ spec/javascripts/fixtures/todos.json | 4 ++ spec/javascripts/header_spec.js | 54 +++++++++++++++++++ spec/javascripts/right_sidebar_spec.js | 19 ++++++- 15 files changed, 223 insertions(+), 13 deletions(-) create mode 100644 app/assets/javascripts/header.js create mode 100644 spec/javascripts/dashboard_spec.js.es6 create mode 100644 spec/javascripts/fixtures/dashboard.html.haml create mode 100644 spec/javascripts/fixtures/header.html.haml create mode 100644 spec/javascripts/fixtures/todos.json create mode 100644 spec/javascripts/header_spec.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 86878e5af6c..197a74fd4b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,6 +77,7 @@ Please view this file on the master branch, on stable branches it's out of date. - Add more tests for calendar contribution (ClemMakesApps) - Update Gitlab Shell to fix some problems with moving projects between storages - Cache rendered markdown in the database, rather than Redis + - Add todo toggle event (ClemMakesApps) - Avoid database queries on Banzai::ReferenceParser::BaseParser for nodes without references - Simplify Mentionable concern instance methods - API: Ability to retrieve version information (Robert Schilling) diff --git a/app/assets/javascripts/header.js b/app/assets/javascripts/header.js new file mode 100644 index 00000000000..5215ce9c4ba --- /dev/null +++ b/app/assets/javascripts/header.js @@ -0,0 +1,9 @@ +(function() { + + $(document).on('todo:toggle', function(e, count) { + var $todoPendingCount = $('.todos-pending-count'); + $todoPendingCount.text(gl.text.addDelimiter(count)); + $todoPendingCount.toggleClass('hidden', count === 0); + }); + +})(); diff --git a/app/assets/javascripts/lib/utils/text_utility.js b/app/assets/javascripts/lib/utils/text_utility.js index d761a844be9..6206c7f9237 100644 --- a/app/assets/javascripts/lib/utils/text_utility.js +++ b/app/assets/javascripts/lib/utils/text_utility.js @@ -7,6 +7,9 @@ if ((base = w.gl).text == null) { base.text = {}; } + gl.text.addDelimiter = function(text) { + return text ? text.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : text; + } gl.text.randomString = function() { return Math.random().toString(36).substring(7); }; diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js index e3d5f413c77..9f2385a3de8 100644 --- a/app/assets/javascripts/right_sidebar.js +++ b/app/assets/javascripts/right_sidebar.js @@ -74,16 +74,11 @@ }; Sidebar.prototype.todoUpdateDone = function(data, $btn, $btnText, $todoLoading) { - var $todoPendingCount; - $todoPendingCount = $('.todos-pending-count'); - $todoPendingCount.text(data.count); + $(document).trigger('todo:toggle', data.count); + $btn.enable(); $todoLoading.addClass('hidden'); - if (data.count === 0) { - $todoPendingCount.addClass('hidden'); - } else { - $todoPendingCount.removeClass('hidden'); - } + if (data.delete_path != null) { $btn.attr('aria-label', $btn.data('mark-text')).attr('data-delete-path', data.delete_path); return $btnText.text($btn.data('mark-text')); diff --git a/app/assets/javascripts/sidebar.js.es6 b/app/assets/javascripts/sidebar.js.es6 index 755fac8107b..50c9440de5f 100644 --- a/app/assets/javascripts/sidebar.js.es6 +++ b/app/assets/javascripts/sidebar.js.es6 @@ -37,7 +37,8 @@ .on('click', sidebarToggleSelector, () => this.toggleSidebar()) .on('click', pinnedToggleSelector, () => this.togglePinnedState()) .on('click', 'html, body', (e) => this.handleClickEvent(e)) - .on('page:change', () => this.renderState()); + .on('page:change', () => this.renderState()) + .on('todo:toggle', (e, count) => this.updateTodoCount(count)); this.renderState(); } @@ -52,6 +53,10 @@ } } + updateTodoCount(count) { + $('.js-todos-count').text(gl.text.addDelimiter(count)); + } + toggleSidebar() { this.isExpanded = !this.isExpanded; this.renderState(); diff --git a/app/assets/javascripts/todos.js.es6 b/app/assets/javascripts/todos.js.es6 index 055228c5df8..42539ef43e2 100644 --- a/app/assets/javascripts/todos.js.es6 +++ b/app/assets/javascripts/todos.js.es6 @@ -97,7 +97,8 @@ } updateBadges(data) { - $('.todos-pending .badge, .todos-pending-count').text(data.count); + $(document).trigger('todo:toggle', data.count); + $('.todos-pending .badge').text(data.count); return $('.todos-done .badge').text(data.done_count); } diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml index 67f558c854b..3b1295dc3c0 100644 --- a/app/views/layouts/nav/_dashboard.html.haml +++ b/app/views/layouts/nav/_dashboard.html.haml @@ -7,7 +7,7 @@ = link_to dashboard_todos_path, title: 'Todos' do %span Todos - %span.count= number_with_delimiter(todos_pending_count) + %span.count.js-todos-count= number_with_delimiter(todos_pending_count) = nav_link(path: 'dashboard#activity') do = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do %span diff --git a/spec/features/todos/todos_spec.rb b/spec/features/todos/todos_spec.rb index bf93c1d1251..230543cd175 100644 --- a/spec/features/todos/todos_spec.rb +++ b/spec/features/todos/todos_spec.rb @@ -132,7 +132,6 @@ describe 'Dashboard Todos', feature: true do end it 'shows "All done" message!' do - within('.todos-pending-count') { expect(page).to have_content '0' } expect(page).to have_content 'To do 0' expect(page).to have_content "You're all done!" expect(page).not_to have_selector('.gl-pagination') diff --git a/spec/javascripts/dashboard_spec.js.es6 b/spec/javascripts/dashboard_spec.js.es6 new file mode 100644 index 00000000000..8021145d8e8 --- /dev/null +++ b/spec/javascripts/dashboard_spec.js.es6 @@ -0,0 +1,38 @@ +/*= require sidebar */ +/*= require jquery */ +/*= require jquery.cookie */ +/*= require lib/utils/text_utility */ + +((global) => { + describe('Dashboard', () => { + const fixtureTemplate = 'dashboard.html'; + + function todosCountText() { + return $('.js-todos-count').text(); + } + + function triggerToggle(newCount) { + $(document).trigger('todo:toggle', newCount); + } + + fixture.preload(fixtureTemplate); + beforeEach(() => { + fixture.load(fixtureTemplate); + new global.Sidebar(); + }); + + it('should update todos-count after receiving the todo:toggle event', () => { + triggerToggle(5); + expect(todosCountText()).toEqual('5'); + }); + + it('should display todos-count with delimiter', () => { + triggerToggle(1000); + expect(todosCountText()).toEqual('1,000'); + + triggerToggle(1000000); + expect(todosCountText()).toEqual('1,000,000'); + }); + }); + +})(window.gl); diff --git a/spec/javascripts/fixtures/dashboard.html.haml b/spec/javascripts/fixtures/dashboard.html.haml new file mode 100644 index 00000000000..32446acfd60 --- /dev/null +++ b/spec/javascripts/fixtures/dashboard.html.haml @@ -0,0 +1,45 @@ +%ul.nav.nav-sidebar + %li.home.active + %a.dashboard-shortcuts-projects + %span + Projects + %li + %a + %span + Todos + %span.count.js-todos-count + 1 + %li + %a.dashboard-shortcuts-activity + %span + Activity + %li + %a + %span + Groups + %li + %a + %span + Milestones + %li + %a.dashboard-shortcuts-issues + %span + Issues + %span + 1 + %li + %a.dashboard-shortcuts-merge_requests + %span + Merge Requests + %li + %a + %span + Snippets + %li + %a + %span + Help + %li + %a + %span + Profile Settings diff --git a/spec/javascripts/fixtures/header.html.haml b/spec/javascripts/fixtures/header.html.haml new file mode 100644 index 00000000000..4db2ef604de --- /dev/null +++ b/spec/javascripts/fixtures/header.html.haml @@ -0,0 +1,35 @@ +%header.navbar.navbar-fixed-top.navbar-gitlab.nav_header_class + .container-fluid + .header-content + %button.side-nav-toggle + %span.sr-only + Toggle navigation + %i.fa.fa-bars + %button.navbar-toggle + %span.sr-only + Toggle navigation + %i.fa.fa-ellipsis-v + .navbar-collapse.collapse + %ui.nav.navbar-nav + %li.hidden-sm.hidden-xs + %li.visible-sm.visible-xs + %li + %a + %i.fa.fa-bell.fa-fw + %span.badge.todos-pending-count + %li + %a + %i.fa.fa-plus.fa-fw + %li.header-user.dropdown + %a + %img + %span.caret + .dropdown-menu-nav + .dropdown-menu-align-right + %ul + %li + %a.profile-link + %li + %a + %li.divider + %li.sign-out-link diff --git a/spec/javascripts/fixtures/right_sidebar.html.haml b/spec/javascripts/fixtures/right_sidebar.html.haml index 95efaff4b69..d48b77cf0ce 100644 --- a/spec/javascripts/fixtures/right_sidebar.html.haml +++ b/spec/javascripts/fixtures/right_sidebar.html.haml @@ -5,6 +5,10 @@ %div.block.issuable-sidebar-header %a.gutter-toggle.pull-right.js-sidebar-toggle %i.fa.fa-angle-double-left + %button.btn.btn-default.issuable-header-btn.pull-right.js-issuable-todo{ type: "button", data: { todo_text: "Add Todo", mark_text: "Mark Done", issuable_id: "1", issuable_type: "issue", url: "/todos" }} + %span.js-issuable-todo-text + Add Todo + %i.fa.fa-spin.fa-spinner.js-issuable-todo-loading.hidden %form.issuable-context-form %div.block.labels diff --git a/spec/javascripts/fixtures/todos.json b/spec/javascripts/fixtures/todos.json new file mode 100644 index 00000000000..62c2387d515 --- /dev/null +++ b/spec/javascripts/fixtures/todos.json @@ -0,0 +1,4 @@ +{ + "count": 1, + "delete_path": "/dashboard/todos/1" +} \ No newline at end of file diff --git a/spec/javascripts/header_spec.js b/spec/javascripts/header_spec.js new file mode 100644 index 00000000000..b9d023a9aae --- /dev/null +++ b/spec/javascripts/header_spec.js @@ -0,0 +1,54 @@ +/*= require header */ +/*= require lib/utils/text_utility */ +/*= require jquery */ + +(function() { + + describe('Header', function() { + var todosPendingCount = '.todos-pending-count'; + var fixtureTemplate = 'header.html'; + + function isTodosCountHidden() { + return $(todosPendingCount).hasClass('hidden'); + } + + function triggerToggle(newCount) { + $(document).trigger('todo:toggle', newCount); + } + + fixture.preload(fixtureTemplate); + beforeEach(function() { + fixture.load(fixtureTemplate); + }); + + it('should update todos-pending-count after receiving the todo:toggle event', function() { + triggerToggle(5); + expect($(todosPendingCount).text()).toEqual('5'); + }); + + it('should hide todos-pending-count when it is 0', function() { + triggerToggle(0); + expect(isTodosCountHidden()).toEqual(true); + }); + + it('should show todos-pending-count when it is more than 0', function() { + triggerToggle(10); + expect(isTodosCountHidden()).toEqual(false); + }); + + describe('when todos-pending-count is 1000', function() { + beforeEach(function() { + triggerToggle(1000); + }); + + it('should show todos-pending-count', function() { + expect(isTodosCountHidden()).toEqual(false); + }); + + it('should add delimiter to todos-pending-count', function() { + expect($(todosPendingCount).text()).toEqual('1,000'); + }); + }); + }); + +}).call(this); diff --git a/spec/javascripts/right_sidebar_spec.js b/spec/javascripts/right_sidebar_spec.js index c937a4706f7..9c7f44c6427 100644 --- a/spec/javascripts/right_sidebar_spec.js +++ b/spec/javascripts/right_sidebar_spec.js @@ -3,6 +3,8 @@ /*= require jquery */ /*= require jquery.cookie */ +/*= require extensions/jquery.js */ + (function() { var $aside, $icon, $labelsIcon, $page, $toggle, assertSidebarState; @@ -55,12 +57,27 @@ $labelsIcon.click(); return assertSidebarState('expanded'); }); - return it('should collapse when the icon arrow clicked while it is floating on page', function() { + it('should collapse when the icon arrow clicked while it is floating on page', function() { $labelsIcon.click(); assertSidebarState('expanded'); $toggle.click(); return assertSidebarState('collapsed'); }); + + it('should broadcast todo:toggle event when add todo clicked', function() { + spyOn(jQuery, 'ajax').and.callFake(function() { + var d = $.Deferred(); + var response = fixture.load('todos.json'); + d.resolve(response); + return d.promise(); + }); + + var todoToggleSpy = spyOnEvent(document, 'todo:toggle'); + + $('.js-issuable-todo').click(); + + expect(todoToggleSpy.calls.count()).toEqual(1); + }) }); }).call(this);