diff options
author | Douglas Barbosa Alexandre <dbalexandre@gmail.com> | 2016-02-12 16:45:44 -0200 |
---|---|---|
committer | Douglas Barbosa Alexandre <dbalexandre@gmail.com> | 2016-02-20 12:10:26 -0200 |
commit | 7cafa2ce923df9c034ba0b64907b4b6eb6b3c1e2 (patch) | |
tree | e5c69ddd538f291e6271c4d25db6dde02c75cf0c | |
parent | 41d8f5649e3c8a1e37be4608fd03153005c3fa58 (diff) | |
download | gitlab-ce-7cafa2ce923df9c034ba0b64907b4b6eb6b3c1e2.tar.gz |
Add tasks queue list page
-rw-r--r-- | app/assets/stylesheets/pages/tasks.scss | 90 | ||||
-rw-r--r-- | app/controllers/dashboard/tasks_controller.rb | 15 | ||||
-rw-r--r-- | app/helpers/tasks_helper.rb | 17 | ||||
-rw-r--r-- | app/models/task.rb | 23 | ||||
-rw-r--r-- | app/views/dashboard/tasks/_task.html.haml | 17 | ||||
-rw-r--r-- | app/views/dashboard/tasks/index.html.haml | 25 | ||||
-rw-r--r-- | config/routes.rb | 1 | ||||
-rw-r--r-- | spec/models/task_spec.rb | 23 |
8 files changed, 211 insertions, 0 deletions
diff --git a/app/assets/stylesheets/pages/tasks.scss b/app/assets/stylesheets/pages/tasks.scss new file mode 100644 index 00000000000..702d7c55e59 --- /dev/null +++ b/app/assets/stylesheets/pages/tasks.scss @@ -0,0 +1,90 @@ +/** + * Dashboard tasks queue + * + */ +.tasks { + .panel { + border-top: none; + margin-bottom: 0; + } +} + +.task-item { + font-size: $gl-font-size; + padding: $gl-padding-top 0 $gl-padding-top ($gl-avatar-size + $gl-padding-top); + border-bottom: 1px solid $table-border-color; + color: #7f8fa4; + + &.task-inline { + .avatar { + position: relative; + top: -2px; + } + + .task-title { + line-height: 40px; + } + } + + a { + color: #4c4e54; + } + + .avatar { + margin-left: -($gl-avatar-size + $gl-padding-top); + } + + .task-title { + @include str-truncated(calc(100% - 174px)); + font-weight: 600; + + .author_name { + color: #333; + } + } + + .task-body { + margin-right: 174px; + + .task-note { + word-wrap: break-word; + + pre { + border: none; + background: #f9f9f9; + border-radius: 0; + color: #777; + margin: 0 20px; + overflow: hidden; + } + + p:last-child { + margin-bottom: 0; + } + } + } + + &:last-child { border:none } +} + +@media (max-width: $screen-xs-max) { + .task-item { + padding-left: $gl-padding; + + .task-title { + white-space: normal; + overflow: visible; + max-width: 100%; + } + + .avatar { + display: none; + } + + .task-body { + margin: 0; + border-left: 2px solid #DDD; + padding-left: 10px; + } + } +} diff --git a/app/controllers/dashboard/tasks_controller.rb b/app/controllers/dashboard/tasks_controller.rb new file mode 100644 index 00000000000..66d891e3dfa --- /dev/null +++ b/app/controllers/dashboard/tasks_controller.rb @@ -0,0 +1,15 @@ +class Dashboard::TasksController < Dashboard::ApplicationController + def index + @tasks = case params[:state] + when 'done' + current_user.tasks.done + else + current_user.tasks.pending + end + + @tasks = @tasks.page(params[:page]).per(PER_PAGE) + + @pending_count = current_user.tasks.pending.count + @done_count = current_user.tasks.done.count + end +end diff --git a/app/helpers/tasks_helper.rb b/app/helpers/tasks_helper.rb new file mode 100644 index 00000000000..4a87f8d4ca4 --- /dev/null +++ b/app/helpers/tasks_helper.rb @@ -0,0 +1,17 @@ +module TasksHelper + def link_to_author(task) + author = task.author + + if author + link_to author.name, user_path(author.username) + else + task.author_name + end + end + + def task_action_name(task) + target = task.target_type.titleize.downcase + + [task.action_name, target].join(" ") + end +end diff --git a/app/models/task.rb b/app/models/task.rb index 5f102dd66b8..37e752bd350 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -15,15 +15,38 @@ # class Task < ActiveRecord::Base + ASSIGNED = 1 + belongs_to :author, class_name: "User" belongs_to :project belongs_to :target, polymorphic: true, touch: true belongs_to :user + delegate :name, :email, to: :author, prefix: true, allow_nil: true + validates :action, :project, :target, :user, presence: true + default_scope { reorder(id: :desc) } + + scope :pending, -> { with_state(:pending) } + scope :done, -> { with_state(:done) } + state_machine :state, initial: :pending do state :pending state :done end + + def action_name + case action + when ASSIGNED then 'assigned' + end + end + + def body? + target.respond_to? :title + end + + def target_iid + target.respond_to?(:iid) ? target.iid : target_id + end end diff --git a/app/views/dashboard/tasks/_task.html.haml b/app/views/dashboard/tasks/_task.html.haml new file mode 100644 index 00000000000..c7b952f0cb5 --- /dev/null +++ b/app/views/dashboard/tasks/_task.html.haml @@ -0,0 +1,17 @@ +%li{class: "task task-#{task.done? ? 'done' : 'pending'}", id: dom_id(task) } + .task-item{class: "#{task.body? ? 'task-block' : 'task-inline' }"} + = image_tag avatar_icon(task.author_email, 40), class: "avatar s40", alt:'' + + .task-title + %span.author_name= link_to_author task + %span.task_label{class: task.action_name} + = task_action_name(task) + + %strong= link_to "##{task.target_iid}", [task.project.namespace.becomes(Namespace), task.project, task.target] + + · #{time_ago_with_tooltip(task.created_at)} + + - if task.body? + .task-body + .task-note + = task.target.title diff --git a/app/views/dashboard/tasks/index.html.haml b/app/views/dashboard/tasks/index.html.haml new file mode 100644 index 00000000000..877c69185c4 --- /dev/null +++ b/app/views/dashboard/tasks/index.html.haml @@ -0,0 +1,25 @@ +- page_title "Tasks Queue" +- header_title "Tasks Queue", dashboard_tasks_path + +.top-area + %ul.nav-links + %li{class: ("active" if params[:state].blank? || params[:state] == 'pending')} + = link_to dashboard_tasks_path(state: 'pending') do + Tasks (#{@pending_count}) + %li{class: ("active" if params[:state] == 'done')} + = link_to dashboard_tasks_path(state: 'done') do + Done (#{@done_count}) + +.tasks + - if @tasks.any? + - @tasks.group_by(&:project).each do |group| + .panel.panel-default + - project = group[0] + .panel-heading + = link_to project.name_with_namespace, namespace_project_path(project.namespace, project) + + %ul.well-list.tasks-list + = render group[1] + = paginate @tasks, theme: "gitlab" + - else + .nothing-here-block No tasks to show diff --git a/config/routes.rb b/config/routes.rb index 0ed3f1731f8..17c0bb22a8c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -333,6 +333,7 @@ Rails.application.routes.draw do resources :groups, only: [:index] resources :snippets, only: [:index] + resources :tasks, only: [:index] resources :projects, only: [:index] do collection do diff --git a/spec/models/task_spec.rb b/spec/models/task_spec.rb index 950d9b74196..86317626cc3 100644 --- a/spec/models/task_spec.rb +++ b/spec/models/task_spec.rb @@ -24,9 +24,32 @@ describe Task, models: true do it { is_expected.to belong_to(:user) } end + describe 'respond to' do + it { is_expected.to respond_to(:author_name) } + it { is_expected.to respond_to(:author_email) } + end + describe 'validations' do it { is_expected.to validate_presence_of(:action) } it { is_expected.to validate_presence_of(:target) } it { is_expected.to validate_presence_of(:user) } end + + describe '#action_name' do + it 'returns assigned when action is assigned' do + subject.action = Task::ASSIGNED + + expect(subject.action_name).to eq 'assigned' + end + end + + describe '#body?' do + it 'returns true when target respond to title' + it 'returns false when target does not respond to title' + end + + describe '#target_iid' do + it 'returns target.iid when target respond to iid' + it 'returns target_id when target does not respond to iid' + end end |