Commit c7a4a3f9 authored by Takuya Noguchi's avatar Takuya Noguchi

Reduce page_bundle for TODO list

Improve user experience in terms of performance

Changelog: fixed
Co-authored-by: default avatarPhil Hughes <me@iamphill.com>
Signed-off-by: default avatarTakuya Noguchi <takninnovationresearch@gmail.com>
parent 7368e2a6
...@@ -8,8 +8,6 @@ ...@@ -8,8 +8,6 @@
.todos-list > .todo { .todos-list > .todo {
// workaround because we cannot use border-collapse // workaround because we cannot use border-collapse
border-top: 1px solid transparent; border-top: 1px solid transparent;
display: flex;
flex-direction: row;
&:hover { &:hover {
background-color: var(--blue-50, $blue-50); background-color: var(--blue-50, $blue-50);
...@@ -26,25 +24,6 @@ ...@@ -26,25 +24,6 @@
} }
} }
.todo-avatar,
.todo-actions {
@include transition(opacity);
flex: 0 0 auto;
}
.todo-actions {
display: flex;
justify-content: center;
flex-direction: column;
margin-left: 10px;
min-width: 55px;
}
.todo-item {
flex: 0 1 100%;
min-width: 0;
}
&.todo-pending.done-reversible { &.todo-pending.done-reversible {
&:hover { &:hover {
border-color: var(--border-color, $border-color); border-color: var(--border-color, $border-color);
...@@ -71,58 +50,22 @@ ...@@ -71,58 +50,22 @@
.todo-item { .todo-item {
@include transition(opacity); @include transition(opacity);
.todo-title {
> .title-item {
&:first-child {
margin-left: 0;
}
&:last-child {
margin-right: 0;
}
}
.todo-label {
flex: 0 1 auto;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.status-box { .status-box {
margin: 0;
float: none;
display: inline-block;
font-weight: $gl-font-weight-normal;
padding: 0 5px;
line-height: inherit; line-height: inherit;
font-size: 14px;
} }
.todo-label, .todo-label,
.todo-project { .todo-project {
a { a {
font-weight: $gl-font-weight-normal;
color: var(--blue-600, $blue-600); color: var(--blue-600, $blue-600);
} }
} }
.todo-body { .todo-body {
.badge.badge-pill,
p { p {
color: var(--gl-text-color, $gl-text-color); color: var(--gl-text-color, $gl-text-color);
} }
.md {
color: $gl-grayish-blue;
font-size: $gl-font-size;
}
code {
white-space: pre-wrap;
}
pre { pre {
border: 0; border: 0;
background: var(--gray-50, $gray-50); background: var(--gray-50, $gray-50);
...@@ -139,120 +82,13 @@ ...@@ -139,120 +82,13 @@
float: none; float: none;
} }
p:last-child {
margin-bottom: 0;
}
}
.gl-label-scoped { .gl-label-scoped {
--label-inset-border: inset 0 0 0 1px currentColor; --label-inset-border: inset 0 0 0 1px currentColor;
} }
}
@include media-breakpoint-down(lg) { @include media-breakpoint-down(sm) {
.todos-filters {
.filter-categories {
width: 75%;
.filter-item {
margin-bottom: 10px;
}
}
}
}
@include media-breakpoint-down(sm) {
.container-fluid .todos-list-container {
margin: 0 (-$gl-padding);
}
.todo {
.avatar {
display: none;
}
}
.todo-item {
.todo-title {
margin-bottom: 10px;
.todo-label {
white-space: normal;
}
}
.todo-body {
margin: 0;
border-left: 2px solid var(--border-color, $border-color); border-left: 2px solid var(--border-color, $border-color);
padding-left: 10px; padding-left: 10px;
} }
} }
.todos-filters {
.filter-categories {
width: auto;
}
.dropdown-menu-toggle {
width: 100%;
}
.dropdown-menu-toggle-sort {
width: auto;
}
}
}
.todos-empty {
display: flex;
flex-direction: column;
max-width: 900px;
margin-left: auto;
margin-right: auto;
@include media-breakpoint-up(sm) {
flex-direction: row;
padding-top: 80px;
}
}
.todos-empty-content {
align-self: center;
max-width: 480px;
}
.todos-empty-hero {
width: 200px;
margin-left: auto;
margin-right: auto;
@include media-breakpoint-up(sm) {
width: 300px;
margin-right: 0;
order: 2;
}
}
.todos-all-done {
padding-top: 20px;
@include media-breakpoint-up(sm) {
padding-top: 50px;
}
> svg {
display: block;
max-width: 300px;
margin: 0 auto 20px;
}
p {
max-width: 470px;
margin-left: auto;
margin-right: auto;
}
a {
font-weight: $gl-font-weight-bold;
}
} }
...@@ -110,12 +110,10 @@ module TodosHelper ...@@ -110,12 +110,10 @@ module TodosHelper
'alert' 'alert'
end end
content_tag(:span, nil, class: 'target-status') do tag.span class: "gl-my-0 gl-px-2 status-box status-box-#{type}-#{todo.target.state.to_s.dasherize}" do
content_tag(:span, nil, class: "status-box status-box-#{type}-#{todo.target.state.to_s.dasherize}") do
todo.target.state.to_s.capitalize todo.target.state.to_s.capitalize
end end
end end
end
def todos_filter_params def todos_filter_params
{ {
......
%li{ class: "todo todo-#{todo.done? ? 'done' : 'pending'}", id: dom_id(todo), data: { url: todo_target_path(todo) } } %li.todo{ class: "todo-#{todo.done? ? 'done' : 'pending'}", id: dom_id(todo), data: { url: todo_target_path(todo) } }
.todo-avatar .gl-display-flex.gl-flex-direction-row
.todo-avatar.gl-display-none.gl-sm-display-inline-block
= author_avatar(todo, size: 40) = author_avatar(todo, size: 40)
.todo-item.todo-block.align-self-center{ data: { qa_selector: "todo_item_container" } } .todo-item.gl-w-full.gl-align-self-center{ data: { qa_selector: "todo_item_container" } }
.todo-title .todo-title.gl-mb-3.gl-md-mb-0
- if todo_author_display?(todo) - if todo_author_display?(todo)
= todo_target_state_pill(todo) = todo_target_state_pill(todo)
...@@ -46,8 +47,8 @@ ...@@ -46,8 +47,8 @@
.md .md
= first_line_in_markdown(todo, :body, 150, project: todo.project) = first_line_in_markdown(todo, :body, 150, project: todo.project)
.todo-actions.gl-ml-3
- if todo.pending? - if todo.pending?
.todo-actions
= link_to dashboard_todo_path(todo), method: :delete, class: 'gl-button btn btn-default btn-loading d-flex align-items-center js-done-todo', data: { href: dashboard_todo_path(todo) } do = link_to dashboard_todo_path(todo), method: :delete, class: 'gl-button btn btn-default btn-loading d-flex align-items-center js-done-todo', data: { href: dashboard_todo_path(todo) } do
Done Done
%span.gl-spinner.ml-1 %span.gl-spinner.ml-1
...@@ -55,7 +56,6 @@ ...@@ -55,7 +56,6 @@
Undo Undo
%span.gl-spinner.ml-1 %span.gl-spinner.ml-1
- else - else
.todo-actions
= link_to restore_dashboard_todo_path(todo), method: :patch, class: 'gl-button btn btn-default btn-loading d-flex align-items-center js-add-todo', data: { href: restore_dashboard_todo_path(todo) } do = link_to restore_dashboard_todo_path(todo), method: :patch, class: 'gl-button btn btn-default btn-loading d-flex align-items-center js-add-todo', data: { href: restore_dashboard_todo_path(todo) } do
Add a to do Add a to do
%span.gl-spinner.ml-1 %span.gl-spinner.ml-1
...@@ -36,34 +36,34 @@ ...@@ -36,34 +36,34 @@
.todos-filters .todos-filters
.issues-details-filters.row-content-block.second-block .issues-details-filters.row-content-block.second-block
= form_tag todos_filter_path(without: [:project_id, :author_id, :type, :action_id]), method: :get, class: 'filter-form d-sm-flex' do = form_tag todos_filter_path(without: [:project_id, :author_id, :type, :action_id]), method: :get, class: 'filter-form gl-display-flex gl-flex-direction-column gl-sm-flex-direction-row' do
.filter-categories.flex-fill .filter-categories.gl-display-flex.gl-flex-direction-column.gl-md-flex-direction-row.gl-flex-fill-1.gl-flex-wrap.gl-mx-n2
.filter-item.inline .filter-item.gl-m-2
- if params[:group_id].present? - if params[:group_id].present?
= hidden_field_tag(:group_id, params[:group_id]) = hidden_field_tag(:group_id, params[:group_id])
= dropdown_tag(group_dropdown_label(params[:group_id], 'Group'), options: { toggle_class: 'js-group-search js-filter-submit', title: 'Filter by group', filter: true, filterInput: 'input#group-search', dropdown_class: 'dropdown-menu-selectable dropdown-menu-group js-filter-submit', = dropdown_tag(group_dropdown_label(params[:group_id], 'Group'), options: { toggle_class: 'js-group-search js-filter-submit gl-xs-w-full!', title: 'Filter by group', filter: true, filterInput: 'input#group-search', dropdown_class: 'dropdown-menu-selectable dropdown-menu-group js-filter-submit',
placeholder: 'Search groups', data: { default_label: 'Group', display: 'static' } }) placeholder: 'Search groups', data: { default_label: 'Group', display: 'static' } })
.filter-item.inline .filter-item.gl-m-2
- if params[:project_id].present? - if params[:project_id].present?
= hidden_field_tag(:project_id, params[:project_id]) = hidden_field_tag(:project_id, params[:project_id])
= dropdown_tag(project_dropdown_label(params[:project_id], 'Project'), options: { toggle_class: 'js-project-search js-filter-submit', title: 'Filter by project', filter: true, filterInput: 'input#project-search', dropdown_class: 'dropdown-menu-selectable dropdown-menu-project js-filter-submit', = dropdown_tag(project_dropdown_label(params[:project_id], 'Project'), options: { toggle_class: 'js-project-search js-filter-submit gl-xs-w-full!', title: 'Filter by project', filter: true, filterInput: 'input#project-search', dropdown_class: 'dropdown-menu-selectable dropdown-menu-project js-filter-submit',
placeholder: 'Search projects', data: { default_label: 'Project', display: 'static' } }) placeholder: 'Search projects', data: { default_label: 'Project', display: 'static' } })
.filter-item.inline .filter-item.gl-m-2
- if params[:author_id].present? - if params[:author_id].present?
= hidden_field_tag(:author_id, params[:author_id]) = hidden_field_tag(:author_id, params[:author_id])
= dropdown_tag(user_dropdown_label(params[:author_id], 'Author'), options: { toggle_class: 'js-user-search js-filter-submit js-author-search', title: 'Filter by author', filter: true, filterInput: 'input#author-search', dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit', = dropdown_tag(user_dropdown_label(params[:author_id], 'Author'), options: { toggle_class: 'js-user-search js-filter-submit js-author-search gl-xs-w-full!', title: 'Filter by author', filter: true, filterInput: 'input#author-search', dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit',
placeholder: 'Search authors', data: { any_user: 'Any Author', first_user: (current_user.username if current_user), project_id: (@project.id if @project), selected: params[:author_id], field_name: 'author_id', default_label: 'Author', todo_filter: true, todo_state_filter: params[:state] || 'pending' } }) placeholder: 'Search authors', data: { any_user: 'Any Author', first_user: (current_user.username if current_user), project_id: (@project.id if @project), selected: params[:author_id], field_name: 'author_id', default_label: 'Author', todo_filter: true, todo_state_filter: params[:state] || 'pending' } })
.filter-item.inline .filter-item.gl-m-2
- if params[:type].present? - if params[:type].present?
= hidden_field_tag(:type, params[:type]) = hidden_field_tag(:type, params[:type])
= dropdown_tag(todo_types_dropdown_label(params[:type], 'Type'), options: { toggle_class: 'js-type-search js-filter-submit', dropdown_class: 'dropdown-menu-selectable dropdown-menu-type js-filter-submit', = dropdown_tag(todo_types_dropdown_label(params[:type], 'Type'), options: { toggle_class: 'js-type-search js-filter-submit gl-xs-w-full!', dropdown_class: 'dropdown-menu-selectable dropdown-menu-type js-filter-submit',
data: { data: todo_types_options, default_label: 'Type' } }) data: { data: todo_types_options, default_label: 'Type' } })
.filter-item.inline.actions-filter .filter-item.actions-filter.gl-m-2
- if params[:action_id].present? - if params[:action_id].present?
= hidden_field_tag(:action_id, params[:action_id]) = hidden_field_tag(:action_id, params[:action_id])
= dropdown_tag(todo_actions_dropdown_label(params[:action_id], 'Action'), options: { toggle_class: 'js-action-search js-filter-submit', dropdown_class: 'dropdown-menu-selectable dropdown-menu-action js-filter-submit', = dropdown_tag(todo_actions_dropdown_label(params[:action_id], 'Action'), options: { toggle_class: 'js-action-search js-filter-submit gl-xs-w-full!', dropdown_class: 'dropdown-menu-selectable dropdown-menu-action js-filter-submit',
data: { data: todo_actions_options, default_label: 'Action' } }) data: { data: todo_actions_options, default_label: 'Action' } })
.filter-item.sort-filter .filter-item.sort-filter.gl-mt-3.gl-sm-mt-0.gl-mb-0.gl-sm-mb-0
.dropdown .dropdown
%button.dropdown-menu-toggle.dropdown-menu-toggle-sort{ type: 'button', class: 'gl-xs-w-full!', 'data-toggle' => 'dropdown' } %button.dropdown-menu-toggle.dropdown-menu-toggle-sort{ type: 'button', class: 'gl-xs-w-full!', 'data-toggle' => 'dropdown' }
%span.light %span.light
...@@ -81,40 +81,45 @@ ...@@ -81,40 +81,45 @@
= link_to todos_filter_path(sort: sort_value_oldest_created) do = link_to todos_filter_path(sort: sort_value_oldest_created) do
= sort_title_oldest_created = sort_title_oldest_created
.todos-list-container.js-todos-all .row.js-todos-all
- if @todos.any? - if @todos.any?
.js-todos-list-container{ data: { qa_selector: "todos_list_container" } } .col.js-todos-list-container{ data: { qa_selector: "todos_list_container" } }
.js-todos-options{ data: { per_page: @todos.limit_value, current_page: @todos.current_page, total_pages: @todos.total_pages } } .js-todos-options{ data: { per_page: @todos.limit_value, current_page: @todos.current_page, total_pages: @todos.total_pages } }
%ul.content-list.todos-list %ul.content-list.todos-list
= render @todos = render @todos
= paginate @todos, theme: "gitlab" = paginate @todos, theme: "gitlab"
.js-nothing-here-container.todos-all-done.hidden.svg-content .js-nothing-here-container.empty-state.hidden
.svg-content
= image_tag 'illustrations/todos_all_done.svg' = image_tag 'illustrations/todos_all_done.svg'
.text-content
%h4.text-center %h4.text-center
You're all done! You're all done!
- elsif current_user.todos.any? - elsif current_user.todos.any?
.todos-all-done .col.todos-all-done.empty-state
.svg-content.svg-250 .svg-content.svg-250
= image_tag 'illustrations/todos_all_done.svg' = image_tag 'illustrations/todos_all_done.svg'
.text-content
- if todos_filter_empty? - if todos_filter_empty?
%h4.text-center %h4.text-center
= Gitlab.config.gitlab.no_todos_messages.sample = Gitlab.config.gitlab.no_todos_messages.sample
%p %p
Are you looking for things to do? Take a look at Are you looking for things to do? Take a look at
= succeed "," do = succeed "," do
%strong
= link_to "open issues", issues_dashboard_path = link_to "open issues", issues_dashboard_path
contribute to contribute to
%strong
= link_to "a merge request\,", merge_requests_dashboard_path = link_to "a merge request\,", merge_requests_dashboard_path
or mention someone in a comment to automatically assign them a new to-do item. or mention someone in a comment to automatically assign them a new to-do item.
- else - else
%h4.text-center %h4.text-center
Nothing is on your to-do list. Nice work! Nothing is on your to-do list. Nice work!
- else - else
.todos-empty .col.empty-state
.todos-empty-hero.svg-content .svg-content
= image_tag 'illustrations/todos_empty.svg' = image_tag 'illustrations/todos_empty.svg'
.todos-empty-content.gl-mx-5 .text-content
%h4 %h4.text-center
Your To-Do List shows what to work on next Your To-Do List shows what to work on next
%p %p
When an issue or merge request is assigned to you, or when you receive a When an issue or merge request is assigned to you, or when you receive a
......
...@@ -79,7 +79,7 @@ RSpec.describe 'Dashboard Todos' do ...@@ -79,7 +79,7 @@ RSpec.describe 'Dashboard Todos' do
end end
it 'has not "All done" message' do it 'has not "All done" message' do
expect(page).not_to have_selector('.todos-all-done') expect(page).not_to have_selector('.empty-state')
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment