Merge pull request #2918 from urbanrotnik/ur-sci-5134

Refactor projects page [SCI-5134]
This commit is contained in:
Alex Kriuchykhin 2020-10-30 13:40:12 +01:00 committed by GitHub
commit ffca4ae022
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 175 additions and 214 deletions

View file

@ -1,63 +1,42 @@
# frozen_string_literal: true
class ProjectsController < ApplicationController
include RenamingUtil
include TeamsHelper
include InputSanitizeHelper
before_action :switch_team_with_param, only: :index
before_action :load_vars, only: %i(show edit update
notifications reports
experiment_archive)
before_action :load_projects_tree, only: %i(sidebar show archive
experiment_archive)
before_action :check_view_permissions, only: %i(show reports notifications
experiment_archive)
before_action :load_vars, only: %i(show edit update notifications experiment_archive)
before_action :load_projects_tree, only: %i(sidebar show experiment_archive index)
before_action :check_view_permissions, only: %i(show notifications experiment_archive)
before_action :check_create_permissions, only: %i(new create)
before_action :check_manage_permissions, only: :edit
before_action :set_inline_name_editing, only: %i(show experiment_archive)
# except parameter could be used but it is not working.
layout 'fluid'
def index
respond_to do |format|
format.json do
@current_team = current_team if current_team
@current_team ||= current_user.teams.first
@projects = ProjectsOverviewService
.new(@current_team, current_user, params)
.project_cards
render json: {
html: render_to_string(
partial: 'projects/index/team_projects.html.erb',
locals: { projects: @projects }
),
count: @projects.size
}
end
format.html do
@teams = current_user.teams
# New project for create new project modal
@project = Project.new
if current_team
view_state =
current_team.current_view_state(current_user)
@current_filter = view_state.state.dig('projects', 'filter')
@current_sort = view_state.state.dig('projects', 'cards', 'sort')
end
load_projects_tree
end
if current_team
view_state = current_team.current_view_state(current_user)
@current_filter = view_state.state.dig('projects', 'filter')
@current_sort = view_state.state.dig('projects', 'cards', 'sort')
end
end
def cards
projects = ProjectsOverviewService.new(current_team, current_user, params).project_cards
render json: {
html: render_to_string(partial: 'projects/index/team_projects.html.erb', locals: { projects: projects }),
count: projects.size
}
end
def index_dt
@draw = params[:draw].to_i
respond_to do |format|
format.json do
@current_team = current_team if current_team
@current_team ||= current_user.teams.first
@projects = ProjectsOverviewService
.new(@current_team, current_user, params)
.projects_datatable
team = current_team || current_user.teams.first
@projects = ProjectsOverviewService.new(team, current_user, params).projects_datatable
end
end
end
@ -84,10 +63,6 @@ class ProjectsController < ApplicationController
end
end
def new
@project = Project.new
end
def create
@project = Project.new(project_params)
@project.created_by = current_user
@ -105,32 +80,24 @@ class ProjectsController < ApplicationController
message = t('projects.create.success_flash', name: escape_input(@project.name))
respond_to do |format|
format.json {
format.json do
render json: { message: message }, status: :ok
}
end
end
else
respond_to do |format|
format.json {
format.json do
render json: @project.errors, status: :unprocessable_entity
}
end
end
end
end
def edit
respond_to do |format|
format.json {
render json: {
html: render_to_string({
partial: "edit.html.erb",
locals: { project: @project }
}),
title: t('projects.index.modal_edit_project.modal_title',
project: escape_input(@project.name))
}
}
end
render json: {
html: render_to_string({ partial: 'edit.html.erb', locals: { project: @project } }),
title: t('projects.index.modal_edit_project.modal_title', project: escape_input(@project.name))
}
end
def update
@ -258,6 +225,10 @@ class ProjectsController < ApplicationController
current_team_switch(@project.team)
end
def dt_state_load
render json: { state: current_team&.current_view_state(current_user)&.state&.dig('projects', 'table') }
end
private
def project_params
@ -265,11 +236,9 @@ class ProjectsController < ApplicationController
end
def load_vars
@project = Project.find_by_id(params[:id])
@project = Project.find_by(id: params[:id])
unless @project
render_404
end
render_404 unless @project
end
def load_projects_tree
@ -299,6 +268,7 @@ class ProjectsController < ApplicationController
def set_inline_name_editing
return unless can_manage_project?(@project)
@inline_editable_title_config = {
name: 'title',
params_group: 'project',

View file

@ -1,8 +0,0 @@
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<%= form.text_field :name, label: t("projects.index.modal_new_project.name"), autofocus: true, placeholder: t("projects.index.modal_new_project.name_placeholder") %>
<%= hidden_field :project, :team_id, value: current_team.id if current_team %>
</div>
</div>
<%= form.enum_btn_group :visibility, label: t("projects.index.modal_new_project.visibility"), btn_names: { hidden: t("projects.index.modal_new_project.visibility_hidden"), visible: t("projects.index.modal_new_project.visibility_visible") } %>

View file

@ -1,4 +1,3 @@
<% provide(:head_title, t("projects.index.head_title")) %>
<% if current_team %>
@ -7,163 +6,44 @@
<span style="display: none;" data-hook="projects-index-html"></span>
<% if can_create_projects?(current_team) %>
<!-- New project modal -->
<div class="modal" id="new-project-modal" tabindex="-1" role="dialog" aria-labelledby="new-project-modal-label">
<%= bootstrap_form_for @project, remote: true do |f| %>
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="new-project-modal-label"><%= t("projects.index.modal_new_project.modal_title") %></h4>
</div>
<div class="modal-body">
<%= render partial: "new.html.erb", locals: { form: f, teams: @teams } %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal"><%=t "general.cancel" %></button>
<%= f.button t("projects.index.modal_new_project.create"), class: "btn btn-primary" %>
</div>
</div>
</div>
<% end %>
</div>
<% end %>
<!-- Edit project modal -->
<div class="modal" id="edit-project-modal" tabindex="-1" role="dialog" aria-labelledby="edit-project-modal-label">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="edit-project-modal-label"></h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal"><%=t "general.cancel" %></button>
<button type="button" class="btn btn-primary" data-action="submit"><%=t "projects.index.modal_edit_project.submit" %></button>
</div>
</div>
</div>
</div>
<!-- Manage users modal -->
<div class="modal" id="project-actions-modal" tabindex="-1" role="dialog" aria-labelledby="project-actions-modal-label">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="project-actions-modal-label"></h4>
</div>
<div class="modal-body"></div>
<div class="modal-footer"></div>
</div>
</div>
</div>
<!-- Export projects modal -->
<div class="modal" id="export-projects-modal" tabindex="-1" role="dialog" aria-labelledby="export-projects-modal-label">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="export-projects-modal-label"></h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button id="export-projects-modal-close" type="button" class="btn btn-secondary" data-dismiss="modal"><%=t "general.close" %></button>
<button id="export-projects-modal-cancel" type="button" class="btn btn-secondary" data-dismiss="modal"><%=t "general.cancel" %></button>
<button id="export-projects-modal-submit"
type="button"
class="btn btn-primary"
data-export-projects-submit-url="<%= export_projects_team_path(current_team) %>">
<%=t "projects.export_projects.modal_submit" %>
</button>
</div>
</div>
</div>
</div>
<%= render partial: 'projects/index/modals/new' %>
<%= render partial: 'projects/index/modals/edit' %>
<%= render partial: 'projects/index/modals/manage_users' %>
<%= render partial: 'projects/index/modals/export_projects' %>
<div class="content-pane" id="projects-index">
<div id="projects-absent" style="display:none">
<div class="jumbotron text-center" style="margin-top:12%">
<strong><%=t 'projects.index.no_projects.text' %></strong>
<% if @teams.exists? && can_create_projects?(current_team) %>
<h2><strong><%=t 'projects.index.no_projects.title' %></strong></h2>
<br />
<strong><%= t 'projects.index.no_projects.text' %></strong>
<% if can_create_projects?(current_team) %>
<h2><strong><%= t 'projects.index.no_projects.title' %></strong></h2>
<br/>
<a class="btn btn-primary new-project-btn">
<span class="fas fa-plus"></span>
<span class="hidden-xs"><%= t('projects.index.no_projects.create_new_button') %></span>
</a>
<% else %>
<p><strong><%=t 'projects.index.no_projects.no_permission_title' %></strong></p>
<p><strong><%= t 'projects.index.no_projects.no_permission_title' %></strong></p>
<% end %>
</div>
</div>
<div id="projects-present" style="display:none">
<div id="projects-toolbar">
<form class="form-inline" action="<%= projects_path %>">
<div class="form-group">
<% if @teams.exists? && can_create_projects?(current_team) %>
<!-- new project button -->
<a class="btn btn-primary new-project-btn">
<span class="fas fa-plus" aria-hidden="true"></span>
<span class="hidden-xs"><%=t "projects.index.new" %></span>
</a>
<% end %>
<!-- project sort -->
<div class="dropdown">
<button class="btn btn-light dropdown-toggle" type="button" id="sortMenu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<span><%= t("general.sort.#{@current_sort}_html") %></span>
<span class="caret"></span>
</button>
<ul id="sortMenuDropdown" class="dropdown-menu" aria-labelledby="sortMenu">
<% ["new", "old", "atoz", "ztoa"].each do |sort| %>
<li>
<% if @current_sort != sort %>
<a href="#" data-sort="<%= sort %>"><%= t("general.sort.#{sort}_html") %></a>
<% else %>
<a class="disabled" href="#" data-sort="<%= sort %>"><%= t("general.sort.#{sort}_html") %></a>
<% end %>
</li>
<% end %>
</ul>
</div>
<!-- export projects button -->
<button type="button" class="btn btn-secondary pull-right"
id="export-projects-button"
data-export-projects-modal-url="<%= export_projects_modal_team_path(current_team) %>"
disabled>
<span class="fas fa-file-export"></span>
<span class="hidden-xs-custom"><%= t("projects.export_projects.export_button") %></span>
</button>
</div>
</form>
</div>
<%= render partial: 'projects/index/toolbar' %>
<div class="tab-content">
<div class="tab-pane active"
id="projects-cards-view"
data-projects-url="<%= projects_path %>"
data-projects-url="<%= cards_projects_path %>"
data-projects-sidebar-url="<%= projects_sidebar_path %>">
</div>
<div class="tab-pane" id="projects-table-view">
<%= render partial: "projects/index/team_projects_table" %>
</div>
</div>
</div>
</div>
<% end %>
<%= javascript_include_tag "projects/index" %>

View file

@ -0,0 +1,41 @@
<div id="projects-toolbar">
<form class="form-inline" action="<%= projects_path %>">
<div class="form-group">
<% if can_create_projects?(current_team) %>
<!-- new project button -->
<a class="btn btn-primary new-project-btn">
<span class="fas fa-plus" aria-hidden="true"></span>
<span class="hidden-xs"><%= t "projects.index.new" %></span>
</a>
<% end %>
<!-- project sort -->
<div class="dropdown">
<button class="btn btn-light dropdown-toggle" type="button" id="sortMenu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<span><%= t("general.sort.#{@current_sort}_html") %></span>
<span class="caret"></span>
</button>
<ul id="sortMenuDropdown" class="dropdown-menu" aria-labelledby="sortMenu">
<% ["new", "old", "atoz", "ztoa"].each do |sort| %>
<li>
<% if @current_sort != sort %>
<a href="#" data-sort="<%= sort %>"><%= t("general.sort.#{sort}_html") %></a>
<% else %>
<a class="disabled" href="#" data-sort="<%= sort %>"><%= t("general.sort.#{sort}_html") %></a>
<% end %>
</li>
<% end %>
</ul>
</div>
<!-- export projects button -->
<button type="button" class="btn btn-secondary pull-right"
id="export-projects-button"
data-export-projects-modal-url="<%= export_projects_modal_team_path(current_team) %>"
disabled>
<span class="fas fa-file-export"></span>
<span class="hidden-xs-custom"><%= t("projects.export_projects.export_button") %></span>
</button>
</div>
</form>
</div>

View file

@ -0,0 +1,16 @@
<div class="modal" id="edit-project-modal" tabindex="-1" role="dialog" aria-labelledby="edit-project-modal-label">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="edit-project-modal-label"></h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal"><%=t "general.cancel" %></button>
<button type="button" class="btn btn-primary" data-action="submit"><%=t "projects.index.modal_edit_project.submit" %></button>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,22 @@
<div class="modal" id="export-projects-modal" tabindex="-1" role="dialog" aria-labelledby="export-projects-modal-label">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="export-projects-modal-label"></h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button id="export-projects-modal-close" type="button" class="btn btn-secondary" data-dismiss="modal"><%=t "general.close" %></button>
<button id="export-projects-modal-cancel" type="button" class="btn btn-secondary" data-dismiss="modal"><%=t "general.cancel" %></button>
<button id="export-projects-modal-submit"
type="button"
class="btn btn-primary"
data-export-projects-submit-url="<%= export_projects_team_path(current_team) %>">
<%=t "projects.export_projects.modal_submit" %>
</button>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,12 @@
<div class="modal" id="project-actions-modal" tabindex="-1" role="dialog" aria-labelledby="project-actions-modal-label">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="project-actions-modal-label"></h4>
</div>
<div class="modal-body"></div>
<div class="modal-footer"></div>
</div>
</div>
</div>

View file

@ -0,0 +1,28 @@
<% if can_create_projects?(current_team) %>
<div class="modal" id="new-project-modal" tabindex="-1" role="dialog" aria-labelledby="new-project-modal-label">
<%= bootstrap_form_for Project.new, remote: true do |f| %>
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="new-project-modal-label"><%= t("projects.index.modal_new_project.modal_title") %></h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<%= f.text_field :name, label: t("projects.index.modal_new_project.name"), autofocus: true, placeholder: t("projects.index.modal_new_project.name_placeholder") %>
<%= hidden_field :project, :team_id, value: current_team.id if current_team %>
</div>
</div>
<%= f.enum_btn_group :visibility, label: t("projects.index.modal_new_project.visibility"), btn_names: { hidden: t("projects.index.modal_new_project.visibility_hidden"), visible: t("projects.index.modal_new_project.visibility_visible") } %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal"><%=t "general.cancel" %></button>
<%= f.button t("projects.index.modal_new_project.create"), class: "btn btn-primary" %>
</div>
</div>
</div>
<% end %>
</div>
<% end %>

View file

@ -195,8 +195,7 @@ Rails.application.routes.draw do
post 'projects/index_dt', to: 'projects#index_dt', as: 'projects_index_dt'
get 'projects/sidebar', to: 'projects#sidebar', as: 'projects_sidebar'
get 'projects/dt_state_load', to: 'projects#dt_state_load',
as: 'projects_dt_state_load'
get 'projects/dt_state_load', to: 'projects#dt_state_load', as: 'projects_dt_state_load'
resources :reports, only: :index
get 'reports/datatable', to: 'reports#datatable'
@ -296,6 +295,10 @@ Rails.application.routes.draw do
# This route is defined outside of member block
# to preserve original :project_id parameter in URL.
get 'users/edit', to: 'user_projects#index_edit'
collection do
get 'cards'
end
end
resources :experiments do

View file

@ -65,14 +65,11 @@ describe ProjectsController, type: :controller do
# rubocop:enable Style/EvalWithLocation
describe '#index' do
context 'in JSON format' do
let(:params) { { team: team.id, sort: 'atoz' } }
let(:params) { { team: team.id, sort: 'atoz' } }
it 'returns success response' do
get :index, params: params, format: :json
expect(response).to have_http_status(:success)
expect(response.media_type).to eq 'application/json'
end
it 'returns success response' do
get :index, params: params
expect(response).to have_http_status(:success)
end
end