Merge branch 'add-todo-toggle-event' into 'master'
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 😄 ## 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
This commit is contained in:
commit
f879319840
15 changed files with 223 additions and 13 deletions
|
@ -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)
|
||||
|
|
9
app/assets/javascripts/header.js
Normal file
9
app/assets/javascripts/header.js
Normal file
|
@ -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);
|
||||
});
|
||||
|
||||
})();
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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'));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
38
spec/javascripts/dashboard_spec.js.es6
Normal file
38
spec/javascripts/dashboard_spec.js.es6
Normal file
|
@ -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);
|
45
spec/javascripts/fixtures/dashboard.html.haml
Normal file
45
spec/javascripts/fixtures/dashboard.html.haml
Normal file
|
@ -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
|
35
spec/javascripts/fixtures/header.html.haml
Normal file
35
spec/javascripts/fixtures/header.html.haml
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
4
spec/javascripts/fixtures/todos.json
Normal file
4
spec/javascripts/fixtures/todos.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"count": 1,
|
||||
"delete_path": "/dashboard/todos/1"
|
||||
}
|
54
spec/javascripts/header_spec.js
Normal file
54
spec/javascripts/header_spec.js
Normal file
|
@ -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);
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue