diff options
author | Phil Hughes <me@iamphill.com> | 2016-10-12 12:40:15 +0100 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2016-11-01 08:47:27 +0000 |
commit | abd15596200e993a060b8d89b85b69ba3bbf2f0e (patch) | |
tree | c2204deeede53e961479e0dbc54d266dca059949 /app | |
parent | b328c7885532ccff70e1f9f7dc970a8dde0c52d6 (diff) | |
download | gitlab-ce-abd15596200e993a060b8d89b85b69ba3bbf2f0e.tar.gz |
New todos blank state
Closes #20833
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/stylesheets/pages/todos.scss | 56 | ||||
-rw-r--r-- | app/views/dashboard/todos/index.html.haml | 146 | ||||
-rw-r--r-- | app/views/shared/empty_states/_todos_all_done.svg | 1 | ||||
-rw-r--r-- | app/views/shared/empty_states/_todos_empty.svg | 110 |
4 files changed, 252 insertions, 61 deletions
diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss index ea76fe18876..f76436b2b8b 100644 --- a/app/assets/stylesheets/pages/todos.scss +++ b/app/assets/stylesheets/pages/todos.scss @@ -161,3 +161,59 @@ } } } + +.todos-empty { + display: -webkit-flex; + display: flex; + flex-direction: column; + max-width: 900px; + margin-left: auto; + margin-right: auto; + + @media (min-width: $screen-sm-min) { + flex-direction: row; + padding-top: 80px; + } +} + +.todos-empty-content { + align-self: center; + max-width: 480px; + margin-right: 20px; +} + +.todos-empty-hero { + width: 200px; + margin-left: auto; + margin-right: auto; + + @media (min-width: $screen-sm-min) { + width: 300px; + margin-right: 0; + order: 2; + } +} + +.todos-all-done { + padding-top: 20px; + + @media (min-width: $screen-sm-min) { + 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: 600; + } +} diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index 2a0302638ba..ff13254e0f5 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -1,69 +1,70 @@ - page_title "Todos" - header_title "Todos", dashboard_todos_path -.top-area - %ul.nav-links - - todo_pending_active = ('active' if params[:state].blank? || params[:state] == 'pending') - %li{class: "todos-pending #{todo_pending_active}"} - = link_to todos_filter_path(state: 'pending') do - %span - To do - %span.badge - = number_with_delimiter(todos_pending_count) - - todo_done_active = ('active' if params[:state] == 'done') - %li{class: "todos-done #{todo_done_active}"} - = link_to todos_filter_path(state: 'done') do - %span - Done - %span.badge - = number_with_delimiter(todos_done_count) +- if current_user.todos.any? + .top-area + %ul.nav-links + - todo_pending_active = ('active' if params[:state].blank? || params[:state] == 'pending') + %li{class: "todos-pending #{todo_pending_active}"} + = link_to todos_filter_path(state: 'pending') do + %span + To do + %span.badge + = number_with_delimiter(todos_pending_count) + - todo_done_active = ('active' if params[:state] == 'done') + %li{class: "todos-done #{todo_done_active}"} + = link_to todos_filter_path(state: 'done') do + %span + Done + %span.badge + = number_with_delimiter(todos_done_count) - .nav-controls - - if @todos.any?(&:pending?) - = link_to destroy_all_dashboard_todos_path(todos_filter_params), class: 'btn btn-loading js-todos-mark-all', method: :delete do - Mark all as done - = icon('spinner spin') + .nav-controls + - if @todos.any?(&:pending?) + = link_to destroy_all_dashboard_todos_path(todos_filter_params), class: 'btn btn-loading js-todos-mark-all', method: :delete do + Mark all as done + = icon('spinner spin') -.todos-filters - .row-content-block.second-block - = form_tag todos_filter_path(without: [:project_id, :author_id, :type, :action_id]), method: :get, class: 'filter-form' do - .filter-item.inline - - if params[:project_id].present? - = 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', - placeholder: 'Search projects', data: { data: todo_projects_options } }) - .filter-item.inline - - if params[:author_id].present? - = 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', - placeholder: 'Search authors', data: { any_user: 'Any Author', first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author_id], field_name: 'author_id', default_label: 'Author' } }) - .filter-item.inline - - if params[:type].present? - = 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', - data: { data: todo_types_options } }) - .filter-item.inline.actions-filter - - if params[:action_id].present? - = 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', - data: { data: todo_actions_options }}) - .pull-right - .dropdown.inline.prepend-left-10 - %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} - %span.light - - if @sort.present? - = sort_options_hash[@sort] - - else - = sort_title_recently_created - = icon('caret-down') - %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-sort - %li - = link_to todos_filter_path(sort: sort_value_priority) do - = sort_title_priority - = link_to todos_filter_path(sort: sort_value_recently_created) do + .todos-filters + .row-content-block.second-block + = form_tag todos_filter_path(without: [:project_id, :author_id, :type, :action_id]), method: :get, class: 'filter-form' do + .filter-item.inline + - if params[:project_id].present? + = 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', + placeholder: 'Search projects', data: { data: todo_projects_options } }) + .filter-item.inline + - if params[:author_id].present? + = 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', + placeholder: 'Search authors', data: { any_user: 'Any Author', first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author_id], field_name: 'author_id', default_label: 'Author' } }) + .filter-item.inline + - if params[:type].present? + = 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', + data: { data: todo_types_options } }) + .filter-item.inline.actions-filter + - if params[:action_id].present? + = 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', + data: { data: todo_actions_options }}) + .pull-right + .dropdown.inline.prepend-left-10 + %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} + %span.light + - if @sort.present? + = sort_options_hash[@sort] + - else = sort_title_recently_created - = link_to todos_filter_path(sort: sort_value_oldest_created) do - = sort_title_oldest_created + = icon('caret-down') + %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-sort + %li + = link_to todos_filter_path(sort: sort_value_priority) do + = sort_title_priority + = link_to todos_filter_path(sort: sort_value_recently_created) do + = sort_title_recently_created + = link_to todos_filter_path(sort: sort_value_oldest_created) do + = sort_title_oldest_created .prepend-top-default @@ -78,5 +79,28 @@ %ul.content-list.todos-list = render group[1] = paginate @todos, theme: "gitlab" + - elsif current_user.todos.any? + .todos-all-done + = render "shared/empty_states/todos_all_done.svg" + %h4.text-center + Good job! Looks like you don't have any todos left. + %p.text-center + Are you looking for things to do? Take a look at + = succeed "," do + = link_to "the opened issues", issues_dashboard_path + = link_to "contribute to merge requests", merge_requests_dashboard_path + or mention someone in a comment to assign a new todo automatically. - else - .nothing-here-block You're all done! + .todos-empty + .todos-empty-hero + = render "shared/empty_states/todos_empty.svg" + .todos-empty-content + %h4 + Todos let you see what you should do next. + %p + When an issue or merge request is assigned to you, or when you + %strong + @mention + in a comment, this will trigger a new item in your todo list, automatically. + %p + You will always know what to work on next. diff --git a/app/views/shared/empty_states/_todos_all_done.svg b/app/views/shared/empty_states/_todos_all_done.svg new file mode 100644 index 00000000000..94b5c2e0ea0 --- /dev/null +++ b/app/views/shared/empty_states/_todos_all_done.svg @@ -0,0 +1 @@ +<svg viewBox="0 0 293 216"><g fill="none" fill-rule="evenodd"><g transform="rotate(-5 211.388 -693.89)"><rect width="163.6" height="200" x=".2" fill="#FFF" stroke="#EEE" stroke-width="3" stroke-linecap="round" stroke-dasharray="6 9" rx="6"/><g transform="translate(24 38)"><path fill="#FC6D26" d="M18.2 14l-4-3.8c-.4-.6-1.4-.6-2 0-.6.6-.6 1.5 0 2l5 5c.3.4.6.5 1 .5s.8 0 1-.4L28 8.8c.6-.6.6-1.5 0-2-.6-.7-1.6-.7-2 0L18 14z"/><path stroke="#6B4FBB" stroke-width="3" d="M27 23.3V27c0 2.3-1.7 4-4 4H4c-2.3 0-4-1.7-4-4V8c0-2.3 1.7-4 4-4h3.8" stroke-linecap="round"/><rect width="76" height="3" x="40" y="11" fill="#6B4FBB" opacity=".5" rx="1.5"/><rect width="43" height="3" x="40" y="21" fill="#6B4FBB" opacity=".5" rx="1.5"/></g><g transform="translate(24 83)"><path fill="#FC6D26" d="M18.2 14l-4-3.8c-.4-.6-1.4-.6-2 0-.6.6-.6 1.5 0 2l5 5c.3.4.6.5 1 .5s.8 0 1-.4L28 8.8c.6-.6.6-1.5 0-2-.6-.7-1.6-.7-2 0L18 14z"/><path stroke="#6B4FBB" stroke-width="3" d="M27 23.3V27c0 2.3-1.7 4-4 4H4c-2.3 0-4-1.7-4-4V8c0-2.3 1.7-4 4-4h3.8" stroke-linecap="round"/><rect width="76" height="3" x="40" y="11" fill="#B5A7DD" rx="1.5"/><rect width="43" height="3" x="40" y="21" fill="#B5A7DD" rx="1.5"/></g><g transform="translate(24 130)"><path fill="#FC6D26" d="M18.2 14l-4-3.8c-.4-.6-1.4-.6-2 0-.6.6-.6 1.5 0 2l5 5c.3.4.6.5 1 .5s.8 0 1-.4L28 8.8c.6-.6.6-1.5 0-2-.6-.7-1.6-.7-2 0L18 14z"/><path stroke="#6B4FBB" stroke-width="3" d="M27 23.3V27c0 2.3-1.7 4-4 4H4c-2.3 0-4-1.7-4-4V8c0-2.3 1.7-4 4-4h3.8" stroke-linecap="round"/><rect width="76" height="3" x="40" y="11" fill="#B5A7DD" rx="1.5"/><rect width="43" height="3" x="40" y="21" fill="#B5A7DD" rx="1.5"/></g></g><path fill="#FFCE29" d="M30 11l-1.8 4-2-4-4-1.8 4-2 2-4 2 4 4 2M286 60l-2.7 6.3-3-6-6-3 6-3 3-6 2.8 6.2 6.6 2.8M263 97l-2 4-2-4-4-2 4-2 2-4 2 4 4 2M12 85l-2.7 6.3-3-6-6-3 6-3 3-6 2.8 6.2 6.6 2.8"/></g></svg> diff --git a/app/views/shared/empty_states/_todos_empty.svg b/app/views/shared/empty_states/_todos_empty.svg new file mode 100644 index 00000000000..b1e661268fb --- /dev/null +++ b/app/views/shared/empty_states/_todos_empty.svg @@ -0,0 +1,110 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 284 337" xmlns:xlink="http://www.w3.org/1999/xlink"> + <defs> + <rect id="a" width="180" height="220" x="66.2" y="74.4" rx="6"/> + <mask id="l" width="180" height="220" x="0" y="0" fill="#fff"> + <use xlink:href="#a"/> + </mask> + <rect id="b" width="180" height="220" rx="6"/> + <mask id="m" width="180" height="220" x="0" y="0" fill="#fff"> + <use xlink:href="#b"/> + </mask> + <rect id="c" width="28" height="28" rx="4"/> + <mask id="n" width="28" height="28" x="0" y="0" fill="#fff"> + <use xlink:href="#c"/> + </mask> + <rect id="d" width="28" height="28" rx="4"/> + <mask id="o" width="28" height="28" x="0" y="0" fill="#fff"> + <use xlink:href="#d"/> + </mask> + <circle id="e" cx="21.5" cy="21.5" r="21.5"/> + <mask id="p" width="43" height="43" x="0" y="0" fill="#fff"> + <use xlink:href="#e"/> + </mask> + <circle id="f" cx="26.5" cy="26.5" r="26.5"/> + <mask id="q" width="53" height="53" x="0" y="0" fill="#fff"> + <use xlink:href="#f"/> + </mask> + <circle id="g" cx="9.5" cy="4.5" r="4.5"/> + <mask id="r" width="13" height="13" x="-2" y="-2"> + <path fill="#fff" d="M3-2h13v13H3z"/> + <use xlink:href="#g"/> + </mask> + <circle id="h" cx="26.5" cy="26.5" r="26.5"/> + <mask id="s" width="53" height="53" x="0" y="0" fill="#fff"> + <use xlink:href="#h"/> + </mask> + <circle id="i" cx="21.5" cy="21.5" r="21.5"/> + <mask id="t" width="43" height="43" x="0" y="0" fill="#fff"> + <use xlink:href="#i"/> + </mask> + <path id="j" d="M18 38h15c10.5 0 19-8.5 19-19S43.5 0 33 0H19C8.5 0 0 8.5 0 19c0 6.3 3 12 7.8 15.3l5.2 9c.6 1 1.4 1 2 0l3-5.3z"/> + <mask id="u" width="52" height="44" x="0" y="0" fill="#fff"> + <use xlink:href="#j"/> + </mask> + <circle id="k" cx="18.5" cy="18.5" r="18.5"/> + <mask id="v" width="37" height="37" x="0" y="0" fill="#fff"> + <use xlink:href="#k"/> + </mask> + </defs> + <g fill="none" fill-rule="evenodd" transform="translate(-6 -4)"> + <use stroke="#EEE" stroke-width="6" mask="url(#l)" transform="rotate(-5 156.245 184.425)" xlink:href="#a"/> + <g transform="rotate(5 -707.333 618.042)"> + <use fill="#FFF" stroke="#EEE" stroke-width="6" mask="url(#m)" xlink:href="#b"/> + <g transform="translate(29 24)"> + <path fill="#FC6D26" d="M18.2 14l-4-3.8c-.4-.6-1.4-.6-2 0-.6.6-.6 1.5 0 2l5 5c.3.4.6.5 1 .5s.8 0 1-.4L28 8.8c.6-.6.6-1.5 0-2-.6-.7-1.6-.7-2 0L18 14z"/> + <path stroke="#6B4FBB" stroke-width="3" d="M27 23.3V27c0 2.3-1.7 4-4 4H4c-2.3 0-4-1.7-4-4V8c0-2.3 1.7-4 4-4h3.8" stroke-linecap="round"/> + <rect width="86" height="3" x="40" y="11" fill="#6B4FBB" opacity=".5" rx="1.5"/> + <rect width="43" height="3" x="40" y="21" fill="#6B4FBB" opacity=".5" rx="1.5"/> + </g> + <g transform="translate(29 69)"> + <path fill="#FC6D26" d="M18.2 14l-4-3.8c-.4-.6-1.4-.6-2 0-.6.6-.6 1.5 0 2l5 5c.3.4.6.5 1 .5s.8 0 1-.4L28 8.8c.6-.6.6-1.5 0-2-.6-.7-1.6-.7-2 0L18 14z"/> + <path stroke="#6B4FBB" stroke-width="3" d="M27 23.3V27c0 2.3-1.7 4-4 4H4c-2.3 0-4-1.7-4-4V8c0-2.3 1.7-4 4-4h3.8" stroke-linecap="round"/> + <rect width="86" height="3" x="40" y="11" fill="#B5A7DD" rx="1.5"/> + <rect width="43" height="3" x="40" y="21" fill="#B5A7DD" rx="1.5"/> + </g> + <g transform="translate(28 160)"> + <use stroke="#E5E5E5" stroke-width="6" mask="url(#n)" opacity=".7" xlink:href="#c"/> + <rect width="26" height="3" x="41" y="7" fill="#ECECEC" rx="1.5"/> + <rect width="43" height="3" x="41" y="17" fill="#ECECEC" rx="1.5"/> + </g> + <g transform="translate(28 116)"> + <use stroke="#E5E5E5" stroke-width="6" mask="url(#o)" xlink:href="#d"/> + <rect width="86" height="3" x="41" y="7" fill="#E5E5E5" rx="1.5"/> + <rect width="43" height="3" x="41" y="17" fill="#E5E5E5" rx="1.5"/> + </g> + </g> + <g transform="rotate(-15 601.917 -782.362)"> + <use fill="#FFF" stroke="#B5A7DD" stroke-width="6" mask="url(#p)" xlink:href="#e"/> + <text fill="#6B4FBB" font-family="SourceSansPro-Black, Source Sans Pro" font-size="20" font-weight="700" letter-spacing="-.1"> + <tspan x="12" y="27">@</tspan> + </text> + </g> + <g transform="rotate(15 -686.59 1035.907)"> + <use fill="#FFF" stroke="#FDE5D8" stroke-width="6" mask="url(#q)" xlink:href="#f"/> + <path fill="#FC6D26" d="M26.5 38.2c3.3 0 9.5-2.5 9.5-9.6 0-7-2.4-6.6-9.5-6.6-7 0-9.5-.4-9.5 6.6s6.2 9.6 9.5 9.6z"/> + <g transform="translate(17 14)"> + <use fill="#FC6D26" xlink:href="#g"/> + <use stroke="#FFF" stroke-width="4" mask="url(#r)" xlink:href="#g"/> + </g> + </g> + <g transform="rotate(15 -85.125 65.185)"> + <use fill="#FFF" stroke="#B5A7DD" stroke-width="6" mask="url(#s)" xlink:href="#h"/> + <path fill="#6B4FBB" d="M24 18.5c0-1.4 1-2.5 2.5-2.5 1.4 0 2.5 1 2.5 2.5v9c0 1.4-1 2.5-2.5 2.5-1.4 0-2.5-1-2.5-2.5v-9zM26.5 37c1.4 0 2.5-1 2.5-2.5 0-1.4-1-2.5-2.5-2.5-1.4 0-2.5 1-2.5 2.5 0 1.4 1 2.5 2.5 2.5z"/> + </g> + <g transform="rotate(-15 716.492 78.873)"> + <use fill="#FFF" stroke="#FDE5D8" stroke-width="6" mask="url(#t)" xlink:href="#i"/> + <path fill="#FC6D26" d="M20 23v-3h3v3h-3zm0 3v1.5c0 .8-.7 1.5-1.5 1.5s-1.5-.7-1.5-1.5V26h-2.5c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5H17v-3h-1.5c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5H17v-2.5c0-.8.7-1.5 1.5-1.5s1.5.7 1.5 1.5V17h3v-1.5c0-.8.7-1.5 1.5-1.5s1.5.7 1.5 1.5V17h2.5c.8 0 1.5.7 1.5 1.5s-.7 1.5-1.5 1.5H26v3h1.5c.8 0 1.5.7 1.5 1.5s-.7 1.5-1.5 1.5H26v2.5c0 .8-.7 1.5-1.5 1.5s-1.5-.7-1.5-1.5V26h-3z"/> + </g> + <g transform="rotate(-15 129.114 -585.74)"> + <use stroke="#FDE5D8" stroke-width="6" mask="url(#u)" xlink:href="#j"/> + <circle cx="16" cy="20" r="2" fill="#FC6D26"/> + <circle cx="27" cy="20" r="2" fill="#FC6D26"/> + <circle cx="38" cy="20" r="2" fill="#FC6D26"/> + </g> + <g transform="rotate(-15 1254.8 -458.986)"> + <use stroke="#FDE5D8" stroke-width="6" mask="url(#v)" xlink:href="#k"/> + <path fill="#FC6D26" d="M10.6 19l2-2c.5-.5.5-1 0-1.5-.3-.4-1-.4-1.3 0l-2.8 2.8c-.2.2-.3.4-.3.7 0 .3 0 .5.3.7l2.8 2.8c.4.4 1 .4 1.4 0 .4-.4.4-1 0-1.4l-2-2zm14.8 0l-2-2c-.5-.5-.5-1 0-1.5.3-.4 1-.4 1.3 0l2.8 2.8c.2.2.3.4.3.7 0 .3 0 .5-.3.7l-2.8 2.8c-.4.4-1 .4-1.4 0-.4-.4-.4-1 0-1.4l2-2z"/> + <rect width="2" height="7" x="17" y="15.1" fill="#FC6D26" opacity=".5" transform="rotate(15 18.002 18.64)" rx="1"/> + </g> + </g> +</svg> |