diff options
author | Fatih Acet <acetfatih@gmail.com> | 2016-10-27 13:28:40 +0000 |
---|---|---|
committer | Fatih Acet <acetfatih@gmail.com> | 2016-10-27 13:28:40 +0000 |
commit | f879319840949c1d4b363742cb9573d89abd1296 (patch) | |
tree | 7138a0edfb88cc4cb86a078bc0a3e2f93df64125 | |
parent | 337c5ded7ed46f69efc9d1c47114d3b5a18dceba (diff) | |
parent | f610f69ab92827c49e9cbb528cacc26af10be081 (diff) | |
download | gitlab-ce-f879319840949c1d4b363742cb9573d89abd1296.tar.gz |
Merge branch 'add-todo-toggle-event' into 'master'
remove-tooltip-text-truncation-from-pipeline-graph-build-node-tooltips
Add todo toggle event
## What does this MR do?
Adds a custom jQuery event `todo:toggle` to detect when a new todo is added so that the respective todo counters (header navigation and sidebar) can update as needed
## Are there points in the code the reviewer needs to double check?
* I wasn't sure whether each `spec` should be modularized based on the html templates or whether they should be separated based on function. There are some crossovers between the `dashboard_spec` and the `header_spec`.
* The naming conventions for `sidebar` and `right_sidebar` were a little confusing since they were named the opposite in their `specs`. I made a few assumptions and named a few files based on what I thought they should be named. I'd be happy to change it to something else though :smile:
## Why was this MR needed?
This resolves an existing issue where the todo count on the sidebar would not update (until refresh) and refactors the existing methods that are used to update the todo counters (header navigation and sidebar)
## What are the relevant issue numbers?
Closes #20140
## Does this MR meet the acceptance criteria?
- [x] [CHANGELOG](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG) entry added
- Tests
- [x] Added for this feature/bug
- [x] All builds are passing
- [x] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides)
- [x] Branch has no merge conflicts with `master` (if you do - rebase it please)
- [x] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)
See merge request !5724
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | app/assets/javascripts/header.js | 9 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/text_utility.js | 3 | ||||
-rw-r--r-- | app/assets/javascripts/right_sidebar.js | 11 | ||||
-rw-r--r-- | app/assets/javascripts/sidebar.js.es6 | 7 | ||||
-rw-r--r-- | app/assets/javascripts/todos.js.es6 | 3 | ||||
-rw-r--r-- | app/views/layouts/nav/_dashboard.html.haml | 2 | ||||
-rw-r--r-- | spec/features/todos/todos_spec.rb | 1 | ||||
-rw-r--r-- | spec/javascripts/dashboard_spec.js.es6 | 38 | ||||
-rw-r--r-- | spec/javascripts/fixtures/dashboard.html.haml | 45 | ||||
-rw-r--r-- | spec/javascripts/fixtures/header.html.haml | 35 | ||||
-rw-r--r-- | spec/javascripts/fixtures/right_sidebar.html.haml | 4 | ||||
-rw-r--r-- | spec/javascripts/fixtures/todos.json | 4 | ||||
-rw-r--r-- | spec/javascripts/header_spec.js | 54 | ||||
-rw-r--r-- | spec/javascripts/right_sidebar_spec.js | 19 |
15 files changed, 223 insertions, 13 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index ff8e03e7d58..a4b8e6498cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -102,6 +102,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 469da61bc4e..98f9815ff05 100644 --- a/app/assets/javascripts/lib/utils/text_utility.js +++ b/app/assets/javascripts/lib/utils/text_utility.js @@ -8,6 +8,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 dcedea17a9c..df38937858f 100644 --- a/app/assets/javascripts/right_sidebar.js +++ b/app/assets/javascripts/right_sidebar.js @@ -82,16 +82,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 ca68f9e2982..a23ca449c4b 100644 --- a/app/assets/javascripts/sidebar.js.es6 +++ b/app/assets/javascripts/sidebar.js.es6 @@ -38,7 +38,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(); } @@ -53,6 +54,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 23da346ecb1..213e80825b7 100644 --- a/app/assets/javascripts/todos.js.es6 +++ b/app/assets/javascripts/todos.js.es6 @@ -98,7 +98,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 c191e42dff7..ef03d1147de 100644 --- a/spec/javascripts/right_sidebar_spec.js +++ b/spec/javascripts/right_sidebar_spec.js @@ -4,6 +4,8 @@ /*= require jquery */ /*= require js.cookie */ +/*= require extensions/jquery.js */ + (function() { var $aside, $icon, $labelsIcon, $page, $toggle, assertSidebarState; @@ -56,12 +58,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); |