diff --git a/app/assets/javascripts/pages/dashboard/todos/vue/index.js b/app/assets/javascripts/pages/dashboard/todos/vue/index.js new file mode 100644 index 0000000000000000000000000000000000000000..3829b9845dff19cc786739cab20aad1dff82484a --- /dev/null +++ b/app/assets/javascripts/pages/dashboard/todos/vue/index.js @@ -0,0 +1,3 @@ +import initTodosApp from '~/todos'; + +initTodosApp(); diff --git a/app/assets/javascripts/todos/components/todos_app.vue b/app/assets/javascripts/todos/components/todos_app.vue new file mode 100644 index 0000000000000000000000000000000000000000..282d3173b0110b6100727c409a8accbeba396377 --- /dev/null +++ b/app/assets/javascripts/todos/components/todos_app.vue @@ -0,0 +1,5 @@ +<script> +export default {}; +</script> + +<template><div></div></template> diff --git a/app/assets/javascripts/todos/index.js b/app/assets/javascripts/todos/index.js new file mode 100644 index 0000000000000000000000000000000000000000..6bd24f65d3fb67e9356fe52bb22dff6bb58aa8ea --- /dev/null +++ b/app/assets/javascripts/todos/index.js @@ -0,0 +1,17 @@ +import Vue from 'vue'; +import TodosApp from './components/todos_app.vue'; + +export default () => { + const el = document.getElementById('js-todos-app-root'); + + if (!el) { + return false; + } + + return new Vue({ + el, + render(createElement) { + return createElement(TodosApp); + }, + }); +}; diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb index b1a8ac351bf9b1012135a6caef8c6086a6c52e5c..d06d053a3d11c212fb33167daa72400da2ca4bb8 100644 --- a/app/controllers/dashboard/todos_controller.rb +++ b/app/controllers/dashboard/todos_controller.rb @@ -22,6 +22,10 @@ def index @allowed_todos = ::Todos::AllowedTargetFilterService.new(@todos, current_user).execute end + def vue + redirect_to(dashboard_todos_path, status: :found) unless Feature.enabled?(:todos_vue_application, current_user) + end + def destroy todo = current_user.todos.find(params[:id]) diff --git a/app/views/dashboard/todos/_user_has_no_todos.html.haml b/app/views/dashboard/todos/_user_has_no_todos.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..fa383ecba1f02eae80e23934cd71255b7aca2a36 --- /dev/null +++ b/app/views/dashboard/todos/_user_has_no_todos.html.haml @@ -0,0 +1,8 @@ += render Pajamas::EmptyStateComponent.new(svg_path: 'illustrations/empty-todos-md.svg', + title: s_("Todos|Your To-Do List shows what to work on next")) do |c| + + - c.with_description do + %p + = (s_("Todos|When an issue or merge request is assigned to you, or when you receive a %{strongStart}@mention%{strongEnd} in a comment, this automatically triggers a new item in your To-Do List.") % { strongStart: '<strong>', strongEnd: '</strong>' }).html_safe + %p + = s_("Todos|It's how you always know what to work on next.") diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index ee92fd85774984e57144508001d6aea0ec2b1643..4bc7e7c5f29ebfbbe3d2ce6cd99d0875e7fbeff6 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -114,11 +114,4 @@ = link_to s_("Todos|Do you want to remove the filters?"), todos_filter_path(without: [:project_id, :author_id, :type, :action_id]) - else - = render Pajamas::EmptyStateComponent.new(svg_path: 'illustrations/empty-todos-md.svg', - title: s_("Todos|Your To-Do List shows what to work on next")) do |c| - - - c.with_description do - %p - = (s_("Todos|When an issue or merge request is assigned to you, or when you receive a %{strongStart}@mention%{strongEnd} in a comment, this automatically triggers a new item in your To-Do List.") % { strongStart: '<strong>', strongEnd: '</strong>' }).html_safe - %p - = s_("Todos|It's how you always know what to work on next.") + = render 'dashboard/todos/user_has_no_todos' diff --git a/app/views/dashboard/todos/vue.html.haml b/app/views/dashboard/todos/vue.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..a4e74116693182718fa5fc40e342b1f9d15e2035 --- /dev/null +++ b/app/views/dashboard/todos/vue.html.haml @@ -0,0 +1,17 @@ +- page_title _("To-Do List") + += render_two_factor_auth_recovery_settings_check += render_dashboard_ultimate_trial(current_user) + += render_if_exists 'shared/dashboard/saml_reauth_notice', + groups_requiring_saml_reauth: todo_groups_requiring_saml_reauth(@todos) + +- add_page_specific_style 'page_bundles/todos' +- add_issuable_stylesheet +- user_has_todos = current_user.todos.any? + +- if user_has_todos + = render ::Layouts::PageHeadingComponent.new(_('To-Do List')) + #js-todos-app-root +- else + = render 'dashboard/todos/user_has_no_todos' diff --git a/config/feature_flags/wip/todos_vue_application.yml b/config/feature_flags/wip/todos_vue_application.yml new file mode 100644 index 0000000000000000000000000000000000000000..c06f58f74d6818fc3ff951f9998dbcbbab60887f --- /dev/null +++ b/config/feature_flags/wip/todos_vue_application.yml @@ -0,0 +1,9 @@ +--- +name: todos_vue_application +feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/464069 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/162587 +rollout_issue_url: +milestone: '17.4' +group: group::personal productivity +type: wip +default_enabled: false diff --git a/config/routes/dashboard.rb b/config/routes/dashboard.rb index a9b4582a1a4ab5188c296e93cd832986858c2581..a78775f9afef3adac4a40446e4109046f634a752 100644 --- a/config/routes/dashboard.rb +++ b/config/routes/dashboard.rb @@ -16,6 +16,7 @@ resources :todos, only: [:index, :destroy] do collection do + get :vue delete :destroy_all patch :bulk_restore end diff --git a/spec/controllers/dashboard/todos_controller_spec.rb b/spec/controllers/dashboard/todos_controller_spec.rb index b66ad8f1e3c2304d63cda9d57b1e475b09f30c22..9f5bd1a1a56be81875aae70f503110dfcc7d6c66 100644 --- a/spec/controllers/dashboard/todos_controller_spec.rb +++ b/spec/controllers/dashboard/todos_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Dashboard::TodosController do +RSpec.describe Dashboard::TodosController, feature_category: :notifications do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, developers: user) } let_it_be(:author) { create(:user) } @@ -157,6 +157,32 @@ end end + describe 'GET #vue' do + context 'with todos_vue_application on' do + before do + stub_feature_flags(todos_vue_application: true) + end + + it 'renders 200' do + get :vue + + expect(response).to have_gitlab_http_status(:ok) + end + end + + context 'with todos_vue_application off' do + before do + stub_feature_flags(todos_vue_application: false) + end + + it 'redirects to #index' do + get :vue + + expect(response).to redirect_to dashboard_todos_path + end + end + end + describe 'PATCH #restore' do let(:todo) { create(:todo, :done, user: user, project: project, author: author) }