diff --git a/app/controllers/custom_tables_controller.rb b/app/controllers/custom_tables_controller.rb
index 3f59565..02d1cf6 100644
--- a/app/controllers/custom_tables_controller.rb
+++ b/app/controllers/custom_tables_controller.rb
@@ -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
diff --git a/app/models/custom_table.rb b/app/models/custom_table.rb
index 515fa79..2759ec0 100644
--- a/app/models/custom_table.rb
+++ b/app/models/custom_table.rb
@@ -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
diff --git a/app/views/custom_tables/_edit.html.erb b/app/views/custom_tables/_edit.html.erb
index 2e77296..3ffae54 100644
--- a/app/views/custom_tables/_edit.html.erb
+++ b/app/views/custom_tables/_edit.html.erb
@@ -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 %>
\ No newline at end of file
diff --git a/app/views/custom_tables/_form.html.erb b/app/views/custom_tables/_form.html.erb
index 2a40509..c92ae51 100644
--- a/app/views/custom_tables/_form.html.erb
+++ b/app/views/custom_tables/_form.html.erb
@@ -1,15 +1,49 @@
<%= error_messages_for @custom_table %>
+
-
+
+
+
+ <% role_ids = @custom_table.role_ids %>
+ <% Role.givable.sorted.each do |role| %>
+
+ <% end %>
+ <%= hidden_field_tag 'custom_table[role_ids][]', '' %>
+
+
- <%= f.check_box :is_for_all, onclick: "window.AllProjects.toggle($(this).is(':checked'))" %>
+ <%= f.check_box :is_for_all, onclick: "window.ToggleCheckboxes.projects($(this).is(':checked'))" %>
<% project_ids = @custom_table.project_ids.to_a %>
@@ -22,9 +56,12 @@
\ No newline at end of file
diff --git a/app/views/custom_tables/edit.html.erb b/app/views/custom_tables/edit.html.erb
index ca18a52..7044199 100644
--- a/app/views/custom_tables/edit.html.erb
+++ b/app/views/custom_tables/edit.html.erb
@@ -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)) -%>
\ No newline at end of file
diff --git a/app/views/custom_tables/settings/_custom_fields.html.erb b/app/views/custom_tables/settings/_custom_fields.html.erb
new file mode 100644
index 0000000..d095aa0
--- /dev/null
+++ b/app/views/custom_tables/settings/_custom_fields.html.erb
@@ -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 %>
\ No newline at end of file
diff --git a/app/views/issues/_custom_tables.html.erb b/app/views/issues/_custom_tables.html.erb
index 1a3199f..641828b 100644
--- a/app/views/issues/_custom_tables.html.erb
+++ b/app/views/issues/_custom_tables.html.erb
@@ -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? %>
<%= l(:text_missing_permission_manage_custom_tables) %>
diff --git a/app/views/table_fields/_form.html.erb b/app/views/table_fields/_form.html.erb
index ffa47f8..ef9b763 100644
--- a/app/views/table_fields/_form.html.erb
+++ b/app/views/table_fields/_form.html.erb
@@ -82,9 +82,7 @@ when "IssueCustomField" %>
<% else %>
<%= f.check_box :is_required %>
<%= f.check_box :is_filter, { checked: true } %>
- <% if User.current.admin? %>
-
<%= f.text_field :external_name %>
- <% end %>
+
<%= f.text_field :external_name %>
<% end %>
<%= call_hook(:"view_custom_fields_form_#{@custom_field.type.to_s.underscore}", :custom_field => @custom_field, :form => f) %>
diff --git a/app/views/table_fields/_index.html.erb b/app/views/table_fields/_index.html.erb
index 3573dfa..9164bf5 100644
--- a/app/views/table_fields/_index.html.erb
+++ b/app/views/table_fields/_index.html.erb
@@ -1,3 +1,8 @@
+<% back_url = edit_custom_table_path(@custom_table, tab: 'custom_fields')%>
+
+ <%= 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' %>
+
+
<%=l(:field_name)%> |
@@ -9,14 +14,14 @@
<% (@custom_fields_by_type[tab[:name]] || []).sort.each do |custom_field| -%>
">
- <%= link_to custom_field.name, edit_table_field_path(custom_field, custom_table_id: @custom_table.id), remote: true %> |
+ <%= link_to custom_field.name, edit_table_field_path(custom_field, custom_table_id: @custom_table.id, back_url: back_url), remote: true %> |
<%= l(custom_field.format.label) %> |
<%= checked_image custom_field.is_required? %> |
<%= f.radio_button :main_custom_field_id, custom_field.id %> |
<%= 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' %>
|
<% end; reset_cycle %>
diff --git a/app/views/table_fields/edit.html.erb b/app/views/table_fields/edit.html.erb
index bb2044f..fc19f9b 100644
--- a/app/views/table_fields/edit.html.erb
+++ b/app/views/table_fields/edit.html.erb
@@ -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 %>
\ No newline at end of file
diff --git a/app/views/table_fields/new.html.erb b/app/views/table_fields/new.html.erb
index b7199cc..d08d20d 100644
--- a/app/views/table_fields/new.html.erb
+++ b/app/views/table_fields/new.html.erb
@@ -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 %>
diff --git a/db/migrate/20190820221144_add_tracker_ids_to_custom_table.rb b/db/migrate/20190820221144_add_tracker_ids_to_custom_table.rb
new file mode 100644
index 0000000..d743ca0
--- /dev/null
+++ b/db/migrate/20190820221144_add_tracker_ids_to_custom_table.rb
@@ -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
diff --git a/lib/custom_tables/patches/project_patch.rb b/lib/custom_tables/patches/project_patch.rb
index 9cc85ca..204f0d7 100644
--- a/lib/custom_tables/patches/project_patch.rb
+++ b/lib/custom_tables/patches/project_patch.rb
@@ -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
diff --git a/spec/factories/factories.rb b/spec/factories/factories.rb
index 7ede074..6955749 100644
--- a/spec/factories/factories.rb
+++ b/spec/factories/factories.rb
@@ -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
diff --git a/spec/models/custom_table_spec.rb b/spec/models/custom_table_spec.rb
new file mode 100644
index 0000000..07cc41f
--- /dev/null
+++ b/spec/models/custom_table_spec.rb
@@ -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
\ No newline at end of file
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
new file mode 100644
index 0000000..cb33e01
--- /dev/null
+++ b/spec/models/project_spec.rb
@@ -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
\ No newline at end of file
diff --git a/spec/views/custom_tables/new.html.erb_spec.rb b/spec/views/custom_tables/new.html.erb_spec.rb
new file mode 100644
index 0000000..ee3d34c
--- /dev/null
+++ b/spec/views/custom_tables/new.html.erb_spec.rb
@@ -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
\ No newline at end of file
diff --git a/spec/views/issues/_custom_tables.html.erb_spec.rb b/spec/views/issues/_custom_tables.html.erb_spec.rb
index 9e10104..1d18455 100644
--- a/spec/views/issues/_custom_tables.html.erb_spec.rb
+++ b/spec/views/issues/_custom_tables.html.erb_spec.rb
@@ -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).
diff --git a/spec/views/issues/_query_custom_table.html.erb_spec.rb b/spec/views/issues/_query_custom_table.html.erb_spec.rb
deleted file mode 100644
index 79a3d5a..0000000
--- a/spec/views/issues/_query_custom_table.html.erb_spec.rb
+++ /dev/null
@@ -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
\ No newline at end of file