Added #roles #trackers #decription to custom field settings
This commit is contained in:
parent
5d2e8ff82a
commit
329c81dc41
@ -152,7 +152,8 @@ class CustomTablesController < ApplicationController
|
||||
|
||||
def setting_tabs
|
||||
@setting_tabs = [
|
||||
{name: 'general', partial: 'custom_tables/edit', label: :label_general}
|
||||
{name: 'general', partial: 'custom_tables/edit', label: :label_general},
|
||||
{name: 'custom_fields', partial: 'custom_tables/settings/custom_fields', label: :label_custom_field_plural}
|
||||
]
|
||||
call_hook(:controller_setting_tabs_after, { setting_tabs: @setting_tabs, custom_table: @custom_table })
|
||||
end
|
||||
|
@ -6,6 +6,8 @@ class CustomTable < ActiveRecord::Base
|
||||
has_many :custom_entities, dependent: :destroy
|
||||
has_one :custom_entity
|
||||
has_and_belongs_to_many :projects
|
||||
has_and_belongs_to_many :trackers
|
||||
has_and_belongs_to_many :roles
|
||||
|
||||
acts_as_nested_set
|
||||
|
||||
@ -20,7 +22,22 @@ class CustomTable < ActiveRecord::Base
|
||||
end
|
||||
}
|
||||
|
||||
safe_attributes 'name', 'author_id', 'main_custom_field_id', 'project_ids', 'is_for_all'
|
||||
scope :visible, lambda {|*args|
|
||||
user = args.shift || User.current
|
||||
if user.admin?
|
||||
# nop
|
||||
elsif user.memberships.any?
|
||||
where("#{table_name}.visible = ? OR #{table_name}.id IN (SELECT DISTINCT cfr.custom_table_id FROM #{Member.table_name} m" +
|
||||
" INNER JOIN #{MemberRole.table_name} mr ON mr.member_id = m.id" +
|
||||
" INNER JOIN #{table_name_prefix}custom_tables_roles#{table_name_suffix} cfr ON cfr.role_id = mr.role_id" +
|
||||
" WHERE m.user_id = ?)",
|
||||
true, user.id)
|
||||
else
|
||||
where(:visible => true)
|
||||
end
|
||||
}
|
||||
|
||||
safe_attributes 'name', 'author_id', 'main_custom_field_id', 'project_ids', 'is_for_all', 'description', 'tracker_ids', 'role_ids', 'visible'
|
||||
|
||||
validates :name, presence: true, uniqueness: true
|
||||
|
||||
|
@ -1,11 +1,4 @@
|
||||
<%= labelled_form_for :custom_table, @custom_table, url: custom_table_path(project_id: @project), html: {multipart: true, id: 'custom_table_form'} do |f| %>
|
||||
<%= render partial: 'form', locals: {f: f} %>
|
||||
<% tab = {name: 'CustomEntityCustomField', partial: 'table_fields/index', label: :label_spent_time} %>
|
||||
|
||||
<%= content_tag('div', render(partial: 'table_fields/index', locals: {tab: tab, f: f})) %>
|
||||
|
||||
<%= javascript_tag do %>
|
||||
$(function() { $("table.custom_fields tbody").positionedItems(); });
|
||||
<% end %>
|
||||
<%= submit_tag l(:button_update) %>
|
||||
<% end %>
|
@ -1,15 +1,49 @@
|
||||
<%= error_messages_for @custom_table %>
|
||||
|
||||
<div class="splitcontentleft">
|
||||
<fieldset class="box"><legend><%= l :label_general %></legend>
|
||||
<div class = "tabular" >
|
||||
<p><%= f.text_field :name %></p>
|
||||
</div>
|
||||
<div class="box tabular">
|
||||
<p><%= f.text_field :name, size: 50, required: true %></p>
|
||||
<p><%= f.text_area :description, rows: 7 %></p>
|
||||
</div>
|
||||
|
||||
<fieldset class="box" id="custom_table_tracker_ids"><legend><%= toggle_checkboxes_link("#custom_table_tracker_ids input[type=checkbox]") %><%=l(:label_tracker_plural)%></legend>
|
||||
<% tracker_ids = @custom_table.tracker_ids %>
|
||||
<% Tracker.sorted.each do |tracker| %>
|
||||
<%= check_box_tag "custom_table[tracker_ids][]",
|
||||
tracker.id,
|
||||
tracker_ids.include?(tracker.id),
|
||||
:id => "custom_table_tracker_ids_#{tracker.id}" %>
|
||||
<label class="no-css" for="custom_table_tracker_ids_<%=tracker.id%>">
|
||||
<%= tracker.name %>
|
||||
</label>
|
||||
<% end %>
|
||||
<%= hidden_field_tag "custom_table[tracker_ids][]", '' %>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div class="splitcontentright">
|
||||
<fieldset class="box tabular"><legend><%= l(:field_visible) %></legend>
|
||||
<label class="block">
|
||||
<%= radio_button_tag 'custom_table[visible]', 1, @custom_table.visible?, :id => 'custom_table_visible_on',
|
||||
onclick: "window.ToggleCheckboxes.roles(true)" %>
|
||||
<%= l(:label_visibility_public) %>
|
||||
</label>
|
||||
<label class="block">
|
||||
<%= radio_button_tag 'custom_table[visible]', 0, !@custom_table.visible?, :id => 'custom_table_visible_off', onclick: "window.ToggleCheckboxes.roles(false)" %>
|
||||
<%= l(:label_visibility_roles) %>:
|
||||
</label>
|
||||
<% role_ids = @custom_table.role_ids %>
|
||||
<% Role.givable.sorted.each do |role| %>
|
||||
<label class="block custom_table_role" style="padding-left:2em;">
|
||||
<%= check_box_tag 'custom_table[role_ids][]', role.id, role_ids.include?(role.id), :id => nil, class: 'custom_table_roles_radio', disabled: f.object.visible? %>
|
||||
<%= role.name %>
|
||||
</label>
|
||||
<% end %>
|
||||
<%= hidden_field_tag 'custom_table[role_ids][]', '' %>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="box"><legend><%= toggle_checkboxes_link("#custom_table_project_ids input[type=checkbox]:enabled") %><%= l(:label_project_plural) %></legend>
|
||||
<p><%= f.check_box :is_for_all, onclick: "window.AllProjects.toggle($(this).is(':checked'))" %></p>
|
||||
<p><%= f.check_box :is_for_all, onclick: "window.ToggleCheckboxes.projects($(this).is(':checked'))" %></p>
|
||||
|
||||
<div id="custom_field_project_ids">
|
||||
<% project_ids = @custom_table.project_ids.to_a %>
|
||||
@ -22,9 +56,12 @@
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
window.AllProjects = {
|
||||
toggle: function(checked){
|
||||
window.ToggleCheckboxes = {
|
||||
projects: function(checked){
|
||||
$(".custom_table_project_checkbox").prop('disabled', checked);
|
||||
},
|
||||
roles: function(checked){
|
||||
$(".custom_table_roles_radio").prop('disabled', checked);
|
||||
},
|
||||
}
|
||||
</script>
|
@ -1,4 +1,4 @@
|
||||
<%= title [l(:label_custom_tables), custom_tables_path], [@custom_table.name, custom_table_path(@custom_table)], l(:label_settings) %>
|
||||
<%= render_tabs @setting_tabs %>
|
||||
<%= render_tabs @setting_tabs, params[:tab] %>
|
||||
|
||||
<% html_title(l(:label_settings)) -%>
|
10
app/views/custom_tables/settings/_custom_fields.html.erb
Normal file
10
app/views/custom_tables/settings/_custom_fields.html.erb
Normal file
@ -0,0 +1,10 @@
|
||||
<%= labelled_form_for :custom_table, @custom_table, url: custom_table_path(project_id: @project, back_url: edit_custom_table_path(@custom_table, tab: 'custom_fields')), html: {multipart: true, id: 'custom_table_form'} do |f| %>
|
||||
<% tab = {name: 'CustomEntityCustomField', partial: 'table_fields/index', label: :label_spent_time} %>
|
||||
|
||||
<%= content_tag('div', render(partial: 'table_fields/index', locals: {tab: tab, f: f})) %>
|
||||
|
||||
<%= javascript_tag do %>
|
||||
$(function() { $("table.custom_fields tbody").positionedItems(); });
|
||||
<% end %>
|
||||
<%= submit_tag l(:button_update) %>
|
||||
<% end %>
|
@ -1,5 +1,5 @@
|
||||
<% if User.current.allowed_to?(:manage_custom_tables, nil, global: true) %>
|
||||
<% issue.project.all_issue_custom_tables.each do |custom_table| %>
|
||||
<% issue.project.all_issue_custom_tables(issue).each do |custom_table| %>
|
||||
<% query = custom_table.query(totalable_all: true) %>
|
||||
<% query.add_short_filter('issue_id', "=#{issue.id}") %>
|
||||
<% back_url = issue_path(issue) %>
|
||||
@ -17,7 +17,7 @@
|
||||
back_url: back_url,
|
||||
entities: query.results_scope} %>
|
||||
<% end %>
|
||||
<% elsif issue.project.all_issue_custom_tables.any? %>
|
||||
<% elsif issue.project.all_issue_custom_tables(issue).any? %>
|
||||
<div class="warning">
|
||||
<p>
|
||||
<strong><%= l(:text_missing_permission_manage_custom_tables) %></strong>
|
||||
|
@ -82,9 +82,7 @@ when "IssueCustomField" %>
|
||||
<% else %>
|
||||
<p><%= f.check_box :is_required %></p>
|
||||
<p><%= f.check_box :is_filter, { checked: true } %></p>
|
||||
<% if User.current.admin? %>
|
||||
<p><%= f.text_field :external_name %></p>
|
||||
<% end %>
|
||||
<p><%= f.text_field :external_name %></p>
|
||||
<% end %>
|
||||
<%= call_hook(:"view_custom_fields_form_#{@custom_field.type.to_s.underscore}", :custom_field => @custom_field, :form => f) %>
|
||||
</div>
|
||||
|
@ -1,3 +1,8 @@
|
||||
<% back_url = edit_custom_table_path(@custom_table, tab: 'custom_fields')%>
|
||||
<div class="contextual">
|
||||
<%= link_to l(:label_new_column), new_table_field_path(custom_table_id: @custom_table, back_url: back_url), remote: true, class: 'icon icon-custom-fields' %>
|
||||
</div>
|
||||
|
||||
<table class="list custom_fields">
|
||||
<thead><tr>
|
||||
<th><%=l(:field_name)%></th>
|
||||
@ -9,14 +14,14 @@
|
||||
<tbody>
|
||||
<% (@custom_fields_by_type[tab[:name]] || []).sort.each do |custom_field| -%>
|
||||
<tr class="<%= cycle("odd", "even") %>">
|
||||
<td class="name"><%= link_to custom_field.name, edit_table_field_path(custom_field, custom_table_id: @custom_table.id), remote: true %></td>
|
||||
<td class="name"><%= link_to custom_field.name, edit_table_field_path(custom_field, custom_table_id: @custom_table.id, back_url: back_url), remote: true %></td>
|
||||
<td><%= l(custom_field.format.label) %></td>
|
||||
<td><%= checked_image custom_field.is_required? %></td>
|
||||
<td><%= f.radio_button :main_custom_field_id, custom_field.id %></td>
|
||||
<td class="buttons">
|
||||
<%= reorder_handle(custom_field, url: custom_field_path(custom_field), param: 'custom_field') %>
|
||||
<%= link_to l(:button_edit), edit_table_field_path(id: custom_field), remote: true, title: l(:button_edit), class: 'icon-only icon-edit' %>
|
||||
<%= delete_link table_field_path(custom_field, custom_table_id: @custom_table.id), class: 'icon-only icon-del' %>
|
||||
<%= link_to l(:button_edit), edit_table_field_path(id: custom_field, back_url: back_url), remote: true, title: l(:button_edit), class: 'icon-only icon-edit' %>
|
||||
<%= delete_link table_field_path(custom_field, custom_table_id: @custom_table.id, back_url: back_url), class: 'icon-only icon-del' %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end; reset_cycle %>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<%= labelled_form_for :custom_field, @custom_field, url: table_field_path(@custom_field), html: {method: :put, id: 'custom_field_form'} do |f| %>
|
||||
<%= hidden_field_tag :back_url, edit_custom_table_path(@custom_field.custom_table) %>
|
||||
<%= hidden_field_tag :back_url, params[:back_url] %>
|
||||
<%= hidden_field_tag :tab, @tab || params[:tab] %>
|
||||
<%= render partial: 'form', locals: {f: f} %>
|
||||
<% end %>
|
@ -1,4 +1,3 @@
|
||||
|
||||
<%= labelled_form_for :custom_field, @custom_field, url: table_fields_path, html: {id: 'custom_field_form'} do |f| %>
|
||||
<%= render partial: 'form', locals: {f: f} %>
|
||||
<%= hidden_field_tag :type, @custom_field.type %>
|
||||
|
16
db/migrate/20190820221144_add_tracker_ids_to_custom_table.rb
Normal file
16
db/migrate/20190820221144_add_tracker_ids_to_custom_table.rb
Normal file
@ -0,0 +1,16 @@
|
||||
class AddTrackerIdsToCustomTable < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :custom_tables_trackers, id: false do |t|
|
||||
t.belongs_to :custom_table
|
||||
t.belongs_to :tracker
|
||||
end
|
||||
|
||||
create_table :custom_tables_roles, id: false do |t|
|
||||
t.belongs_to :custom_table
|
||||
t.belongs_to :role
|
||||
end
|
||||
|
||||
add_column :custom_tables, :description, :text
|
||||
add_column :custom_tables, :visible, :boolean, null: false, default: true
|
||||
end
|
||||
end
|
@ -8,10 +8,13 @@ module CustomTables
|
||||
|
||||
# Returns a scope of all custom tables enabled for project issues
|
||||
# (explicitly associated custom tables and custom tables enabled for all projects)
|
||||
def all_issue_custom_tables
|
||||
CustomTable.
|
||||
def all_issue_custom_tables(issue)
|
||||
@custom_tables ||= CustomTable.
|
||||
joins(:trackers).
|
||||
visible.
|
||||
sorted.
|
||||
where("is_for_all = ? OR id IN (?)", true, custom_table_ids)
|
||||
where("custom_tables.is_for_all = ? OR custom_tables.id IN (?)", true, custom_table_ids).
|
||||
where(trackers: {id: issue.tracker})
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -98,7 +98,53 @@ FactoryBot.define do
|
||||
tracker { project.trackers.first }
|
||||
start_date { Date.today }
|
||||
due_date { Date.today + 7.days }
|
||||
priority { IssuePriority.default || FactoryBot.create(:issue_priority, :default) }
|
||||
association :status, factory: :issue_status
|
||||
association :author, :factory => :user, :firstname => "Author"
|
||||
end
|
||||
|
||||
factory :enumeration do
|
||||
name { 'Test' }
|
||||
|
||||
trait :default do
|
||||
name { 'Default' }
|
||||
is_default { true }
|
||||
end
|
||||
end
|
||||
|
||||
factory :role do
|
||||
sequence(:name){ |n| "Role ##{n}" }
|
||||
permissions { Role.new.setable_permissions.collect(&:name).uniq }
|
||||
end
|
||||
|
||||
factory :issue_priority, parent: :enumeration, class: 'IssuePriority' do
|
||||
sequence(:name){ |n| "Priority ##{n}" }
|
||||
end
|
||||
|
||||
factory :member_role do
|
||||
role
|
||||
member
|
||||
end
|
||||
|
||||
factory :member do
|
||||
project
|
||||
user
|
||||
roles { [] }
|
||||
|
||||
after :build do |member, evaluator|
|
||||
if evaluator.roles.empty?
|
||||
member.member_roles << FactoryBot.build(:member_role, member: member)
|
||||
else
|
||||
evaluator.roles.each do |role|
|
||||
member.member_roles << FactoryBot.build(:member_role, member: member, role: role)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
trait :without_roles do
|
||||
after :create do |member, evaluator|
|
||||
member.member_roles.clear
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
24
spec/models/custom_table_spec.rb
Normal file
24
spec/models/custom_table_spec.rb
Normal file
@ -0,0 +1,24 @@
|
||||
require "spec_helper"
|
||||
|
||||
describe CustomTable, type: :model do
|
||||
|
||||
let(:role) { FactoryBot.create(:role) }
|
||||
let(:member) { FactoryBot.create(:member) }
|
||||
let(:user) { FactoryBot.create(:user, memberships: [member]) }
|
||||
let(:custom_table) { FactoryBot.create(:custom_table, visible: false, roles: user.roles) }
|
||||
|
||||
describe 'visible' do
|
||||
|
||||
it 'when table is visible' do
|
||||
expect(CustomTable.visible(user)).to include custom_table
|
||||
end
|
||||
|
||||
context 'should be invisible' do
|
||||
let(:user) { FactoryBot.create(:user) }
|
||||
it 'user is not member' do
|
||||
expect(CustomTable.visible(user)).not_to include custom_table
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
16
spec/models/project_spec.rb
Normal file
16
spec/models/project_spec.rb
Normal file
@ -0,0 +1,16 @@
|
||||
require "spec_helper"
|
||||
|
||||
describe Project, type: :model do
|
||||
|
||||
let(:tracker) { FactoryBot.create(:tracker) }
|
||||
let(:project) { FactoryBot.create(:project, trackers: [tracker]) }
|
||||
let(:issue) { FactoryBot.create(:issue, project: project, tracker: tracker) }
|
||||
let(:custom_table) { FactoryBot.create(:custom_table, projects: [project], trackers: [tracker]) }
|
||||
|
||||
|
||||
it '#all_issue_custom_tables' do
|
||||
custom_table
|
||||
expect(project.all_issue_custom_tables(issue)).
|
||||
to include custom_table
|
||||
end
|
||||
end
|
33
spec/views/custom_tables/new.html.erb_spec.rb
Normal file
33
spec/views/custom_tables/new.html.erb_spec.rb
Normal file
@ -0,0 +1,33 @@
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe "custom_tables/new" do
|
||||
include_context 'logged as admin'
|
||||
|
||||
let(:tracker) { FactoryBot.create(:tracker) }
|
||||
let(:role) { FactoryBot.create(:role) }
|
||||
let(:custom_table) { FactoryBot.create(:custom_table, description: 'Table desc', trackers: [tracker], roles: [role]) }
|
||||
|
||||
before(:each) do
|
||||
@custom_table = assign(:custom_table, custom_table)
|
||||
end
|
||||
|
||||
it "It displays description" do
|
||||
assign(:custom_table, custom_table)
|
||||
render
|
||||
expect(rendered).to match /Table desc/
|
||||
end
|
||||
|
||||
it "It displays trackers" do
|
||||
assign(:custom_table, custom_table)
|
||||
render
|
||||
expect(rendered).to match /#{custom_table.trackers.first.name}/
|
||||
end
|
||||
|
||||
it "It displays roles" do
|
||||
assign(:custom_table, custom_table)
|
||||
render
|
||||
expect(rendered).to match /#{custom_table.roles.first.name}/
|
||||
end
|
||||
|
||||
|
||||
end
|
@ -3,7 +3,8 @@ require "spec_helper"
|
||||
RSpec.describe "issues/_custom_tables" do
|
||||
include_context 'logged as'
|
||||
|
||||
let(:issue) { FactoryBot.create(:issue) }
|
||||
let(:tracker) { FactoryBot.create(:tracker) }
|
||||
let(:issue) { FactoryBot.create(:issue, tracker: tracker) }
|
||||
let(:custom_table) { FactoryBot.create(:custom_table) }
|
||||
|
||||
before(:each) do
|
||||
@ -19,7 +20,6 @@ RSpec.describe "issues/_custom_tables" do
|
||||
end
|
||||
|
||||
context 'with permission' do
|
||||
let(:issue) { FactoryBot.create(:issue) }
|
||||
|
||||
before(:each) do
|
||||
allow_any_instance_of(User).
|
||||
|
@ -1,21 +0,0 @@
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe "issues/_query_custom_table" do
|
||||
include_context 'logged as admin'
|
||||
helper(QueriesHelper)
|
||||
|
||||
let(:issue) { FactoryBot.create(:issue) }
|
||||
let(:custom_table) { FactoryBot.create(:custom_table) }
|
||||
|
||||
|
||||
it "Displays no data" do
|
||||
render partial: "issues/query_custom_table", locals: {
|
||||
query: custom_table.query,
|
||||
custom_table: custom_table,
|
||||
back_url: issue_path(issue),
|
||||
entities: custom_table.query.results_scope }
|
||||
|
||||
expect(rendered).to match /No data to display/
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue
Block a user