Working on ruby 2.7 updates and warning fixes
This commit is contained in:
parent
a48ee5b4a7
commit
07c306fa66
3
.github/workflows/linters.yml
vendored
3
.github/workflows/linters.yml
vendored
@ -14,7 +14,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Setup Gemfile
|
- name: Setup Gemfile
|
||||||
run: |
|
run: |
|
||||||
cp test/support/gemfile.rb Gemfile
|
touch .enable_dev
|
||||||
|
sed -i "3isource 'https://rubygems.org'" Gemfile
|
||||||
|
|
||||||
- name: Setup Ruby
|
- name: Setup Ruby
|
||||||
uses: ruby/setup-ruby@v1
|
uses: ruby/setup-ruby@v1
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -6,7 +6,9 @@ tmp/
|
|||||||
Gemfile.lock
|
Gemfile.lock
|
||||||
.project
|
.project
|
||||||
.vscode
|
.vscode
|
||||||
|
.bundle
|
||||||
.settings/
|
.settings/
|
||||||
docs/_build
|
docs/_build
|
||||||
docs/_static
|
docs/_static
|
||||||
docs/_templates
|
docs/_templates
|
||||||
|
.enable_dev
|
||||||
|
43
.rubocop.yml
43
.rubocop.yml
@ -16,6 +16,10 @@ Metrics/AbcSize:
|
|||||||
Metrics/BlockLength:
|
Metrics/BlockLength:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
Metrics/ParameterLists:
|
||||||
|
Enabled: true
|
||||||
|
CountKeywordArgs: false
|
||||||
|
|
||||||
Metrics/ClassLength:
|
Metrics/ClassLength:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
@ -58,16 +62,45 @@ Performance/ChainArrayAllocation:
|
|||||||
Style/AutoResourceCleanup:
|
Style/AutoResourceCleanup:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
Style/ExpandPathArguments:
|
||||||
|
Enabled: true
|
||||||
|
Exclude:
|
||||||
|
- additionals.gemspec
|
||||||
|
- test/**/*
|
||||||
|
|
||||||
Style/FrozenStringLiteralComment:
|
Style/FrozenStringLiteralComment:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
Exclude:
|
||||||
|
- '/**/*.rsb'
|
||||||
|
|
||||||
|
Style/OptionHash:
|
||||||
|
Enabled: true
|
||||||
|
SuspiciousParamNames:
|
||||||
|
- options
|
||||||
|
- api_options
|
||||||
|
- opts
|
||||||
|
- args
|
||||||
|
- params
|
||||||
|
- parameters
|
||||||
|
- settings
|
||||||
|
Exclude:
|
||||||
|
- lib/additionals/patches/*.rb
|
||||||
|
|
||||||
|
Style/ReturnNil:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
Style/UnlessLogicalOperators:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
Style/MethodCallWithArgsParentheses:
|
||||||
|
Enabled: true
|
||||||
|
AllowParenthesesInMultilineCall: true
|
||||||
|
AllowParenthesesInChaining: true
|
||||||
|
EnforcedStyle: omit_parentheses
|
||||||
|
|
||||||
Style/Documentation:
|
Style/Documentation:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# required for travis/ci (symbolic links problem)
|
|
||||||
Style/ExpandPathArguments:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
Style/HashTransformValues:
|
Style/HashTransformValues:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ linters:
|
|||||||
RuboCop:
|
RuboCop:
|
||||||
ignored_cops:
|
ignored_cops:
|
||||||
- Layout/ArgumentAlignment
|
- Layout/ArgumentAlignment
|
||||||
|
- Layout/ArrayAlignment
|
||||||
- Layout/BlockEndNewline
|
- Layout/BlockEndNewline
|
||||||
- Layout/EmptyLineAfterGuardClause
|
- Layout/EmptyLineAfterGuardClause
|
||||||
- Layout/HashAlignment
|
- Layout/HashAlignment
|
||||||
@ -21,6 +22,7 @@ linters:
|
|||||||
- Lint/Void
|
- Lint/Void
|
||||||
- Metrics/BlockNesting
|
- Metrics/BlockNesting
|
||||||
- Rails/OutputSafety
|
- Rails/OutputSafety
|
||||||
|
- Style/FrozenStringLiteralComment
|
||||||
- Style/IdenticalConditionalBranches
|
- Style/IdenticalConditionalBranches
|
||||||
- Style/IfUnlessModifier
|
- Style/IfUnlessModifier
|
||||||
- Style/Next
|
- Style/Next
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
3.0.3
|
||||||
|
+++++
|
||||||
|
|
||||||
|
- Ruby 2.7 warnings fixed
|
||||||
|
|
||||||
3.0.2
|
3.0.2
|
||||||
+++++
|
+++++
|
||||||
|
|
||||||
|
18
Gemfile
18
Gemfile
@ -1,2 +1,20 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# Specify your gem's dependencies in additionals.gemspec
|
# Specify your gem's dependencies in additionals.gemspec
|
||||||
gemspec
|
gemspec
|
||||||
|
|
||||||
|
group :development do
|
||||||
|
# this is only used for development.
|
||||||
|
# if you want to use it, do:
|
||||||
|
# - create .enable_dev file in additionals directory
|
||||||
|
# - remove rubocop entries from REDMINE/Gemfile
|
||||||
|
# - remove REDMINE/.rubocop* files
|
||||||
|
if File.file? File.expand_path './.enable_dev', __dir__
|
||||||
|
gem 'brakeman', require: false
|
||||||
|
gem 'pandoc-ruby', require: false
|
||||||
|
gem 'rubocop', require: false
|
||||||
|
gem 'rubocop-performance', require: false
|
||||||
|
gem 'rubocop-rails', require: false
|
||||||
|
gem 'slim_lint', require: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
2
Rakefile
2
Rakefile
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'bundler/gem_tasks'
|
require 'bundler/gem_tasks'
|
||||||
require 'rake/testtask'
|
require 'rake/testtask'
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
lib = File.expand_path '../lib', __FILE__
|
lib = File.expand_path '../lib', __FILE__
|
||||||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
$LOAD_PATH.unshift lib unless $LOAD_PATH.include? lib
|
||||||
require 'additionals/version'
|
require 'additionals/version'
|
||||||
|
|
||||||
Gem::Specification.new do |spec|
|
Gem::Specification.new do |spec|
|
||||||
@ -22,9 +24,4 @@ Gem::Specification.new do |spec|
|
|||||||
spec.add_runtime_dependency 'render_async'
|
spec.add_runtime_dependency 'render_async'
|
||||||
spec.add_runtime_dependency 'rss'
|
spec.add_runtime_dependency 'rss'
|
||||||
spec.add_runtime_dependency 'slim-rails'
|
spec.add_runtime_dependency 'slim-rails'
|
||||||
|
|
||||||
spec.add_development_dependency 'brakeman'
|
|
||||||
spec.add_development_dependency 'bundler'
|
|
||||||
spec.add_development_dependency 'rake'
|
|
||||||
spec.add_development_dependency 'slim_lint'
|
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AdditionalsAssignToMeController < ApplicationController
|
class AdditionalsAssignToMeController < ApplicationController
|
||||||
before_action :find_issue
|
before_action :find_issue
|
||||||
helper :additionals_issues
|
helper :additionals_issues
|
||||||
@ -11,11 +13,11 @@ class AdditionalsAssignToMeController < ApplicationController
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@issue.init_journal(User.current)
|
@issue.init_journal User.current
|
||||||
@issue.assigned_to = User.current
|
@issue.assigned_to = User.current
|
||||||
|
|
||||||
if !@issue.save || old_user == @issue.assigned_to
|
if !@issue.save || old_user == @issue.assigned_to
|
||||||
flash[:error] = l(:error_issues_could_not_be_assigned_to_me)
|
flash[:error] = l :error_issues_could_not_be_assigned_to_me
|
||||||
return redirect_to(issue_path(@issue))
|
return redirect_to(issue_path(@issue))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -29,7 +31,7 @@ class AdditionalsAssignToMeController < ApplicationController
|
|||||||
private
|
private
|
||||||
|
|
||||||
def find_issue
|
def find_issue
|
||||||
@issue = Issue.find(params[:issue_id])
|
@issue = Issue.find params[:issue_id]
|
||||||
raise Unauthorized unless @issue.visible? && @issue.editable?
|
raise Unauthorized unless @issue.visible? && @issue.editable?
|
||||||
|
|
||||||
@project = @issue.project
|
@project = @issue.project
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AdditionalsChangeStatusController < ApplicationController
|
class AdditionalsChangeStatusController < ApplicationController
|
||||||
before_action :find_issue
|
before_action :find_issue
|
||||||
helper :additionals_issues
|
helper :additionals_issues
|
||||||
@ -6,7 +8,7 @@ class AdditionalsChangeStatusController < ApplicationController
|
|||||||
issue_old_status_id = @issue.status.id
|
issue_old_status_id = @issue.status.id
|
||||||
issue_old_user = @issue.assigned_to
|
issue_old_user = @issue.assigned_to
|
||||||
new_status_id = params[:new_status_id].to_i
|
new_status_id = params[:new_status_id].to_i
|
||||||
allowed_status = @issue.sidbar_change_status_allowed_to(User.current, new_status_id)
|
allowed_status = @issue.sidbar_change_status_allowed_to User.current, new_status_id
|
||||||
|
|
||||||
if new_status_id < 1 || @issue.status_id == new_status_id || allowed_status.nil?
|
if new_status_id < 1 || @issue.status_id == new_status_id || allowed_status.nil?
|
||||||
redirect_to(issue_path(@issue))
|
redirect_to(issue_path(@issue))
|
||||||
@ -18,7 +20,7 @@ class AdditionalsChangeStatusController < ApplicationController
|
|||||||
@issue.assigned_to = User.current if @issue.status_x_affected?(new_status_id) && issue_old_user != User.current
|
@issue.assigned_to = User.current if @issue.status_x_affected?(new_status_id) && issue_old_user != User.current
|
||||||
|
|
||||||
if !@issue.save || issue_old_status_id == @issue.status_id
|
if !@issue.save || issue_old_status_id == @issue.status_id
|
||||||
flash[:error] = l(:error_issue_status_could_not_changed)
|
flash[:error] = l :error_issue_status_could_not_changed
|
||||||
return redirect_to(issue_path(@issue))
|
return redirect_to(issue_path(@issue))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -33,7 +35,7 @@ class AdditionalsChangeStatusController < ApplicationController
|
|||||||
private
|
private
|
||||||
|
|
||||||
def find_issue
|
def find_issue
|
||||||
@issue = Issue.find(params[:issue_id])
|
@issue = Issue.find params[:issue_id]
|
||||||
raise Unauthorized unless @issue.visible? && @issue.editable?
|
raise Unauthorized unless @issue.visible? && @issue.editable?
|
||||||
|
|
||||||
@project = @issue.project
|
@project = @issue.project
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AdditionalsMacrosController < ApplicationController
|
class AdditionalsMacrosController < ApplicationController
|
||||||
before_action :require_login
|
before_action :require_login
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'open-uri'
|
require 'open-uri'
|
||||||
|
|
||||||
class DashboardAsyncBlocksController < ApplicationController
|
class DashboardAsyncBlocksController < ApplicationController
|
||||||
@ -84,7 +86,7 @@ class DashboardAsyncBlocksController < ApplicationController
|
|||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
deny_access unless User.current.allowed_to?(:view_project, @project)
|
deny_access unless User.current.allowed_to? :view_project, @project
|
||||||
|
|
||||||
@project
|
@project
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class DashboardsController < ApplicationController
|
class DashboardsController < ApplicationController
|
||||||
menu_item :dashboards
|
menu_item :dashboards
|
||||||
|
|
||||||
@ -63,7 +65,7 @@ class DashboardsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@dashboard = Dashboard.new(author: User.current)
|
@dashboard = Dashboard.new author: User.current
|
||||||
@dashboard.safe_attributes = params[:dashboard]
|
@dashboard.safe_attributes = params[:dashboard]
|
||||||
@dashboard.dashboard_type = assign_dashboard_type
|
@dashboard.dashboard_type = assign_dashboard_type
|
||||||
@dashboard.role_ids = params[:dashboard][:role_ids] if params[:dashboard].present?
|
@dashboard.role_ids = params[:dashboard][:role_ids] if params[:dashboard].present?
|
||||||
@ -71,7 +73,7 @@ class DashboardsController < ApplicationController
|
|||||||
@allowed_projects = @dashboard.allowed_target_projects
|
@allowed_projects = @dashboard.allowed_target_projects
|
||||||
|
|
||||||
if @dashboard.save
|
if @dashboard.save
|
||||||
flash[:notice] = l(:notice_successful_create)
|
flash[:notice] = l :notice_successful_create
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to dashboard_link_path(@project, @dashboard) }
|
format.html { redirect_to dashboard_link_path(@project, @dashboard) }
|
||||||
@ -80,13 +82,13 @@ class DashboardsController < ApplicationController
|
|||||||
else
|
else
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { render action: 'new' }
|
format.html { render action: 'new' }
|
||||||
format.api { render_validation_errors(@dashboard) }
|
format.api { render_validation_errors @dashboard }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
return render_403 unless @dashboard.editable_by?(User.current)
|
return render_403 unless @dashboard.editable_by? User.current
|
||||||
|
|
||||||
@allowed_projects = @dashboard.allowed_target_projects
|
@allowed_projects = @dashboard.allowed_target_projects
|
||||||
|
|
||||||
@ -97,7 +99,7 @@ class DashboardsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
return render_403 unless @dashboard.editable_by?(User.current)
|
return render_403 unless @dashboard.editable_by? User.current
|
||||||
|
|
||||||
@dashboard.safe_attributes = params[:dashboard]
|
@dashboard.safe_attributes = params[:dashboard]
|
||||||
@dashboard.role_ids = params[:dashboard][:role_ids] if params[:dashboard].present?
|
@dashboard.role_ids = params[:dashboard][:role_ids] if params[:dashboard].present?
|
||||||
@ -106,9 +108,9 @@ class DashboardsController < ApplicationController
|
|||||||
@allowed_projects = @dashboard.allowed_target_projects
|
@allowed_projects = @dashboard.allowed_target_projects
|
||||||
|
|
||||||
if @dashboard.save
|
if @dashboard.save
|
||||||
flash[:notice] = l(:notice_successful_update)
|
flash[:notice] = l :notice_successful_update
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to dashboard_link_path @project, @dashboard }
|
format.html { redirect_to dashboard_link_path(@project, @dashboard) }
|
||||||
format.api { head :ok }
|
format.api { head :ok }
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -124,20 +126,20 @@ class DashboardsController < ApplicationController
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
@dashboard.destroy
|
@dashboard.destroy
|
||||||
flash[:notice] = l(:notice_successful_delete)
|
flash[:notice] = l :notice_successful_delete
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to @project.nil? ? home_path : project_path(@project) }
|
format.html { redirect_to @project.nil? ? home_path : project_path(@project) }
|
||||||
format.api { head :ok }
|
format.api { head :ok }
|
||||||
end
|
end
|
||||||
rescue ActiveRecord::RecordNotDestroyed
|
rescue ActiveRecord::RecordNotDestroyed
|
||||||
flash[:error] = l(:error_remove_db_entry)
|
flash[:error] = l :error_remove_db_entry
|
||||||
redirect_to dashboard_path(@dashboard)
|
redirect_to dashboard_path(@dashboard)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def query_statement_invalid(exception)
|
def query_statement_invalid(exception)
|
||||||
logger&.error "Query::StatementInvalid: #{exception.message}"
|
logger&.error "Query::StatementInvalid: #{exception.message}"
|
||||||
session.delete(additionals_query_session_key('dashboard'))
|
session.delete additionals_query_session_key('dashboard')
|
||||||
render_error l(:error_query_statement_invalid)
|
render_error l(:error_query_statement_invalid)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -145,7 +147,7 @@ class DashboardsController < ApplicationController
|
|||||||
block_settings = params[:settings] || {}
|
block_settings = params[:settings] || {}
|
||||||
|
|
||||||
block_settings.each do |block, settings|
|
block_settings.each do |block, settings|
|
||||||
@dashboard.update_block_settings(block, settings.to_unsafe_hash)
|
@dashboard.update_block_settings block, settings.to_unsafe_hash
|
||||||
end
|
end
|
||||||
@dashboard.save
|
@dashboard.save
|
||||||
@updated_blocks = block_settings.keys
|
@updated_blocks = block_settings.keys
|
||||||
@ -201,7 +203,7 @@ class DashboardsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def find_dashboard
|
def find_dashboard
|
||||||
@dashboard = Dashboard.find(params[:id])
|
@dashboard = Dashboard.find params[:id]
|
||||||
raise ::Unauthorized unless @dashboard.visible?
|
raise ::Unauthorized unless @dashboard.visible?
|
||||||
|
|
||||||
if @dashboard.dashboard_type == DashboardContentProject::TYPE_NAME && @dashboard.project.nil?
|
if @dashboard.dashboard_type == DashboardContentProject::TYPE_NAME && @dashboard.project.nil?
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AdditionalsChartjsHelper
|
module AdditionalsChartjsHelper
|
||||||
def chartjs_colorschemes_info_url
|
def chartjs_colorschemes_info_url
|
||||||
link_to(l(:label_chartjs_colorscheme_info),
|
link_to(l(:label_chartjs_colorscheme_info),
|
||||||
@ -7,6 +9,6 @@ module AdditionalsChartjsHelper
|
|||||||
|
|
||||||
def select_options_for_chartjs_colorscheme(selected)
|
def select_options_for_chartjs_colorscheme(selected)
|
||||||
data = YAML.safe_load(ERB.new(IO.read(File.join(Additionals.plugin_dir, 'config', 'colorschemes.yml'))).result) || {}
|
data = YAML.safe_load(ERB.new(IO.read(File.join(Additionals.plugin_dir, 'config', 'colorschemes.yml'))).result) || {}
|
||||||
grouped_options_for_select(data, selected)
|
grouped_options_for_select data, selected
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AdditionalsClipboardjsHelper
|
module AdditionalsClipboardjsHelper
|
||||||
def clipboardjs_button_for(target, clipboard_text_from_button = nil)
|
def clipboardjs_button_for(target, clipboard_text_from_button = nil)
|
||||||
render_clipboardjs_button(target, clipboard_text_from_button) + render_clipboardjs_javascript(target)
|
render_clipboardjs_button(target, clipboard_text_from_button) + render_clipboardjs_javascript(target)
|
||||||
@ -34,6 +36,6 @@ module AdditionalsClipboardjsHelper
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render_clipboardjs_javascript(target)
|
def render_clipboardjs_javascript(target)
|
||||||
javascript_tag("setClipboardJS('#zc_#{target}');")
|
javascript_tag "setClipboardJS('#zc_#{target}');"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AdditionalsCustomFieldsHelper
|
module AdditionalsCustomFieldsHelper
|
||||||
def custom_fields_with_full_with_layout
|
def custom_fields_with_full_with_layout
|
||||||
['IssueCustomField']
|
['IssueCustomField']
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AdditionalsFontawesomeHelper
|
module AdditionalsFontawesomeHelper
|
||||||
# name = TYPE-FA_NAME, eg. fas_car
|
# name = TYPE-FA_NAME, eg. fas_car
|
||||||
# fas_cloud-upload-alt
|
# fas_cloud-upload-alt
|
||||||
@ -7,7 +9,7 @@ module AdditionalsFontawesomeHelper
|
|||||||
# pre_text
|
# pre_text
|
||||||
# post_text
|
# post_text
|
||||||
# title
|
# title
|
||||||
def font_awesome_icon(name, options = {})
|
def font_awesome_icon(name, **options)
|
||||||
info = AdditionalsFontAwesome.value_info name
|
info = AdditionalsFontAwesome.value_info name
|
||||||
return '' if info.blank?
|
return '' if info.blank?
|
||||||
|
|
||||||
@ -29,7 +31,7 @@ module AdditionalsFontawesomeHelper
|
|||||||
post_text = options[:post_text]
|
post_text = options[:post_text]
|
||||||
options.delete :post_text
|
options.delete :post_text
|
||||||
end
|
end
|
||||||
s << tag.span(options)
|
s << tag.span(**options)
|
||||||
if post_text.present?
|
if post_text.present?
|
||||||
s << ' '
|
s << ' '
|
||||||
s << post_text
|
s << post_text
|
||||||
@ -37,16 +39,16 @@ module AdditionalsFontawesomeHelper
|
|||||||
safe_join s
|
safe_join s
|
||||||
end
|
end
|
||||||
|
|
||||||
def additionals_fontawesome_select(form, selected, options = {})
|
def additionals_fontawesome_select(form, selected, **options)
|
||||||
options[:include_blank] ||= true unless options[:required]
|
options[:include_blank] ||= true unless options[:required]
|
||||||
html_options = {}
|
html_options = {}
|
||||||
|
|
||||||
additionals_fontawesome_add_selected selected
|
additionals_fontawesome_add_selected selected
|
||||||
|
|
||||||
name, options = Additionals.hash_remove_with_default(:name, options, :icon)
|
name, options = Additionals.hash_remove_with_default :name, options, :icon
|
||||||
loader, options = Additionals.hash_remove_with_default(:loader, options, true)
|
loader, options = Additionals.hash_remove_with_default :loader, options, true
|
||||||
html_options[:class], options = Additionals.hash_remove_with_default(:class, options, 'select2-fontawesome-field')
|
html_options[:class], options = Additionals.hash_remove_with_default :class, options, 'select2-fontawesome-field'
|
||||||
html_options[:style], options = Additionals.hash_remove_with_default(:style, options)
|
html_options[:style], options = Additionals.hash_remove_with_default :style, options
|
||||||
|
|
||||||
s = []
|
s = []
|
||||||
s << form.select(name,
|
s << form.select(name,
|
||||||
@ -54,7 +56,7 @@ module AdditionalsFontawesomeHelper
|
|||||||
options,
|
options,
|
||||||
html_options)
|
html_options)
|
||||||
|
|
||||||
s << additionals_fontawesome_loader(options, html_options) if loader
|
s << additionals_fontawesome_loader(**options, field_class: html_options[:class]) if loader
|
||||||
|
|
||||||
safe_join s
|
safe_join s
|
||||||
end
|
end
|
||||||
@ -70,21 +72,20 @@ module AdditionalsFontawesomeHelper
|
|||||||
'250px'
|
'250px'
|
||||||
end
|
end
|
||||||
|
|
||||||
def additionals_fontawesome_loader(options, html_options = {})
|
def additionals_fontawesome_loader(field_class: 'select2-fontawesome-field', **options)
|
||||||
html_options[:class] ||= 'select2-fontawesome-field'
|
|
||||||
options[:template_selection] = 'formatFontawesomeText'
|
options[:template_selection] = 'formatFontawesomeText'
|
||||||
options[:template_result] = 'formatFontawesomeText'
|
options[:template_result] = 'formatFontawesomeText'
|
||||||
if options[:include_blank]
|
if options[:include_blank]
|
||||||
options[:placeholder] ||= l(:label_disabled)
|
options[:placeholder] ||= l :label_disabled
|
||||||
options[:allow_clear] ||= true
|
options[:allow_clear] ||= true
|
||||||
end
|
end
|
||||||
options[:width] = additionals_fontawesome_default_select_width
|
options[:width] = additionals_fontawesome_default_select_width
|
||||||
|
|
||||||
render(layout: false,
|
render layout: false,
|
||||||
partial: 'additionals/select2_ajax_call.js',
|
partial: 'additionals/select2_ajax_call',
|
||||||
formats: [:js],
|
formats: [:js],
|
||||||
locals: { field_class: html_options[:class],
|
locals: { field_class: field_class,
|
||||||
ajax_url: fontawesome_auto_completes_path(selected: @selected_store.join(',')),
|
ajax_url: fontawesome_auto_completes_path(selected: @selected_store.join(',')),
|
||||||
options: options })
|
options: options }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AdditionalsIssuesHelper
|
module AdditionalsIssuesHelper
|
||||||
def author_options_for_select(project, entity = nil, permission = nil)
|
def author_options_for_select(project, entity = nil, permission = nil)
|
||||||
scope = project.present? ? project.users.visible : User.active.visible
|
scope = project.present? ? project.users.visible : User.active.visible
|
||||||
scope = scope.with_permission(permission, project) unless permission.nil?
|
scope = scope.with_permission permission, project unless permission.nil?
|
||||||
authors = scope.sorted.to_a
|
authors = scope.sorted.to_a
|
||||||
|
|
||||||
unless entity.nil?
|
unless entity.nil?
|
||||||
@ -15,7 +17,7 @@ module AdditionalsIssuesHelper
|
|||||||
s = []
|
s = []
|
||||||
return s unless authors.any?
|
return s unless authors.any?
|
||||||
|
|
||||||
s << tag.option("<< #{l :label_me} >>", value: User.current.id) if authors.include?(User.current)
|
s << tag.option("<< #{l :label_me} >>", value: User.current.id) if authors.include? User.current
|
||||||
|
|
||||||
if entity.nil?
|
if entity.nil?
|
||||||
s << options_from_collection_for_select(authors, 'id', 'name')
|
s << options_from_collection_for_select(authors, 'id', 'name')
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AdditionalsJournalsHelper
|
module AdditionalsJournalsHelper
|
||||||
MultipleValuesDetail = Struct.new(:property, :prop_key, :custom_field, :old_value, :value)
|
MultipleValuesDetail = Struct.new :property, :prop_key, :custom_field, :old_value, :value
|
||||||
|
|
||||||
# Returns the textual representation of a journal details
|
# Returns the textual representation of a journal details
|
||||||
# as an array of strings
|
# as an array of strings
|
||||||
def entity_details_to_strings(entity, details, options = {})
|
def entity_details_to_strings(entity, details, **options)
|
||||||
entity_type = entity.model_name.param_key
|
entity_type = entity.model_name.param_key
|
||||||
show_detail_method = "#{entity_type}_show_detail"
|
show_detail_method = "#{entity_type}_show_detail"
|
||||||
options[:only_path] = options[:only_path] != false
|
options[:only_path] = options[:only_path] != false
|
||||||
no_html = options.delete(:no_html)
|
no_html = options.delete :no_html
|
||||||
strings = []
|
strings = []
|
||||||
values_by_field = {}
|
values_by_field = {}
|
||||||
|
|
||||||
@ -21,21 +23,21 @@ module AdditionalsJournalsHelper
|
|||||||
next
|
next
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
strings << send(show_detail_method, detail, no_html, options)
|
strings << send(show_detail_method, detail, no_html, **options)
|
||||||
end
|
end
|
||||||
|
|
||||||
if values_by_field.present?
|
if values_by_field.present?
|
||||||
values_by_field.each do |field, changes|
|
values_by_field.each do |field, changes|
|
||||||
if changes[:added].any?
|
if changes[:added].any?
|
||||||
detail = MultipleValuesDetail.new('cf', field.id.to_s, field)
|
detail = MultipleValuesDetail.new 'cf', field.id.to_s, field
|
||||||
detail.value = changes[:added]
|
detail.value = changes[:added]
|
||||||
strings << send(show_detail_method, detail, no_html, options)
|
strings << send(show_detail_method, detail, no_html, **options)
|
||||||
end
|
end
|
||||||
next unless changes[:deleted].any?
|
next unless changes[:deleted].any?
|
||||||
|
|
||||||
detail = MultipleValuesDetail.new('cf', field.id.to_s, field)
|
detail = MultipleValuesDetail.new 'cf', field.id.to_s, field
|
||||||
detail.old_value = changes[:deleted]
|
detail.old_value = changes[:deleted]
|
||||||
strings << send(show_detail_method, detail, no_html, options)
|
strings << send(show_detail_method, detail, no_html, **options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
strings
|
strings
|
||||||
@ -64,7 +66,7 @@ module AdditionalsJournalsHelper
|
|||||||
|
|
||||||
# Returns the textual representation of a single journal detail
|
# Returns the textual representation of a single journal detail
|
||||||
# rubocop: disable Rails/OutputSafety
|
# rubocop: disable Rails/OutputSafety
|
||||||
def entity_show_detail(entity, detail, no_html = false, options = {}) # rubocop:disable Style/OptionalBooleanParameter:
|
def entity_show_detail(entity, detail, no_html = false, **options) # rubocop:disable Style/OptionalBooleanParameter:
|
||||||
multiple = false
|
multiple = false
|
||||||
no_detail = false
|
no_detail = false
|
||||||
show_diff = false
|
show_diff = false
|
||||||
@ -82,17 +84,17 @@ module AdditionalsJournalsHelper
|
|||||||
|
|
||||||
if label || show_diff
|
if label || show_diff
|
||||||
unless no_html
|
unless no_html
|
||||||
label = tag.strong(label)
|
label = tag.strong label
|
||||||
old_value = tag.i(old_value) if detail.old_value
|
old_value = tag.i old_value if detail.old_value
|
||||||
old_value = tag.del(old_value) if detail.old_value && detail.value.blank?
|
old_value = tag.del old_value if detail.old_value && detail.value.blank?
|
||||||
value = tag.i(value) if value
|
value = tag.i value if value
|
||||||
end
|
end
|
||||||
|
|
||||||
html =
|
html =
|
||||||
if no_detail
|
if no_detail
|
||||||
l(:text_journal_changed_no_detail, label: label)
|
l :text_journal_changed_no_detail, label: label
|
||||||
elsif show_diff
|
elsif show_diff
|
||||||
s = l(:text_journal_changed_no_detail, label: label)
|
s = l :text_journal_changed_no_detail, label: label
|
||||||
unless no_html
|
unless no_html
|
||||||
diff_link = link_to l(:label_diff),
|
diff_link = link_to l(:label_diff),
|
||||||
send(diff_url_method,
|
send(diff_url_method,
|
||||||
@ -105,11 +107,11 @@ module AdditionalsJournalsHelper
|
|||||||
s.html_safe
|
s.html_safe
|
||||||
elsif detail.value.present?
|
elsif detail.value.present?
|
||||||
if detail.old_value.present?
|
if detail.old_value.present?
|
||||||
l(:text_journal_changed, label: label, old: old_value, new: value)
|
l :text_journal_changed, label: label, old: old_value, new: value
|
||||||
elsif multiple
|
elsif multiple
|
||||||
l(:text_journal_added, label: label, value: value)
|
l :text_journal_added, label: label, value: value
|
||||||
else
|
else
|
||||||
l(:text_journal_set_to, label: label, value: value)
|
l :text_journal_set_to, label: label, value: value
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
l(:text_journal_deleted, label: label, old: old_value).html_safe
|
l(:text_journal_deleted, label: label, old: old_value).html_safe
|
||||||
@ -138,20 +140,20 @@ module AdditionalsJournalsHelper
|
|||||||
prop = { label: custom_field.name }
|
prop = { label: custom_field.name }
|
||||||
project = Project.visible.where(id: detail.value).first if detail.value.present?
|
project = Project.visible.where(id: detail.value).first if detail.value.present?
|
||||||
old_project = Project.visible.where(id: detail.old_value).first if detail.old_value.present?
|
old_project = Project.visible.where(id: detail.old_value).first if detail.old_value.present?
|
||||||
prop[:value] = link_to_project(project) if project.present?
|
prop[:value] = link_to_project project if project.present?
|
||||||
prop[:old_value] = link_to_project(old_project) if old_project.present?
|
prop[:old_value] = link_to_project old_project if old_project.present?
|
||||||
when 'db_entry'
|
when 'db_entry'
|
||||||
prop = { label: custom_field.name }
|
prop = { label: custom_field.name }
|
||||||
db_entry = DbEntry.visible.where(id: detail.value).first if detail.value.present?
|
db_entry = DbEntry.visible.where(id: detail.value).first if detail.value.present?
|
||||||
old_db_entry = DbEntry.visible.where(id: detail.old_value).first if detail.old_value.present?
|
old_db_entry = DbEntry.visible.where(id: detail.old_value).first if detail.old_value.present?
|
||||||
prop[:value] = link_to(db_entry.name, db_entry_url(db_entry)) if db_entry.present?
|
prop[:value] = link_to db_entry.name, db_entry_url(db_entry) if db_entry.present?
|
||||||
prop[:old_value] = link_to(old_db_entry.name, db_entry_url(old_db_entry)) if old_db_entry.present?
|
prop[:old_value] = link_to old_db_entry.name, db_entry_url(old_db_entry) if old_db_entry.present?
|
||||||
when 'password'
|
when 'password'
|
||||||
prop = { label: custom_field.name }
|
prop = { label: custom_field.name }
|
||||||
password = Password.visible.where(id: detail.value).first if detail.value.present? && defined?(Password)
|
password = Password.visible.where(id: detail.value).first if detail.value.present? && defined?(Password)
|
||||||
old_password = Password.visible.where(id: detail.old_value).first if detail.old_value.present? && defined?(Password)
|
old_password = Password.visible.where(id: detail.old_value).first if detail.old_value.present? && defined?(Password)
|
||||||
prop[:value] = link_to(password.name, password_url(password)) if password.present?
|
prop[:value] = link_to password.name, password_url(password) if password.present?
|
||||||
prop[:old_value] = link_to(old_password.name, password_url(old_password)) if old_password.present?
|
prop[:old_value] = link_to old_password.name, password_url(old_password) if old_password.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
prop
|
prop
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AdditionalsMenuHelper
|
module AdditionalsMenuHelper
|
||||||
def additionals_top_menu_setup
|
def additionals_top_menu_setup
|
||||||
return if Redmine::Plugin.installed? 'redmine_hrm'
|
return if Redmine::Plugin.installed? 'redmine_hrm'
|
||||||
@ -18,11 +20,11 @@ module AdditionalsMenuHelper
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_top_submenu_item(menu_name, item)
|
def handle_top_submenu_item(menu_name, **item)
|
||||||
handle_top_menu_item menu_name, item, with_submenu: true
|
handle_top_menu_item menu_name, with_submenu: true, **item
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_top_menu_item(menu_name, item, with_submenu: false)
|
def handle_top_menu_item(menu_name, with_submenu: false, **item)
|
||||||
Redmine::MenuManager.map(:top_menu).delete(menu_name.to_sym) if Redmine::MenuManager.map(:top_menu).exists?(menu_name.to_sym)
|
Redmine::MenuManager.map(:top_menu).delete(menu_name.to_sym) if Redmine::MenuManager.map(:top_menu).exists?(menu_name.to_sym)
|
||||||
|
|
||||||
html_options = {}
|
html_options = {}
|
||||||
@ -30,7 +32,7 @@ module AdditionalsMenuHelper
|
|||||||
css_classes = []
|
css_classes = []
|
||||||
css_classes << 'top-submenu' if with_submenu
|
css_classes << 'top-submenu' if with_submenu
|
||||||
css_classes << 'external' if item[:url].include? '://'
|
css_classes << 'external' if item[:url].include? '://'
|
||||||
html_options[:class] = css_classes.join(' ') if css_classes.present?
|
html_options[:class] = css_classes.join ' ' if css_classes.present?
|
||||||
|
|
||||||
html_options[:title] = item[:title] if item[:title].present?
|
html_options[:title] = item[:title] if item[:title].present?
|
||||||
|
|
||||||
@ -40,9 +42,9 @@ module AdditionalsMenuHelper
|
|||||||
menu_options[:if] = menu_options[:if] if menu_options[:if].present?
|
menu_options[:if] = menu_options[:if] if menu_options[:if].present?
|
||||||
|
|
||||||
menu_options[:caption] = if item[:symbol].present? && item[:name].present?
|
menu_options[:caption] = if item[:symbol].present? && item[:name].present?
|
||||||
font_awesome_icon(item[:symbol], post_text: item[:name])
|
font_awesome_icon item[:symbol], post_text: item[:name]
|
||||||
elsif item[:symbol].present?
|
elsif item[:symbol].present?
|
||||||
font_awesome_icon(item[:symbol])
|
font_awesome_icon item[:symbol]
|
||||||
elsif item[:name].present?
|
elsif item[:name].present?
|
||||||
item[:name].to_s
|
item[:name].to_s
|
||||||
end
|
end
|
||||||
@ -149,8 +151,8 @@ module AdditionalsMenuHelper
|
|||||||
raise e unless e.class.to_s == 'NameError'
|
raise e unless e.class.to_s == 'NameError'
|
||||||
end
|
end
|
||||||
|
|
||||||
plugin_item = plugin_item_base.try(:additionals_help_items) unless plugin_item_base.nil?
|
plugin_item = plugin_item_base.try :additionals_help_items unless plugin_item_base.nil?
|
||||||
plugin_item = additionals_help_items_fallbacks(plugin.id) if plugin_item.nil?
|
plugin_item = additionals_help_items_fallbacks plugin.id if plugin_item.nil?
|
||||||
|
|
||||||
next if plugin_item.nil?
|
next if plugin_item.nil?
|
||||||
|
|
||||||
@ -186,12 +188,12 @@ module AdditionalsMenuHelper
|
|||||||
s << if item[:title] == '-'
|
s << if item[:title] == '-'
|
||||||
tag.li tag.hr
|
tag.li tag.hr
|
||||||
else
|
else
|
||||||
html_options = { class: "help_item_#{idx}" }
|
html_options = { class: +"help_item_#{idx}" }
|
||||||
if item[:url].include? '://'
|
if item[:url].include? '://'
|
||||||
html_options[:class] << ' external'
|
html_options[:class] << ' external'
|
||||||
html_options[:target] = '_blank'
|
html_options[:target] = '_blank'
|
||||||
end
|
end
|
||||||
tag.li(link_to(item[:title], item[:url], html_options))
|
tag.li link_to(item[:title], item[:url], html_options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
safe_join s
|
safe_join s
|
||||||
@ -200,13 +202,8 @@ module AdditionalsMenuHelper
|
|||||||
# Plugin help items definition for plugins,
|
# Plugin help items definition for plugins,
|
||||||
# which do not have additionals_help_menu_items integration
|
# which do not have additionals_help_menu_items integration
|
||||||
def additionals_help_items_fallbacks(plugin_id)
|
def additionals_help_items_fallbacks(plugin_id)
|
||||||
plugins = { redmine_wiki_lists: [{ title: 'Wiki Lists Macros',
|
plugins = { redmine_drawio: [{ title: 'draw.io usage',
|
||||||
url: 'https://www.r-labs.org/projects/wiki_lists/wiki/Wiki_Lists_en' }],
|
url: 'https://github.com/mikitex70/redmine_drawio#usage' }],
|
||||||
redmine_wiki_extensions: [{ title: 'Wiki Extensions',
|
|
||||||
url: 'https://www.r-labs.org/projects/r-labs/wiki/Wiki_Extensions_en' }],
|
|
||||||
redmine_git_hosting: [{ title: 'Redmine Git Hosting',
|
|
||||||
url: 'http://redmine-git-hosting.io/get_started/',
|
|
||||||
admin: true }],
|
|
||||||
redmine_contacts: [{ title: 'Redmine CRM',
|
redmine_contacts: [{ title: 'Redmine CRM',
|
||||||
url: 'https://www.redmineup.com/pages/help/crm',
|
url: 'https://www.redmineup.com/pages/help/crm',
|
||||||
admin: true }],
|
admin: true }],
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AdditionalsProjectsHelper
|
module AdditionalsProjectsHelper
|
||||||
def project_overview_name(_project, dashboard = nil)
|
def project_overview_name(_project, dashboard = nil)
|
||||||
name = [l(:label_overview)]
|
name = [l(:label_overview)]
|
||||||
|
@ -1,22 +1,28 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AdditionalsQueriesHelper
|
module AdditionalsQueriesHelper
|
||||||
def additionals_query_session_key(object_type)
|
def additionals_query_session_key(object_type)
|
||||||
"#{object_type}_query".to_sym
|
"#{object_type}_query".to_sym
|
||||||
end
|
end
|
||||||
|
|
||||||
def additionals_retrieve_query(object_type, options = {})
|
def additionals_retrieve_query(object_type, user_filter: nil)
|
||||||
session_key = additionals_query_session_key object_type
|
session_key = additionals_query_session_key object_type
|
||||||
query_class = Object.const_get "#{object_type.camelcase}Query"
|
query_class = Object.const_get "#{object_type.camelcase}Query"
|
||||||
if params[:query_id].present?
|
if params[:query_id].present?
|
||||||
additionals_load_query_id(query_class, session_key, params[:query_id], options, object_type)
|
additionals_load_query_id query_class,
|
||||||
|
session_key,
|
||||||
|
params[:query_id],
|
||||||
|
object_type,
|
||||||
|
user_filter: user_filter
|
||||||
elsif api_request? ||
|
elsif api_request? ||
|
||||||
params[:set_filter] ||
|
params[:set_filter] ||
|
||||||
session[session_key].nil? ||
|
session[session_key].nil? ||
|
||||||
session[session_key][:project_id] != (@project ? @project.id : nil)
|
session[session_key][:project_id] != (@project ? @project.id : nil)
|
||||||
# Give it a name, required to be valid
|
# Give it a name, required to be valid
|
||||||
@query = query_class.new(name: '_')
|
@query = query_class.new name: '_'
|
||||||
@query.project = @project
|
@query.project = @project
|
||||||
@query.user_filter = options[:user_filter] if options[:user_filter]
|
@query.user_filter = user_filter if user_filter
|
||||||
@query.build_from_params(params)
|
@query.build_from_params params
|
||||||
session[session_key] = { project_id: @query.project_id }
|
session[session_key] = { project_id: @query.project_id }
|
||||||
# session has a limit to 4k, we have to use a cache for it for larger data
|
# session has a limit to 4k, we have to use a cache for it for larger data
|
||||||
Rails.cache.write(additionals_query_cache_key(object_type),
|
Rails.cache.write(additionals_query_cache_key(object_type),
|
||||||
@ -27,7 +33,7 @@ module AdditionalsQueriesHelper
|
|||||||
sort_criteria: params[:sort].presence || @query.sort_criteria.to_a)
|
sort_criteria: params[:sort].presence || @query.sort_criteria.to_a)
|
||||||
else
|
else
|
||||||
# retrieve from session
|
# retrieve from session
|
||||||
@query = query_class.find_by(id: session[session_key][:id]) if session[session_key][:id]
|
@query = query_class.find_by id: session[session_key][:id] if session[session_key][:id]
|
||||||
session_data = Rails.cache.read additionals_query_cache_key(object_type)
|
session_data = Rails.cache.read additionals_query_cache_key(object_type)
|
||||||
@query ||= query_class.new(name: '_',
|
@query ||= query_class.new(name: '_',
|
||||||
filters: session_data.nil? ? nil : session_data[:filters],
|
filters: session_data.nil? ? nil : session_data[:filters],
|
||||||
@ -51,14 +57,14 @@ module AdditionalsQueriesHelper
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def additionals_load_query_id(query_class, session_key, query_id, options, object_type)
|
def additionals_load_query_id(query_class, session_key, query_id, object_type, user_filter: nil)
|
||||||
scope = query_class.where(project_id: nil)
|
scope = query_class.where project_id: nil
|
||||||
scope = scope.or(query_class.where(project_id: @project.id)) if @project
|
scope = scope.or query_class.where(project_id: @project.id) if @project
|
||||||
@query = scope.find(query_id)
|
@query = scope.find query_id
|
||||||
raise ::Unauthorized unless @query.visible?
|
raise ::Unauthorized unless @query.visible?
|
||||||
|
|
||||||
@query.project = @project
|
@query.project = @project
|
||||||
@query.user_filter = options[:user_filter] if options[:user_filter]
|
@query.user_filter = user_filter if user_filter
|
||||||
session[session_key] = { id: @query.id, project_id: @query.project_id }
|
session[session_key] = { id: @query.id, project_id: @query.project_id }
|
||||||
|
|
||||||
@query.sort_criteria = params[:sort] if params[:sort].present?
|
@query.sort_criteria = params[:sort] if params[:sort].present?
|
||||||
@ -76,62 +82,58 @@ module AdditionalsQueriesHelper
|
|||||||
"#{object_type}_query_data_#{session.id}_#{project_id}"
|
"#{object_type}_query_data_#{session.id}_#{project_id}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def additionals_select2_search_users(options = {})
|
def additionals_select2_search_users(all_visible: false, where_filter: nil, where_params: nil)
|
||||||
q = params[:q].to_s.strip
|
q = params[:q].to_s.strip
|
||||||
exclude_id = params[:user_id].to_i
|
exclude_id = params[:user_id].to_i
|
||||||
scope = User.active.where type: 'User'
|
scope = User.active.where type: 'User'
|
||||||
scope = scope.visible unless options[:all_visible]
|
scope = scope.visible unless all_visible
|
||||||
scope = scope.where.not(id: exclude_id) if exclude_id.positive?
|
scope = scope.where.not id: exclude_id if exclude_id.positive?
|
||||||
scope = scope.where(options[:where_filter], options[:where_params]) if options[:where_filter]
|
scope = scope.where where_filter, where_params if where_filter
|
||||||
q.split.map { |search_string| scope = scope.like(search_string) } if q.present?
|
q.split.map { |search_string| scope = scope.like search_string } if q.present?
|
||||||
scope = scope.order(last_login_on: :desc)
|
scope = scope.order(last_login_on: :desc)
|
||||||
.limit(Additionals::SELECT2_INIT_ENTRIES)
|
.limit(Additionals::SELECT2_INIT_ENTRIES)
|
||||||
@users = scope.to_a.sort! { |x, y| x.name <=> y.name }
|
@users = scope.to_a.sort! { |x, y| x.name <=> y.name }
|
||||||
render layout: false, partial: 'auto_completes/additionals_users'
|
render layout: false, partial: 'auto_completes/additionals_users'
|
||||||
end
|
end
|
||||||
|
|
||||||
def additionals_query_to_xlsx(items, query, options = {})
|
def additionals_query_to_xlsx(items, query, no_id_link: false)
|
||||||
require 'write_xlsx'
|
require 'write_xlsx'
|
||||||
columns = if options[:columns].present? || options[:c].present?
|
|
||||||
query.available_columns
|
|
||||||
else
|
|
||||||
query.columns
|
|
||||||
end
|
|
||||||
|
|
||||||
options[:filename] = StringIO.new('')
|
options = { no_id_link: no_id_link,
|
||||||
|
filename: StringIO.new(+'') }
|
||||||
|
|
||||||
export_to_xlsx(items, columns, options)
|
export_to_xlsx items, query.columns, options
|
||||||
options[:filename].string
|
options[:filename].string
|
||||||
end
|
end
|
||||||
|
|
||||||
def additionals_result_to_xlsx(items, columns, options = {})
|
def additionals_result_to_xlsx(items, columns, options)
|
||||||
raise 'option filename is mission' if options[:filename].blank?
|
raise 'option filename is mission' if options[:filename].blank?
|
||||||
|
|
||||||
require 'write_xlsx'
|
require 'write_xlsx'
|
||||||
export_to_xlsx(items, columns, options)
|
export_to_xlsx items, columns, options
|
||||||
end
|
end
|
||||||
|
|
||||||
def export_to_xlsx(items, columns, options)
|
def export_to_xlsx(items, columns, options)
|
||||||
workbook = WriteXLSX.new(options[:filename])
|
workbook = WriteXLSX.new options[:filename]
|
||||||
worksheet = workbook.add_worksheet
|
worksheet = workbook.add_worksheet
|
||||||
|
|
||||||
# Freeze header row and # column.
|
# Freeze header row and # column.
|
||||||
freeze_row = options[:freeze_first_row].nil? || options[:freeze_first_row] ? 1 : 0
|
freeze_row = options[:freeze_first_row].nil? || options[:freeze_first_row] ? 1 : 0
|
||||||
freeze_column = options[:freeze_first_column].nil? || options[:freeze_first_column] ? 1 : 0
|
freeze_column = options[:freeze_first_column].nil? || options[:freeze_first_column] ? 1 : 0
|
||||||
worksheet.freeze_panes(freeze_row, freeze_column)
|
worksheet.freeze_panes freeze_row, freeze_column
|
||||||
|
|
||||||
options[:columns_width] = if options[:xlsx_write_header_row].present?
|
options[:columns_width] = if options[:xlsx_write_header_row].present?
|
||||||
send(options[:xlsx_write_header_row], workbook, worksheet, columns)
|
send options[:xlsx_write_header_row], workbook, worksheet, columns
|
||||||
else
|
else
|
||||||
xlsx_write_header_row(workbook, worksheet, columns)
|
xlsx_write_header_row workbook, worksheet, columns
|
||||||
end
|
end
|
||||||
options[:columns_width] = if options[:xlsx_write_item_rows].present?
|
options[:columns_width] = if options[:xlsx_write_item_rows].present?
|
||||||
send(options[:xlsx_write_item_rows], workbook, worksheet, columns, items, options)
|
send options[:xlsx_write_item_rows], workbook, worksheet, columns, items, options
|
||||||
else
|
else
|
||||||
xlsx_write_item_rows(workbook, worksheet, columns, items, options)
|
xlsx_write_item_rows workbook, worksheet, columns, items, options
|
||||||
end
|
end
|
||||||
columns.size.times do |index|
|
columns.size.times do |index|
|
||||||
worksheet.set_column(index, index, options[:columns_width][index])
|
worksheet.set_column index, index, options[:columns_width][index]
|
||||||
end
|
end
|
||||||
|
|
||||||
workbook.close
|
workbook.close
|
||||||
@ -152,20 +154,20 @@ module AdditionalsQueriesHelper
|
|||||||
columns_width
|
columns_width
|
||||||
end
|
end
|
||||||
|
|
||||||
def xlsx_write_item_rows(workbook, worksheet, columns, items, options = {})
|
def xlsx_write_item_rows(workbook, worksheet, columns, items, options)
|
||||||
hyperlink_format = workbook.add_format(xlsx_cell_format(:link))
|
hyperlink_format = workbook.add_format xlsx_cell_format(:link)
|
||||||
even_text_format = workbook.add_format(xlsx_cell_format(:text, '', 0))
|
even_text_format = workbook.add_format xlsx_cell_format(:text, '', 0)
|
||||||
even_text_format.set_num_format(0x31)
|
even_text_format.set_num_format 0x31
|
||||||
odd_text_format = workbook.add_format(xlsx_cell_format(:text, '', 1))
|
odd_text_format = workbook.add_format xlsx_cell_format(:text, '', 1)
|
||||||
odd_text_format.set_num_format(0x31)
|
odd_text_format.set_num_format 0x31
|
||||||
|
|
||||||
items.each_with_index do |line, line_index|
|
items.each_with_index do |line, line_index|
|
||||||
columns.each_with_index do |c, column_index|
|
columns.each_with_index do |c, column_index|
|
||||||
value = csv_content(c, line)
|
value = csv_content(c, line).dup
|
||||||
if c.name == :id # ID
|
if c.name == :id # ID
|
||||||
if options[:no_id_link].blank?
|
if options[:no_id_link].blank?
|
||||||
link = url_for(controller: line.class.name.underscore.pluralize, action: 'show', id: line.id)
|
link = url_for controller: line.class.name.underscore.pluralize, action: 'show', id: line.id
|
||||||
worksheet.write(line_index + 1, column_index, link, hyperlink_format, value)
|
worksheet.write line_index + 1, column_index, link, hyperlink_format, value
|
||||||
else
|
else
|
||||||
# id without link
|
# id without link
|
||||||
worksheet.write(line_index + 1,
|
worksheet.write(line_index + 1,
|
||||||
@ -173,13 +175,13 @@ module AdditionalsQueriesHelper
|
|||||||
value,
|
value,
|
||||||
workbook.add_format(xlsx_cell_format(:cell, value, line_index)))
|
workbook.add_format(xlsx_cell_format(:cell, value, line_index)))
|
||||||
end
|
end
|
||||||
elsif xlsx_hyperlink_cell?(value)
|
elsif xlsx_hyperlink_cell? value
|
||||||
worksheet.write(line_index + 1, column_index, value[0..254], hyperlink_format, value)
|
worksheet.write line_index + 1, column_index, value[0..254], hyperlink_format, value
|
||||||
elsif !c.inline?
|
elsif !c.inline?
|
||||||
# block column can be multiline strings
|
# block column can be multiline strings
|
||||||
value.gsub!("\r\n", "\n")
|
value.gsub! "\r\n", "\n"
|
||||||
text_format = line_index.even? ? even_text_format : odd_text_format
|
text_format = line_index.even? ? even_text_format : odd_text_format
|
||||||
worksheet.write_rich_string(line_index + 1, column_index, value, text_format)
|
worksheet.write_rich_string line_index + 1, column_index, value, text_format
|
||||||
else
|
else
|
||||||
worksheet.write(line_index + 1,
|
worksheet.write(line_index + 1,
|
||||||
column_index,
|
column_index,
|
||||||
@ -187,7 +189,7 @@ module AdditionalsQueriesHelper
|
|||||||
workbook.add_format(xlsx_cell_format(:cell, value, line_index)))
|
workbook.add_format(xlsx_cell_format(:cell, value, line_index)))
|
||||||
end
|
end
|
||||||
|
|
||||||
width = xlsx_get_column_width(value)
|
width = xlsx_get_column_width value
|
||||||
options[:columns_width][column_index] = width if options[:columns_width][column_index] < width
|
options[:columns_width][column_index] = width if options[:columns_width][column_index] < width
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -238,7 +240,7 @@ module AdditionalsQueriesHelper
|
|||||||
# TODO: this is a temporary fix and should be removed
|
# TODO: this is a temporary fix and should be removed
|
||||||
# after https://www.redmine.org/issues/29830 is in Redmine core.
|
# after https://www.redmine.org/issues/29830 is in Redmine core.
|
||||||
def query_as_hidden_field_tags(query)
|
def query_as_hidden_field_tags(query)
|
||||||
tags = hidden_field_tag('set_filter', '1', id: nil)
|
tags = hidden_field_tag 'set_filter', '1', id: nil
|
||||||
|
|
||||||
if query.filters.present?
|
if query.filters.present?
|
||||||
query.filters.each do |field, filter|
|
query.filters.each do |field, filter|
|
||||||
@ -254,7 +256,7 @@ module AdditionalsQueriesHelper
|
|||||||
|
|
||||||
ignored_block_columns = query.block_columns.map(&:name)
|
ignored_block_columns = query.block_columns.map(&:name)
|
||||||
query.columns.each do |column|
|
query.columns.each do |column|
|
||||||
next if ignored_block_columns.include?(column.name)
|
next if ignored_block_columns.include? column.name
|
||||||
|
|
||||||
tags << hidden_field_tag('c[]', column.name, id: nil)
|
tags << hidden_field_tag('c[]', column.name, id: nil)
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AdditionalsRoutesHelper
|
module AdditionalsRoutesHelper
|
||||||
def _dashboards_path(project, *args)
|
def _dashboards_path(project, *args)
|
||||||
if project
|
if project
|
||||||
@ -71,7 +73,7 @@ module AdditionalsRoutesHelper
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def dashboard_link_path(project, dashboard, options = {})
|
def dashboard_link_path(project, dashboard, **options)
|
||||||
options[:dashboard_id] = dashboard.id
|
options[:dashboard_id] = dashboard.id
|
||||||
if dashboard.dashboard_type == DashboardContentProject::TYPE_NAME
|
if dashboard.dashboard_type == DashboardContentProject::TYPE_NAME
|
||||||
project_path project, options
|
project_path project, options
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AdditionalsSelect2Helper
|
module AdditionalsSelect2Helper
|
||||||
def additionals_select2_tag(name, option_tags = nil, options = {})
|
def additionals_select2_tag(name, option_tags, options)
|
||||||
s = select_tag(name, option_tags, options)
|
s = select_tag name, option_tags, options
|
||||||
id = options.delete(:id) || sanitize_to_id(name)
|
id = options.delete(:id) || sanitize_to_id(name)
|
||||||
s << hidden_field_tag("#{name}[]", '') if options[:multiple] && options.fetch(:include_hidden, true)
|
s << hidden_field_tag("#{name}[]", '') if options[:multiple] && options.fetch(:include_hidden, true)
|
||||||
|
|
||||||
@ -8,7 +10,7 @@ module AdditionalsSelect2Helper
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Transforms select filters of +type+ fields into select2
|
# Transforms select filters of +type+ fields into select2
|
||||||
def additionals_transform_to_select2(type, options = {})
|
def additionals_transform_to_select2(type, options)
|
||||||
javascript_tag("setSelect2Filter('#{type}', #{options.to_json});") unless type.empty?
|
javascript_tag "setSelect2Filter('#{type}', #{options.to_json});" unless type.empty?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AdditionalsSettingsHelper
|
module AdditionalsSettingsHelper
|
||||||
def additionals_settings_tabs
|
def additionals_settings_tabs
|
||||||
tabs = [{ name: 'general', partial: 'additionals/settings/general', label: :label_general },
|
tabs = [{ name: 'general', partial: 'additionals/settings/general', label: :label_general },
|
||||||
@ -13,7 +15,7 @@ module AdditionalsSettingsHelper
|
|||||||
tabs
|
tabs
|
||||||
end
|
end
|
||||||
|
|
||||||
def additionals_settings_checkbox(name, options = {})
|
def additionals_settings_checkbox(name, **options)
|
||||||
active_value = options.delete(:active_value).presence || @settings.present? && @settings[name]
|
active_value = options.delete(:active_value).presence || @settings.present? && @settings[name]
|
||||||
tag_name = options.delete(:tag_name).presence || "settings[#{name}]"
|
tag_name = options.delete(:tag_name).presence || "settings[#{name}]"
|
||||||
|
|
||||||
@ -36,50 +38,50 @@ module AdditionalsSettingsHelper
|
|||||||
|
|
||||||
s = [label_tag(tag_name, label_title)]
|
s = [label_tag(tag_name, label_title)]
|
||||||
s << hidden_field_tag(tag_name, 0, id: nil) if !custom_value || value_is_bool
|
s << hidden_field_tag(tag_name, 0, id: nil) if !custom_value || value_is_bool
|
||||||
s << check_box_tag(tag_name, value, checked, options)
|
s << check_box_tag(tag_name, value, checked, **options)
|
||||||
safe_join s
|
safe_join s
|
||||||
end
|
end
|
||||||
|
|
||||||
def additionals_settings_numberfield(name, options = {})
|
def additionals_settings_numberfield(name, **options)
|
||||||
additionals_settings_input_field :number_field_tag, name, options
|
additionals_settings_input_field :number_field_tag, name, **options
|
||||||
end
|
end
|
||||||
|
|
||||||
def additionals_settings_textfield(name, options = {})
|
def additionals_settings_textfield(name, **options)
|
||||||
additionals_settings_input_field :text_field_tag, name, options
|
additionals_settings_input_field :text_field_tag, name, **options
|
||||||
end
|
end
|
||||||
|
|
||||||
def additionals_settings_passwordfield(name, options = {})
|
def additionals_settings_passwordfield(name, **options)
|
||||||
additionals_settings_input_field :password_field_tag, name, options
|
additionals_settings_input_field :password_field_tag, name, **options
|
||||||
end
|
end
|
||||||
|
|
||||||
def additionals_settings_urlfield(name, options = {})
|
def additionals_settings_urlfield(name, **options)
|
||||||
additionals_settings_input_field :url_field_tag, name, options
|
additionals_settings_input_field :url_field_tag, name, **options
|
||||||
end
|
end
|
||||||
|
|
||||||
def additionals_settings_select(name, values, options = {})
|
def additionals_settings_select(name, values, **options)
|
||||||
tag_name = options.delete(:tag_name).presence || "settings[#{name}]"
|
tag_name = options.delete(:tag_name).presence || "settings[#{name}]"
|
||||||
|
|
||||||
label_title = [options.delete(:label).presence || l("label_#{name}")]
|
label_title = [options.delete(:label).presence || l("label_#{name}")]
|
||||||
label_title << tag.span('*', class: 'required') if options[:required].present?
|
label_title << tag.span('*', class: 'required') if options[:required].present?
|
||||||
|
|
||||||
safe_join [label_tag(tag_name, safe_join(label_title, ' ')),
|
safe_join [label_tag(tag_name, safe_join(label_title, ' ')),
|
||||||
select_tag(tag_name, values, options)]
|
select_tag(tag_name, values, **options)]
|
||||||
end
|
end
|
||||||
|
|
||||||
def additionals_settings_textarea(name, options = {})
|
def additionals_settings_textarea(name, **options)
|
||||||
label_title = options.delete(:label).presence || l("label_#{name}")
|
label_title = options.delete(:label).presence || l("label_#{name}")
|
||||||
value = options.delete(:value).presence || @settings[name]
|
value = options.delete(:value).presence || @settings[name]
|
||||||
|
|
||||||
options[:class] = 'wiki-edit' unless options.key?(:class)
|
options[:class] = 'wiki-edit' unless options.key? :class
|
||||||
options[:rows] = addtionals_textarea_cols(value) unless options.key?(:rows)
|
options[:rows] = addtionals_textarea_cols value unless options.key? :rows
|
||||||
|
|
||||||
safe_join [label_tag("settings[#{name}]", label_title),
|
safe_join [label_tag("settings[#{name}]", label_title),
|
||||||
text_area_tag("settings[#{name}]", value, options)]
|
text_area_tag("settings[#{name}]", value, **options)]
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def additionals_settings_input_field(tag_field, name, options = {})
|
def additionals_settings_input_field(tag_field, name, **options)
|
||||||
tag_name = options.delete(:tag_name).presence || "settings[#{name}]"
|
tag_name = options.delete(:tag_name).presence || "settings[#{name}]"
|
||||||
value = if options.key? :value
|
value = if options.key? :value
|
||||||
options.delete(:value).presence
|
options.delete(:value).presence
|
||||||
@ -91,6 +93,6 @@ module AdditionalsSettingsHelper
|
|||||||
label_title << tag.span('*', class: 'required') if options[:required].present?
|
label_title << tag.span('*', class: 'required') if options[:required].present?
|
||||||
|
|
||||||
safe_join [label_tag(tag_name, safe_join(label_title, ' ')),
|
safe_join [label_tag(tag_name, safe_join(label_title, ' ')),
|
||||||
send(tag_field, tag_name, value, options)], ' '
|
send(tag_field, tag_name, value, **options)], ' '
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AdditionalsWikiPdfHelper
|
module AdditionalsWikiPdfHelper
|
||||||
include Redmine::Export::PDF
|
include Redmine::Export::PDF
|
||||||
|
|
||||||
def wiki_page_to_pdf(page, project)
|
def wiki_page_to_pdf(page, project)
|
||||||
pdf = ITCPDF.new(current_language)
|
pdf = ITCPDF.new current_language
|
||||||
pdf.set_title("#{project} - #{page.title}")
|
pdf.set_title "#{project} - #{page.title}"
|
||||||
pdf.alias_nb_pages
|
pdf.alias_nb_pages
|
||||||
pdf.footer_date = format_date(User.current.today)
|
pdf.footer_date = format_date User.current.today
|
||||||
pdf.add_page
|
pdf.add_page
|
||||||
unless Additionals.setting?(:wiki_pdf_remove_title)
|
unless Additionals.setting? :wiki_pdf_remove_title
|
||||||
pdf.SetFontStyle('B', 11)
|
pdf.SetFontStyle 'B', 11
|
||||||
pdf.RDMMultiCell(190, 5,
|
pdf.RDMMultiCell(190, 5,
|
||||||
"#{project} - #{page.title} - # #{page.content.version}")
|
"#{project} - #{page.title} - # #{page.content.version}")
|
||||||
end
|
end
|
||||||
pdf.ln
|
pdf.ln
|
||||||
# Set resize image scale
|
# Set resize image scale
|
||||||
pdf.set_image_scale(1.6)
|
pdf.set_image_scale 1.6
|
||||||
pdf.SetFontStyle('', 9)
|
pdf.SetFontStyle '', 9
|
||||||
if Additionals.setting?(:wiki_pdf_remove_attachments)
|
if Additionals.setting? :wiki_pdf_remove_attachments
|
||||||
pdf.RDMwriteFormattedCell(190,
|
pdf.RDMwriteFormattedCell(190,
|
||||||
5,
|
5,
|
||||||
'',
|
'',
|
||||||
@ -28,7 +30,7 @@ module AdditionalsWikiPdfHelper
|
|||||||
headings: false,
|
headings: false,
|
||||||
inline_attachments: false), page.attachments)
|
inline_attachments: false), page.attachments)
|
||||||
else
|
else
|
||||||
write_wiki_page(pdf, page)
|
write_wiki_page pdf, page
|
||||||
end
|
end
|
||||||
pdf.output
|
pdf.output
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module DashboardsHelper
|
module DashboardsHelper
|
||||||
def dashboard_async_cache(dashboard, block, async, settings, &content_block)
|
def dashboard_async_cache(dashboard, block, async, settings, &content_block)
|
||||||
cache render_async_cache_key(_dashboard_async_blocks_path(@project, dashboard.async_params(block, async, settings))),
|
cache render_async_cache_key(_dashboard_async_blocks_path(@project, dashboard.async_params(block, async, settings))),
|
||||||
@ -32,7 +34,7 @@ module DashboardsHelper
|
|||||||
|
|
||||||
def sidebar_dashboards(dashboard, project = nil, user = nil)
|
def sidebar_dashboards(dashboard, project = nil, user = nil)
|
||||||
user ||= User.current
|
user ||= User.current
|
||||||
scope = Dashboard.visible.includes([:author])
|
scope = Dashboard.visible.includes [:author]
|
||||||
|
|
||||||
scope = if project.present?
|
scope = if project.present?
|
||||||
scope = scope.project_only
|
scope = scope.project_only
|
||||||
@ -111,7 +113,7 @@ module DashboardsHelper
|
|||||||
return '' unless dashboards.any?
|
return '' unless dashboards.any?
|
||||||
|
|
||||||
tag.h3(title, class: 'dashboards') +
|
tag.h3(title, class: 'dashboards') +
|
||||||
tag.ul(class: 'dashboards') do
|
tag.ul(class: 'dashboards') do # rubocop: disable Style/MethodCallWithArgsParentheses
|
||||||
dashboards.each do |dashboard|
|
dashboards.each do |dashboard|
|
||||||
selected = dashboard.id == if params[:dashboard_id].present?
|
selected = dashboard.id == if params[:dashboard_id].present?
|
||||||
params[:dashboard_id].to_i
|
params[:dashboard_id].to_i
|
||||||
@ -119,7 +121,7 @@ module DashboardsHelper
|
|||||||
active_dashboard.id
|
active_dashboard.id
|
||||||
end
|
end
|
||||||
|
|
||||||
css = 'dashboard'
|
css = +'dashboard'
|
||||||
css << ' selected' if selected
|
css << ' selected' if selected
|
||||||
li_class = nil
|
li_class = nil
|
||||||
|
|
||||||
@ -143,14 +145,14 @@ module DashboardsHelper
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def dashboard_link(dashboard, project, options = {})
|
def dashboard_link(dashboard, project, **options)
|
||||||
if options[:title].blank? && dashboard.public?
|
if options[:title].blank? && dashboard.public?
|
||||||
author = if dashboard.author_id == User.current.id
|
author = if dashboard.author_id == User.current.id
|
||||||
l :label_me
|
l :label_me
|
||||||
else
|
else
|
||||||
dashboard.author
|
dashboard.author
|
||||||
end
|
end
|
||||||
options[:title] = l(:label_dashboard_author, name: author)
|
options[:title] = l :label_dashboard_author, name: author
|
||||||
end
|
end
|
||||||
|
|
||||||
name = options.delete(:name) || dashboard.name
|
name = options.delete(:name) || dashboard.name
|
||||||
@ -171,10 +173,10 @@ module DashboardsHelper
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_dashboard_link(url, options = {})
|
def delete_dashboard_link(url)
|
||||||
options = { method: :delete,
|
options = { method: :delete,
|
||||||
data: { confirm: l(:text_are_you_sure) },
|
data: { confirm: l(:text_are_you_sure) },
|
||||||
class: 'icon icon-del' }.merge(options)
|
class: 'icon icon-del' }
|
||||||
|
|
||||||
link_to l(:button_dashboard_delete), url, options
|
link_to l(:button_dashboard_delete), url, options
|
||||||
end
|
end
|
||||||
@ -252,7 +254,7 @@ module DashboardsHelper
|
|||||||
exposed_params: %i[sort],
|
exposed_params: %i[sort],
|
||||||
partial: 'dashboards/blocks/query_list' }
|
partial: 'dashboards/blocks/query_list' }
|
||||||
partial_locals[:async][:unique_params] = [Redmine::Utils.random_hex(16)] if params[:refresh].present?
|
partial_locals[:async][:unique_params] = [Redmine::Utils.random_hex(16)] if params[:refresh].present?
|
||||||
partial_locals[:async] = partial_locals[:async].merge(block_definition[:async]) if block_definition[:async]
|
partial_locals[:async] = partial_locals[:async].merge block_definition[:async] if block_definition[:async]
|
||||||
elsif block_definition[:async]
|
elsif block_definition[:async]
|
||||||
partial_locals[:async] = block_definition[:async]
|
partial_locals[:async] = block_definition[:async]
|
||||||
end
|
end
|
||||||
@ -277,9 +279,9 @@ module DashboardsHelper
|
|||||||
title << query_block[:label]
|
title << query_block[:label]
|
||||||
|
|
||||||
title << if query_block[:with_project]
|
title << if query_block[:with_project]
|
||||||
link_to(query.name, send(query_block[:link_helper], project, query.as_params))
|
link_to query.name, send(query_block[:link_helper], project, query.as_params)
|
||||||
else
|
else
|
||||||
link_to(query.name, send(query_block[:link_helper], query.as_params))
|
link_to query.name, send(query_block[:link_helper], query.as_params)
|
||||||
end
|
end
|
||||||
|
|
||||||
safe_join title, Additionals::LIST_SEPARATOR
|
safe_join title, Additionals::LIST_SEPARATOR
|
||||||
@ -289,9 +291,9 @@ module DashboardsHelper
|
|||||||
return if dashboard.visibility == Dashboard::VISIBILITY_PRIVATE
|
return if dashboard.visibility == Dashboard::VISIBILITY_PRIVATE
|
||||||
|
|
||||||
title = if query.visibility == Query::VISIBILITY_PRIVATE
|
title = if query.visibility == Query::VISIBILITY_PRIVATE
|
||||||
l(:alert_only_visible_by_yourself)
|
l :alert_only_visible_by_yourself
|
||||||
elsif block_definition.key?(:admin_only) && block_definition[:admin_only]
|
elsif block_definition.key?(:admin_only) && block_definition[:admin_only]
|
||||||
l(:alert_only_visible_by_admins)
|
l :alert_only_visible_by_admins
|
||||||
end
|
end
|
||||||
|
|
||||||
return if title.nil?
|
return if title.nil?
|
||||||
@ -322,7 +324,7 @@ module DashboardsHelper
|
|||||||
max_entries = settings[:max_entries] || DashboardContent::DEFAULT_MAX_ENTRIES
|
max_entries = settings[:max_entries] || DashboardContent::DEFAULT_MAX_ENTRIES
|
||||||
|
|
||||||
scope = Document.visible
|
scope = Document.visible
|
||||||
scope = scope.where(project: dashboard.project) if dashboard.project
|
scope = scope.where project: dashboard.project if dashboard.project
|
||||||
|
|
||||||
documents = scope.order(created_on: :desc)
|
documents = scope.order(created_on: :desc)
|
||||||
.limit(max_entries)
|
.limit(max_entries)
|
||||||
@ -357,10 +359,10 @@ module DashboardsHelper
|
|||||||
days = 7 if days < 1 || days > 365
|
days = 7 if days < 1 || days > 365
|
||||||
|
|
||||||
scope = TimeEntry.where user_id: User.current.id
|
scope = TimeEntry.where user_id: User.current.id
|
||||||
scope = scope.where(project_id: dashboard.content_project.id) unless dashboard.content_project.nil?
|
scope = scope.where project_id: dashboard.content_project.id unless dashboard.content_project.nil?
|
||||||
|
|
||||||
entries_today = scope.where(spent_on: User.current.today)
|
entries_today = scope.where spent_on: User.current.today
|
||||||
entries_days = scope.where(spent_on: User.current.today - (days - 1)..User.current.today)
|
entries_days = scope.where spent_on: User.current.today - (days - 1)..User.current.today
|
||||||
|
|
||||||
render partial: 'dashboards/blocks/my_spent_time',
|
render partial: 'dashboards/blocks/my_spent_time',
|
||||||
locals: { block: block,
|
locals: { block: block,
|
||||||
@ -379,7 +381,7 @@ module DashboardsHelper
|
|||||||
|
|
||||||
Redmine::Activity::Fetcher.new(user, options)
|
Redmine::Activity::Fetcher.new(user, options)
|
||||||
.events(nil, nil, limit: max_entries)
|
.events(nil, nil, limit: max_entries)
|
||||||
.group_by { |event| user.time_to_date(event.event_datetime) }
|
.group_by { |event| user.time_to_date event.event_datetime }
|
||||||
end
|
end
|
||||||
|
|
||||||
def dashboard_feed_catcher(url, max_entries)
|
def dashboard_feed_catcher(url, max_entries)
|
||||||
@ -391,7 +393,7 @@ module DashboardsHelper
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
URI.parse(url).open do |rss_feed|
|
URI.parse(url).open do |rss_feed|
|
||||||
rss = RSS::Parser.parse(rss_feed)
|
rss = RSS::Parser.parse rss_feed
|
||||||
rss.items.each do |item|
|
rss.items.each do |item|
|
||||||
cnt += 1
|
cnt += 1
|
||||||
feed[:items] << { title: item.title.try(:content)&.presence || item.title,
|
feed[:items] << { title: item.title.try(:content)&.presence || item.title,
|
||||||
@ -430,7 +432,7 @@ module DashboardsHelper
|
|||||||
# Renders a single block content
|
# Renders a single block content
|
||||||
def render_dashboard_block_content(block, block_definition, dashboard, overwritten_settings = {})
|
def render_dashboard_block_content(block, block_definition, dashboard, overwritten_settings = {})
|
||||||
settings = dashboard.layout_settings block
|
settings = dashboard.layout_settings block
|
||||||
settings = settings.merge(overwritten_settings) if overwritten_settings.present?
|
settings = settings.merge overwritten_settings if overwritten_settings.present?
|
||||||
|
|
||||||
partial = block_definition[:partial]
|
partial = block_definition[:partial]
|
||||||
partial_locals = build_dashboard_partial_locals block, block_definition, settings, dashboard
|
partial_locals = build_dashboard_partial_locals block, block_definition, settings, dashboard
|
||||||
@ -441,7 +443,7 @@ module DashboardsHelper
|
|||||||
begin
|
begin
|
||||||
render partial: partial, locals: partial_locals
|
render partial: partial, locals: partial_locals
|
||||||
rescue ActionView::MissingTemplate
|
rescue ActionView::MissingTemplate
|
||||||
Rails.logger.warn("Partial \"#{partial}\" missing for block \"#{block}\" found in #{dashboard.name} (id=#{dashboard.id})")
|
Rails.logger.warn "Partial \"#{partial}\" missing for block \"#{block}\" found in #{dashboard.name} (id=#{dashboard.id})"
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AdditionalsJob < ActiveJob::Base
|
class AdditionalsJob < ActiveJob::Base
|
||||||
# Automatically retry jobs that encountered a deadlock
|
# Automatically retry jobs that encountered a deadlock
|
||||||
# retry_on ActiveRecord::Deadlocked
|
# retry_on ActiveRecord::Deadlocked
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AdditionalsChart
|
class AdditionalsChart
|
||||||
include ActiveRecord::Sanitization
|
include ActiveRecord::Sanitization
|
||||||
include Redmine::I18n
|
include Redmine::I18n
|
||||||
@ -15,7 +17,7 @@ class AdditionalsChart
|
|||||||
end
|
end
|
||||||
|
|
||||||
# build return value
|
# build return value
|
||||||
def build_chart_data(datasets, options = {})
|
def build_chart_data(datasets, **options)
|
||||||
cached_labels = labels
|
cached_labels = labels
|
||||||
data = { datasets: datasets.to_json,
|
data = { datasets: datasets.to_json,
|
||||||
labels: cached_labels.keys,
|
labels: cached_labels.keys,
|
||||||
@ -23,13 +25,13 @@ class AdditionalsChart
|
|||||||
|
|
||||||
required_labels = options.key?(:required_labels) ? options.delete(:required_labels) : 2
|
required_labels = options.key?(:required_labels) ? options.delete(:required_labels) : 2
|
||||||
|
|
||||||
data[:valid] = cached_labels.any? && cached_labels.count >= required_labels unless options.key?(:valid)
|
data[:valid] = cached_labels.any? && cached_labels.count >= required_labels unless options.key? :valid
|
||||||
data[:width] = self::CHART_DEFAULT_WIDTH unless options.key?(:width)
|
data[:width] = self::CHART_DEFAULT_WIDTH unless options.key? :width
|
||||||
data[:height] = self::CHART_DEFAULT_HEIGHT unless options.key?(:height)
|
data[:height] = self::CHART_DEFAULT_HEIGHT unless options.key? :height
|
||||||
data[:value_link_method] = '_project_issues_path' unless options.key?(:value_link_method)
|
data[:value_link_method] = '_project_issues_path' unless options.key? :value_link_method
|
||||||
data[:color_schema] = color_schema
|
data[:color_schema] = color_schema
|
||||||
|
|
||||||
data.merge(options)
|
data.merge options
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@ -37,7 +39,7 @@ class AdditionalsChart
|
|||||||
def build_values_without_gaps(data, gap_value = 0)
|
def build_values_without_gaps(data, gap_value = 0)
|
||||||
values = []
|
values = []
|
||||||
labels.each do |label, _label_id|
|
labels.each do |label, _label_id|
|
||||||
values << if data.key?(label)
|
values << if data.key? label
|
||||||
data[label]
|
data[label]
|
||||||
else
|
else
|
||||||
gap_value
|
gap_value
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AdditionalsFontAwesome
|
class AdditionalsFontAwesome
|
||||||
include Redmine::I18n
|
include Redmine::I18n
|
||||||
|
|
||||||
@ -9,7 +11,7 @@ class AdditionalsFontAwesome
|
|||||||
data = YAML.safe_load(ERB.new(IO.read(File.join(Additionals.plugin_dir, 'config', 'fontawesome_icons.yml'))).result) || {}
|
data = YAML.safe_load(ERB.new(IO.read(File.join(Additionals.plugin_dir, 'config', 'fontawesome_icons.yml'))).result) || {}
|
||||||
icons = {}
|
icons = {}
|
||||||
data.each do |key, values|
|
data.each do |key, values|
|
||||||
icons[key] = { unicode: values['unicode'], label: values['label'] } if values['styles'].include?(convert_type2style(type))
|
icons[key] = { unicode: values['unicode'], label: values['label'] } if values['styles'].include? convert_type2style(type)
|
||||||
end
|
end
|
||||||
icons
|
icons
|
||||||
end
|
end
|
||||||
@ -48,7 +50,7 @@ class AdditionalsFontAwesome
|
|||||||
end
|
end
|
||||||
|
|
||||||
def classes(value)
|
def classes(value)
|
||||||
info = value_info(value)
|
info = value_info value
|
||||||
return '' if info.blank?
|
return '' if info.blank?
|
||||||
|
|
||||||
info[:classes]
|
info[:classes]
|
||||||
@ -65,27 +67,27 @@ class AdditionalsFontAwesome
|
|||||||
# show only one value as current selected
|
# show only one value as current selected
|
||||||
# (all other options are retrieved by select2
|
# (all other options are retrieved by select2
|
||||||
def active_option_for_select(selected)
|
def active_option_for_select(selected)
|
||||||
info = value_info(selected, with_details: true)
|
info = value_info selected, with_details: true
|
||||||
return [] if info.blank?
|
return [] if info.blank?
|
||||||
|
|
||||||
[[info[:label], selected]]
|
[[info[:label], selected]]
|
||||||
end
|
end
|
||||||
|
|
||||||
def value_info(value, options = {})
|
def value_info(value, with_details: false)
|
||||||
return {} if value.blank?
|
return {} if value.blank?
|
||||||
|
|
||||||
values = value.split('_')
|
values = value.split '_'
|
||||||
return {} unless values.count == 2
|
return {} unless values.count == 2
|
||||||
|
|
||||||
info = { type: values[0].to_sym,
|
info = { type: values[0].to_sym,
|
||||||
name: "fa-#{values[1]}" }
|
name: "fa-#{values[1]}" }
|
||||||
|
|
||||||
info[:classes] = "#{info[:type]} #{info[:name]}"
|
info[:classes] = "#{info[:type]} #{info[:name]}"
|
||||||
info[:font_weight] = font_weight(info[:type])
|
info[:font_weight] = font_weight info[:type]
|
||||||
info[:font_family] = font_family(info[:type])
|
info[:font_family] = font_family info[:type]
|
||||||
|
|
||||||
if options[:with_details]
|
if with_details
|
||||||
info.merge!(load_details(info[:type], values[1]))
|
info.merge! load_details(info[:type], values[1])
|
||||||
return {} if info[:unicode].blank?
|
return {} if info[:unicode].blank?
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -94,12 +96,12 @@ class AdditionalsFontAwesome
|
|||||||
|
|
||||||
def search_for_select(search, selected = nil)
|
def search_for_select(search, selected = nil)
|
||||||
# could be more then one
|
# could be more then one
|
||||||
selected_store = selected.to_s.split(',')
|
selected_store = selected.to_s.split ','
|
||||||
icons = search_in_type(:far, search, selected_store)
|
icons = search_in_type :far, search, selected_store
|
||||||
cnt = icons.count
|
cnt = icons.count
|
||||||
return icons if cnt >= SEARCH_LIMIT
|
return icons if cnt >= SEARCH_LIMIT
|
||||||
|
|
||||||
icons += search_in_type(:fas, search, selected_store, cnt)
|
icons += search_in_type :fas, search, selected_store, cnt
|
||||||
cnt = icons.count
|
cnt = icons.count
|
||||||
return icons if cnt >= SEARCH_LIMIT
|
return icons if cnt >= SEARCH_LIMIT
|
||||||
|
|
||||||
@ -109,7 +111,7 @@ class AdditionalsFontAwesome
|
|||||||
def convert2mermaid(icon)
|
def convert2mermaid(icon)
|
||||||
return if icon.blank?
|
return if icon.blank?
|
||||||
|
|
||||||
parts = icon.split('_')
|
parts = icon.split '_'
|
||||||
return unless parts.count == 2
|
return unless parts.count == 2
|
||||||
|
|
||||||
"#{parts.first}:fa-#{parts.last}"
|
"#{parts.first}:fa-#{parts.last}"
|
||||||
@ -125,7 +127,7 @@ class AdditionalsFontAwesome
|
|||||||
search[0].downcase
|
search[0].downcase
|
||||||
elsif search_length.zero? && selected_store.any?
|
elsif search_length.zero? && selected_store.any?
|
||||||
selected = selected_store.first
|
selected = selected_store.first
|
||||||
fa = selected.split('_')
|
fa = selected.split '_'
|
||||||
search = fa[1][0] if fa.count > 1
|
search = fa[1][0] if fa.count > 1
|
||||||
search
|
search
|
||||||
end
|
end
|
||||||
@ -147,7 +149,7 @@ class AdditionalsFontAwesome
|
|||||||
end
|
end
|
||||||
|
|
||||||
def load_details(type, name)
|
def load_details(type, name)
|
||||||
return {} unless FONTAWESOME_ICONS.key?(type)
|
return {} unless FONTAWESOME_ICONS.key? type
|
||||||
|
|
||||||
values = FONTAWESOME_ICONS[type][name]
|
values = FONTAWESOME_ICONS[type][name]
|
||||||
return {} if values.blank?
|
return {} if values.blank?
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AdditionalsImport < Import
|
class AdditionalsImport < Import
|
||||||
class_attribute :import_class
|
class_attribute :import_class
|
||||||
|
|
||||||
# Returns the objects that were imported
|
# Returns the objects that were imported
|
||||||
def saved_objects
|
def saved_objects
|
||||||
object_ids = saved_items.pluck(:obj_id)
|
object_ids = saved_items.pluck :obj_id
|
||||||
import_class.where(id: object_ids).order(:id)
|
import_class.where(id: object_ids).order(:id)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -24,17 +26,17 @@ class AdditionalsImport < Import
|
|||||||
object.custom_field_values.each_with_object({}) do |v, h|
|
object.custom_field_values.each_with_object({}) do |v, h|
|
||||||
value = case v.custom_field.field_format
|
value = case v.custom_field.field_format
|
||||||
when 'date'
|
when 'date'
|
||||||
row_date(row, "cf_#{v.custom_field.id}")
|
row_date row, "cf_#{v.custom_field.id}"
|
||||||
else
|
else
|
||||||
row_value(row, "cf_#{v.custom_field.id}")
|
row_value row, "cf_#{v.custom_field.id}"
|
||||||
end
|
end
|
||||||
next unless value
|
next unless value
|
||||||
|
|
||||||
h[v.custom_field.id.to_s] =
|
h[v.custom_field.id.to_s] =
|
||||||
if value.is_a? Array
|
if value.is_a? Array
|
||||||
value.map { |val| v.custom_field.value_from_keyword(val.strip, object) }.flatten!&.compact
|
value.map { |val| v.custom_field.value_from_keyword val.strip, object }.flatten!&.compact
|
||||||
else
|
else
|
||||||
v.custom_field.value_from_keyword(value, object)
|
v.custom_field.value_from_keyword value, object
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AdditionalsInfo
|
class AdditionalsInfo
|
||||||
include Redmine::I18n
|
include Redmine::I18n
|
||||||
|
|
||||||
@ -43,11 +45,11 @@ class AdditionalsInfo
|
|||||||
days = (secs / 86_400).round
|
days = (secs / 86_400).round
|
||||||
end
|
end
|
||||||
if days >= 1
|
if days >= 1
|
||||||
"#{days} #{l(:days, count: days)}"
|
"#{days} #{l :days, count: days}"
|
||||||
elsif hours >= 1
|
elsif hours >= 1
|
||||||
"#{hours} #{l(:hours, count: hours)}"
|
"#{hours} #{l :hours, count: hours}"
|
||||||
else
|
else
|
||||||
"#{min} #{l(:minutes, count: min)}"
|
"#{min} #{l :minutes, count: min}"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
# this should be work on macOS
|
# this should be work on macOS
|
||||||
@ -61,7 +63,7 @@ class AdditionalsInfo
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
days = `uptime | awk '{print $3}'`.to_i.round
|
days = `uptime | awk '{print $3}'`.to_i.round
|
||||||
"#{days} #{l(:days, count: days)}"
|
"#{days} #{l :days, count: days}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AdditionalsJournal
|
class AdditionalsJournal
|
||||||
class << self
|
class << self
|
||||||
def save_journal_history(journal, prop_key, ids_old, ids)
|
def save_journal_history(journal, prop_key, ids_old, ids)
|
||||||
@ -6,7 +8,7 @@ class AdditionalsJournal
|
|||||||
ids_all.each do |id|
|
ids_all.each do |id|
|
||||||
next if ids_old.include?(id) && ids.include?(id)
|
next if ids_old.include?(id) && ids.include?(id)
|
||||||
|
|
||||||
if ids.include?(id)
|
if ids.include? id
|
||||||
value = id
|
value = id
|
||||||
old_value = nil
|
old_value = nil
|
||||||
else
|
else
|
||||||
@ -29,10 +31,10 @@ class AdditionalsJournal
|
|||||||
new_entries = entries.select { |entry| entry.id.blank? }
|
new_entries = entries.select { |entry| entry.id.blank? }
|
||||||
return true if new_entries.blank?
|
return true if new_entries.blank?
|
||||||
|
|
||||||
new_entries.map! { |entry| entry.send(entry_id) }
|
new_entries.map! { |entry| entry.send entry_id }
|
||||||
return false if new_entries.count != new_entries.uniq.count
|
return false if new_entries.count != new_entries.uniq.count
|
||||||
|
|
||||||
old_entries.map! { |entry| entry.send(entry_id) }
|
old_entries.map! { |entry| entry.send entry_id }
|
||||||
return false unless (old_entries & new_entries).count.zero?
|
return false unless (old_entries & new_entries).count.zero?
|
||||||
|
|
||||||
true
|
true
|
||||||
|
@ -1,75 +1,81 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AdditionalsMacro
|
class AdditionalsMacro
|
||||||
def self.all(options = {})
|
class << self
|
||||||
all = Redmine::WikiFormatting::Macros.available_macros
|
def all(only_names: false, filtered: [], controller_only: nil)
|
||||||
macros = {}
|
all = Redmine::WikiFormatting::Macros.available_macros
|
||||||
macro_list = []
|
macros = {}
|
||||||
|
macro_list = []
|
||||||
|
|
||||||
# needs to run every request (for each user once)
|
# needs to run every request (for each user once)
|
||||||
permissions = build_permissions(options)
|
permissions = build_permissions controller_only: controller_only
|
||||||
|
|
||||||
if options[:filtered].present?
|
if filtered.present?
|
||||||
options[:filtered] << 'hello_world'
|
filtered << 'hello_world'
|
||||||
else
|
else
|
||||||
options[:filtered] = ['hello_world']
|
filtered = ['hello_world']
|
||||||
|
end
|
||||||
|
|
||||||
|
all.each do |macro, macro_options|
|
||||||
|
next if filtered.include? macro.to_s
|
||||||
|
next unless macro_allowed macro, permissions
|
||||||
|
|
||||||
|
macro_list << macro.to_s
|
||||||
|
macros[macro] = macro_options
|
||||||
|
end
|
||||||
|
|
||||||
|
if only_names
|
||||||
|
macro_list.sort
|
||||||
|
else
|
||||||
|
macros.sort
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
all.each do |macro, macro_options|
|
private
|
||||||
next if options[:filtered].include?(macro.to_s)
|
|
||||||
next unless macro_allowed(macro, permissions)
|
|
||||||
|
|
||||||
macro_list << macro.to_s
|
def macro_allowed(macro, permissions)
|
||||||
macros[macro] = macro_options
|
permissions.each do |permission|
|
||||||
|
next if permission[:list].exclude? macro
|
||||||
|
return false unless permission[:access]
|
||||||
|
end
|
||||||
|
|
||||||
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
if options[:only_names]
|
def build_permissions(controller_only: nil)
|
||||||
macro_list.sort
|
gpermission = []
|
||||||
else
|
macro_permissions.each do |permission|
|
||||||
macros.sort
|
permission[:access] = if controller_only &&
|
||||||
end
|
permission[:controller].present? &&
|
||||||
end
|
controller_only.to_sym != permission[:controller]
|
||||||
|
false
|
||||||
|
else
|
||||||
|
User.current.allowed_to? permission[:permission], nil, global: true
|
||||||
|
end
|
||||||
|
gpermission << permission
|
||||||
|
end
|
||||||
|
|
||||||
def self.macro_allowed(macro, permissions)
|
gpermission
|
||||||
permissions.each do |permission|
|
|
||||||
next if permission[:list].exclude?(macro)
|
|
||||||
return false unless permission[:access]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
true
|
def macro_permissions
|
||||||
end
|
[{ list: %i[issue issue_name_link],
|
||||||
|
permission: :view_issues },
|
||||||
def self.build_permissions(options)
|
{ list: %i[password password_query password_tag password_tag_count],
|
||||||
gpermission = []
|
permission: :view_passwords },
|
||||||
macro_permissions.each do |permission|
|
{ list: %i[contact deal contact_avatar contact_note contact_plain],
|
||||||
permission[:access] = if options[:controller_only] &&
|
permission: :view_contacts },
|
||||||
permission[:controller].present? &&
|
{ list: %i[db db_query db_tag db_tag_count],
|
||||||
options[:controller_only].to_sym != permission[:controller]
|
permission: :view_db_entries },
|
||||||
false
|
{ list: %i[child_pages last_updated_at last_updated_by lastupdated_at lastupdated_by
|
||||||
else
|
new_page recently_updated recent comments comment_form tags taggedpages tagcloud
|
||||||
User.current.allowed_to?(permission[:permission], nil, global: true)
|
show_count count vote show_vote terms_accept terms_reject],
|
||||||
end
|
permission: :view_wiki_pages,
|
||||||
gpermission << permission
|
controller: :wiki },
|
||||||
|
{ list: %i[mail send_file],
|
||||||
|
permission: :view_helpdesk_tickets },
|
||||||
|
{ list: %i[kb article_id article category],
|
||||||
|
permission: :view_kb_articles }]
|
||||||
end
|
end
|
||||||
|
|
||||||
gpermission
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.macro_permissions
|
|
||||||
[{ list: %i[issue issue_name_link],
|
|
||||||
permission: :view_issues },
|
|
||||||
{ list: %i[password password_query password_tag password_tag_count],
|
|
||||||
permission: :view_passwords },
|
|
||||||
{ list: %i[contact deal contact_avatar contact_note contact_plain],
|
|
||||||
permission: :view_contacts },
|
|
||||||
{ list: %i[db db_query db_tag db_tag_count],
|
|
||||||
permission: :view_db_entries },
|
|
||||||
{ list: %i[child_pages last_updated_at last_updated_by lastupdated_at lastupdated_by
|
|
||||||
new_page recently_updated recent comments comment_form tags taggedpages tagcloud
|
|
||||||
show_count count vote show_vote terms_accept terms_reject],
|
|
||||||
permission: :view_wiki_pages,
|
|
||||||
controller: :wiki },
|
|
||||||
{ list: %i[mail send_file],
|
|
||||||
permission: :view_helpdesk_tickets },
|
|
||||||
{ list: %i[kb article_id article category],
|
|
||||||
permission: :view_kb_articles }]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AdditionalsQuery
|
module AdditionalsQuery
|
||||||
def column_with_prefix?(prefix)
|
def column_with_prefix?(prefix)
|
||||||
columns.detect { |c| c.name.to_s.start_with?("#{prefix}.") }.present?
|
columns.detect { |c| c.name.to_s.start_with? "#{prefix}." }.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def available_column_names(options = {})
|
def available_column_names(only_sortable: false)
|
||||||
names = available_columns.dup
|
names = available_columns.dup
|
||||||
names.flatten!
|
names.flatten!
|
||||||
names.select! { |col| col.sortable.present? } if options[:only_sortable]
|
names.select! { |col| col.sortable.present? } if only_sortable
|
||||||
names.map(&:name)
|
names.map(&:name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def sql_for_enabled_module(table_field, module_names)
|
def sql_for_enabled_module(table_field, module_names)
|
||||||
module_names = Array(module_names)
|
module_names = Array module_names
|
||||||
|
|
||||||
sql = []
|
sql = []
|
||||||
module_names.each do |module_name|
|
module_names.each do |module_name|
|
||||||
@ -19,7 +21,7 @@ module AdditionalsQuery
|
|||||||
" AND #{EnabledModule.table_name}.name='#{module_name}')"
|
" AND #{EnabledModule.table_name}.name='#{module_name}')"
|
||||||
end
|
end
|
||||||
|
|
||||||
sql.join(' AND ')
|
sql.join ' AND '
|
||||||
end
|
end
|
||||||
|
|
||||||
def fix_sql_for_text_field(field, operator, value, table_name = nil, target_field = nil)
|
def fix_sql_for_text_field(field, operator, value, table_name = nil, target_field = nil)
|
||||||
@ -27,15 +29,15 @@ module AdditionalsQuery
|
|||||||
target_field = field if target_field.blank?
|
target_field = field if target_field.blank?
|
||||||
|
|
||||||
sql = []
|
sql = []
|
||||||
sql << "(#{sql_for_field(field, operator, value, table_name, target_field)})"
|
sql << "(#{sql_for_field field, operator, value, table_name, target_field})"
|
||||||
sql << "#{table_name}.#{target_field} != ''" if operator == '*'
|
sql << "#{table_name}.#{target_field} != ''" if operator == '*'
|
||||||
|
|
||||||
sql.join(' AND ')
|
sql.join ' AND '
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize_ids_filter(options = {})
|
def initialize_ids_filter(label: nil)
|
||||||
if options[:label]
|
if label
|
||||||
add_available_filter 'ids', type: :integer, label: options[:label]
|
add_available_filter 'ids', type: :integer, label: label
|
||||||
else
|
else
|
||||||
add_available_filter 'ids', type: :integer, name: '#'
|
add_available_filter 'ids', type: :integer, name: '#'
|
||||||
end
|
end
|
||||||
@ -82,35 +84,29 @@ module AdditionalsQuery
|
|||||||
values: -> { project_statuses_values }
|
values: -> { project_statuses_values }
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize_project_filter(options = {})
|
def initialize_project_filter(always: false, position: nil)
|
||||||
if project.nil? || options[:always]
|
if project.nil? || always
|
||||||
add_available_filter 'project_id', order: options[:position],
|
add_available_filter 'project_id', order: position,
|
||||||
type: :list,
|
type: :list,
|
||||||
values: -> { project_values }
|
values: -> { project_values }
|
||||||
end
|
end
|
||||||
return if project.nil? || project.leaf? || subproject_values.empty?
|
return if project.nil? || project.leaf? || subproject_values.empty?
|
||||||
|
|
||||||
add_available_filter 'subproject_id', order: options[:position],
|
add_available_filter 'subproject_id', order: position,
|
||||||
type: :list_subprojects,
|
type: :list_subprojects,
|
||||||
values: -> { subproject_values }
|
values: -> { subproject_values }
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize_created_filter(options = {})
|
def initialize_created_filter(position: nil, label: nil)
|
||||||
add_available_filter 'created_on', order: options[:position],
|
add_available_filter 'created_on', order: position,
|
||||||
type: :date_past,
|
type: :date_past,
|
||||||
label: options[:label].presence
|
label: label
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize_updated_filter(options = {})
|
def initialize_updated_filter(position: nil, label: nil)
|
||||||
add_available_filter 'updated_on', order: options[:position],
|
add_available_filter 'updated_on', order: position,
|
||||||
type: :date_past,
|
type: :date_past,
|
||||||
label: options[:label].presence
|
label: label
|
||||||
end
|
|
||||||
|
|
||||||
def initialize_tags_filter(options = {})
|
|
||||||
add_available_filter 'tags', order: options[:position],
|
|
||||||
type: :list_optional,
|
|
||||||
values: -> { tag_values(project) }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize_approved_filter
|
def initialize_approved_filter
|
||||||
@ -123,38 +119,26 @@ module AdditionalsQuery
|
|||||||
label: :field_approved
|
label: :field_approved
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize_author_filter(options = {})
|
def initialize_author_filter(position: nil)
|
||||||
add_available_filter 'author_id', order: options[:position],
|
add_available_filter 'author_id', order: position,
|
||||||
type: :list_optional,
|
type: :list_optional,
|
||||||
values: -> { author_values }
|
values: -> { author_values }
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize_assignee_filter(options = {})
|
def initialize_assignee_filter(position: nil)
|
||||||
add_available_filter 'assigned_to_id', order: options[:position],
|
add_available_filter 'assigned_to_id', order: position,
|
||||||
type: :list_optional,
|
type: :list_optional,
|
||||||
values: -> { assigned_to_all_values }
|
values: -> { assigned_to_all_values }
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize_watcher_filter(options = {})
|
def initialize_watcher_filter(position: nil)
|
||||||
return unless User.current.logged?
|
return unless User.current.logged?
|
||||||
|
|
||||||
add_available_filter 'watcher_id', order: options[:position],
|
add_available_filter 'watcher_id', order: position,
|
||||||
type: :list,
|
type: :list,
|
||||||
values: -> { watcher_values_for_manage_public_queries }
|
values: -> { watcher_values_for_manage_public_queries }
|
||||||
end
|
end
|
||||||
|
|
||||||
def tag_values(project)
|
|
||||||
values = if project
|
|
||||||
queried_class.available_tags project: project.id
|
|
||||||
else
|
|
||||||
queried_class.available_tags
|
|
||||||
end
|
|
||||||
|
|
||||||
return [] if values.blank?
|
|
||||||
|
|
||||||
values.collect { |t| [t.name, t.name] }
|
|
||||||
end
|
|
||||||
|
|
||||||
# issue independend values. Use assigned_to_values from Redmine, if you want it only for issues
|
# issue independend values. Use assigned_to_values from Redmine, if you want it only for issues
|
||||||
def assigned_to_all_values
|
def assigned_to_all_values
|
||||||
assigned_to_values = []
|
assigned_to_values = []
|
||||||
@ -168,7 +152,7 @@ module AdditionalsQuery
|
|||||||
# and with users (not groups)
|
# and with users (not groups)
|
||||||
def watcher_values_for_manage_public_queries
|
def watcher_values_for_manage_public_queries
|
||||||
watcher_values = [["<< #{l :label_me} >>", 'me']]
|
watcher_values = [["<< #{l :label_me} >>", 'me']]
|
||||||
watcher_values += users.collect { |s| [s.name, s.id.to_s] } if User.current.allowed_to?(:manage_public_queries, project, global: true)
|
watcher_values += users.collect { |s| [s.name, s.id.to_s] } if User.current.allowed_to? :manage_public_queries, project, global: true
|
||||||
watcher_values
|
watcher_values
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -181,12 +165,8 @@ module AdditionalsQuery
|
|||||||
" #{sql_for_field field, '=', value, db_table, 'user_id'})"
|
" #{sql_for_field field, '=', value, db_table, 'user_id'})"
|
||||||
end
|
end
|
||||||
|
|
||||||
def sql_for_tags_field(field, _operator, value)
|
|
||||||
AdditionalTags.sql_for_tags_field queried_class, operator_for(field), value
|
|
||||||
end
|
|
||||||
|
|
||||||
def sql_for_is_private_field(_field, operator, value)
|
def sql_for_is_private_field(_field, operator, value)
|
||||||
if bool_operator(operator, value)
|
if bool_operator operator, value
|
||||||
return '' if value.count > 1
|
return '' if value.count > 1
|
||||||
|
|
||||||
"#{queried_table_name}.is_private = #{self.class.connection.quoted_true}"
|
"#{queried_table_name}.is_private = #{self.class.connection.quoted_true}"
|
||||||
@ -215,10 +195,10 @@ module AdditionalsQuery
|
|||||||
raise ::Query::StatementInvalid, e.message
|
raise ::Query::StatementInvalid, e.message
|
||||||
end
|
end
|
||||||
|
|
||||||
def results_scope(options = {})
|
def results_scope(**options)
|
||||||
order_option = [group_by_sort_order, (options[:order] || sort_clause)].flatten!.to_a.reject(&:blank?)
|
order_option = [group_by_sort_order, (options[:order] || sort_clause)].flatten!.to_a.reject(&:blank?)
|
||||||
|
|
||||||
objects_scope(options)
|
objects_scope(**options.except(:order, :limit, :offset))
|
||||||
.order(order_option)
|
.order(order_option)
|
||||||
.joins(joins_for_order_statement(order_option.join(',')))
|
.joins(joins_for_order_statement(order_option.join(',')))
|
||||||
.limit(options[:limit])
|
.limit(options[:limit])
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Dashboard < ActiveRecord::Base
|
class Dashboard < ActiveRecord::Base
|
||||||
include Redmine::I18n
|
include Redmine::I18n
|
||||||
include Redmine::SafeAttributes
|
include Redmine::SafeAttributes
|
||||||
@ -22,10 +24,10 @@ class Dashboard < ActiveRecord::Base
|
|||||||
VISIBILITY_ROLES = 1
|
VISIBILITY_ROLES = 1
|
||||||
VISIBILITY_PUBLIC = 2
|
VISIBILITY_PUBLIC = 2
|
||||||
|
|
||||||
scope :by_project, (->(project_id) { where(project_id: project_id) if project_id.present? })
|
scope :by_project, (->(project_id) { where project_id: project_id if project_id.present? })
|
||||||
scope :sorted, (-> { order("#{Dashboard.table_name}.name") })
|
scope :sorted, (-> { order "#{Dashboard.table_name}.name" })
|
||||||
scope :welcome_only, (-> { where(dashboard_type: DashboardContentWelcome::TYPE_NAME) })
|
scope :welcome_only, (-> { where dashboard_type: DashboardContentWelcome::TYPE_NAME })
|
||||||
scope :project_only, (-> { where(dashboard_type: DashboardContentProject::TYPE_NAME) })
|
scope :project_only, (-> { where dashboard_type: DashboardContentProject::TYPE_NAME })
|
||||||
|
|
||||||
safe_attributes 'name', 'description', 'enable_sidebar',
|
safe_attributes 'name', 'description', 'enable_sidebar',
|
||||||
'always_expose', 'project_id', 'author_id',
|
'always_expose', 'project_id', 'author_id',
|
||||||
@ -47,7 +49,7 @@ class Dashboard < ActiveRecord::Base
|
|||||||
|
|
||||||
safe_attributes 'system_default',
|
safe_attributes 'system_default',
|
||||||
if: (lambda do |dashboard, user|
|
if: (lambda do |dashboard, user|
|
||||||
user.allowed_to?(:set_system_dashboards, dashboard.project, global: true)
|
user.allowed_to? :set_system_dashboards, dashboard.project, global: true
|
||||||
end)
|
end)
|
||||||
|
|
||||||
before_save :dashboard_type_check, :visibility_check, :set_options_hash, :clear_unused_block_settings
|
before_save :dashboard_type_check, :visibility_check, :set_options_hash, :clear_unused_block_settings
|
||||||
@ -73,10 +75,10 @@ class Dashboard < ActiveRecord::Base
|
|||||||
def default(dashboard_type, project = nil, user = User.current)
|
def default(dashboard_type, project = nil, user = User.current)
|
||||||
recently_id = User.current.pref.recently_used_dashboard dashboard_type, project
|
recently_id = User.current.pref.recently_used_dashboard dashboard_type, project
|
||||||
|
|
||||||
scope = where(dashboard_type: dashboard_type)
|
scope = where dashboard_type: dashboard_type
|
||||||
scope = scope.where(project_id: project.id).or(scope.where(project_id: nil)) if project.present?
|
scope = scope.where(project_id: project.id).or(scope.where(project_id: nil)) if project.present?
|
||||||
|
|
||||||
dashboard = scope.visible.find_by(id: recently_id) if recently_id.present?
|
dashboard = scope.visible.find_by id: recently_id if recently_id.present?
|
||||||
|
|
||||||
if dashboard.blank?
|
if dashboard.blank?
|
||||||
scope = scope.where(system_default: true).or(scope.where(author_id: user.id))
|
scope = scope.where(system_default: true).or(scope.where(author_id: user.id))
|
||||||
@ -86,7 +88,7 @@ class Dashboard < ActiveRecord::Base
|
|||||||
Rails.logger.debug 'default cleanup required'
|
Rails.logger.debug 'default cleanup required'
|
||||||
# Remove invalid recently_id
|
# Remove invalid recently_id
|
||||||
if project.present?
|
if project.present?
|
||||||
User.current.pref.recently_used_dashboards[dashboard_type].delete(project.id)
|
User.current.pref.recently_used_dashboards[dashboard_type].delete project.id
|
||||||
else
|
else
|
||||||
User.current.pref.recently_used_dashboards[dashboard_type] = nil
|
User.current.pref.recently_used_dashboards[dashboard_type] = nil
|
||||||
end
|
end
|
||||||
@ -101,7 +103,7 @@ class Dashboard < ActiveRecord::Base
|
|||||||
["#{table}.name"]
|
["#{table}.name"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def visible(user = User.current, options = {})
|
def visible(user = User.current, **options)
|
||||||
scope = left_outer_joins :project
|
scope = left_outer_joins :project
|
||||||
scope = scope.where(projects: { id: nil }).or(scope.where(Project.allowed_to_condition(user, :view_project, options)))
|
scope = scope.where(projects: { id: nil }).or(scope.where(Project.allowed_to_condition(user, :view_project, options)))
|
||||||
|
|
||||||
@ -152,7 +154,7 @@ class Dashboard < ActiveRecord::Base
|
|||||||
super
|
super
|
||||||
else
|
else
|
||||||
h = (self[:options] || {}).dup
|
h = (self[:options] || {}).dup
|
||||||
h.update(attr_name => value)
|
h.update attr_name => value
|
||||||
self[:options] = h
|
self[:options] = h
|
||||||
value
|
value
|
||||||
end
|
end
|
||||||
@ -236,7 +238,7 @@ class Dashboard < ActiveRecord::Base
|
|||||||
return if content.groups.exclude?(group) || blocks.blank?
|
return if content.groups.exclude?(group) || blocks.blank?
|
||||||
|
|
||||||
blocks = blocks.map(&:underscore) & layout.values.flatten
|
blocks = blocks.map(&:underscore) & layout.values.flatten
|
||||||
blocks.each { |block| remove_block(block) }
|
blocks.each { |block| remove_block block }
|
||||||
layout[group] = blocks
|
layout[group] = blocks
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -261,7 +263,7 @@ class Dashboard < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def editable?(usr = User.current)
|
def editable?(usr = User.current)
|
||||||
@editable ||= editable_by?(usr)
|
@editable ||= editable_by? usr
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroyable_by?(usr = User.current)
|
def destroyable_by?(usr = User.current)
|
||||||
@ -274,7 +276,7 @@ class Dashboard < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def destroyable?
|
def destroyable?
|
||||||
@destroyable ||= destroyable_by?(User.current)
|
@destroyable ||= destroyable_by? User.current
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
@ -285,7 +287,7 @@ class Dashboard < ActiveRecord::Base
|
|||||||
def css_classes(user = User.current)
|
def css_classes(user = User.current)
|
||||||
s = ['dashboard']
|
s = ['dashboard']
|
||||||
s << 'created-by-me' if author_id == user.id
|
s << 'created-by-me' if author_id == user.id
|
||||||
s.join(' ')
|
s.join ' '
|
||||||
end
|
end
|
||||||
|
|
||||||
def allowed_target_projects(user = User.current)
|
def allowed_target_projects(user = User.current)
|
||||||
@ -293,7 +295,7 @@ class Dashboard < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
# this is used to get unique cache for blocks
|
# this is used to get unique cache for blocks
|
||||||
def async_params(block, options, settings = {})
|
def async_params(block, options, settings)
|
||||||
if block.blank?
|
if block.blank?
|
||||||
msg = 'block is missing for dashboard_async'
|
msg = 'block is missing for dashboard_async'
|
||||||
Rails.log.error msg
|
Rails.log.error msg
|
||||||
@ -326,7 +328,7 @@ class Dashboard < ActiveRecord::Base
|
|||||||
unique_params += options[:unique_params].reject(&:blank?) if options[:unique_params].present?
|
unique_params += options[:unique_params].reject(&:blank?) if options[:unique_params].present?
|
||||||
|
|
||||||
# Rails.logger.debug "debug async_params for #{block}: unique_params=#{unique_params.inspect}"
|
# Rails.logger.debug "debug async_params for #{block}: unique_params=#{unique_params.inspect}"
|
||||||
config[:unique_key] = Digest::SHA256.hexdigest(unique_params.join('_'))
|
config[:unique_key] = Digest::SHA256.hexdigest unique_params.join('_')
|
||||||
end
|
end
|
||||||
|
|
||||||
# Rails.logger.debug "debug async_params for #{block}: config=#{config.inspect}"
|
# Rails.logger.debug "debug async_params for #{block}: config=#{config.inspect}"
|
||||||
@ -345,7 +347,7 @@ class Dashboard < ActiveRecord::Base
|
|||||||
|
|
||||||
def clear_unused_block_settings
|
def clear_unused_block_settings
|
||||||
blocks = layout.values.flatten
|
blocks = layout.values.flatten
|
||||||
layout_settings.keep_if { |block, _settings| blocks.include?(block) }
|
layout_settings.keep_if { |block, _settings| blocks.include? block }
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_unused_role_relations
|
def remove_unused_role_relations
|
||||||
@ -391,7 +393,7 @@ class Dashboard < ActiveRecord::Base
|
|||||||
.where(dashboard_type: dashboard_type)
|
.where(dashboard_type: dashboard_type)
|
||||||
.where.not(id: id)
|
.where.not(id: id)
|
||||||
|
|
||||||
scope = scope.where(project: project) if dashboard_type == DashboardContentProject::TYPE_NAME
|
scope = scope.where project: project if dashboard_type == DashboardContentProject::TYPE_NAME
|
||||||
|
|
||||||
scope.update_all system_default: false
|
scope.update_all system_default: false
|
||||||
end
|
end
|
||||||
@ -409,22 +411,22 @@ class Dashboard < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def validate_visibility
|
def validate_visibility
|
||||||
errors.add(:visibility, :must_be_for_everyone) if system_default? && visibility != VISIBILITY_PUBLIC
|
errors.add :visibility, :must_be_for_everyone if system_default? && visibility != VISIBILITY_PUBLIC
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_name
|
def validate_name
|
||||||
return if name.blank?
|
return if name.blank?
|
||||||
|
|
||||||
scope = self.class.visible.where(name: name)
|
scope = self.class.visible.where name: name
|
||||||
if dashboard_type == DashboardContentProject::TYPE_NAME
|
if dashboard_type == DashboardContentProject::TYPE_NAME
|
||||||
scope = scope.project_only
|
scope = scope.project_only
|
||||||
scope = scope.where project_id: project_id
|
scope = scope.where project_id: project_id
|
||||||
scope = scope.or(scope.where(project_id: nil)) if project_id.present?
|
scope = scope.or scope.where(project_id: nil) if project_id.present?
|
||||||
else
|
else
|
||||||
scope = scope.welcome_only
|
scope = scope.welcome_only
|
||||||
end
|
end
|
||||||
|
|
||||||
scope = scope.where.not(id: id) unless new_record?
|
scope = scope.where.not id: id unless new_record?
|
||||||
errors.add(:name, :name_not_unique) if scope.count.positive?
|
errors.add :name, :name_not_unique if scope.count.positive?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class DashboardContent
|
class DashboardContent
|
||||||
include Redmine::I18n
|
include Redmine::I18n
|
||||||
|
|
||||||
@ -100,7 +102,7 @@ class DashboardContent
|
|||||||
|
|
||||||
def find_block(block)
|
def find_block(block)
|
||||||
block.to_s =~ /\A(.*?)(__\d+)?\z/
|
block.to_s =~ /\A(.*?)(__\d+)?\z/
|
||||||
name = Regexp.last_match(1)
|
name = Regexp.last_match 1
|
||||||
available_blocks.key?(name) ? available_blocks[name].merge(name: name) : nil
|
available_blocks.key?(name) ? available_blocks[name].merge(name: name) : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class DashboardContentProject < DashboardContent
|
class DashboardContentProject < DashboardContent
|
||||||
TYPE_NAME = 'ProjectDashboard'.freeze
|
TYPE_NAME = 'ProjectDashboard'
|
||||||
|
|
||||||
def block_definitions
|
def block_definitions
|
||||||
blocks = super
|
blocks = super
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class DashboardContentWelcome < DashboardContent
|
class DashboardContentWelcome < DashboardContent
|
||||||
TYPE_NAME = 'WelcomeDashboard'.freeze
|
TYPE_NAME = 'WelcomeDashboard'
|
||||||
|
|
||||||
def block_definitions
|
def block_definitions
|
||||||
blocks = super
|
blocks = super
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class DashboardRole < ActiveRecord::Base
|
class DashboardRole < ActiveRecord::Base
|
||||||
include Redmine::SafeAttributes
|
include Redmine::SafeAttributes
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Deface::Override.new virtual_path: 'admin/info',
|
Deface::Override.new virtual_path: 'admin/info',
|
||||||
name: 'add-system_info',
|
name: 'add-system_info',
|
||||||
insert_after: 'table.list',
|
insert_after: 'table.list',
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
unless Redmine::Plugin.installed? 'redmine_servicedesk'
|
unless Redmine::Plugin.installed? 'redmine_servicedesk'
|
||||||
if defined?(CONTACTS_VERSION_TYPE) && CONTACTS_VERSION_TYPE == 'PRO version'
|
if defined?(CONTACTS_VERSION_TYPE) && CONTACTS_VERSION_TYPE == 'PRO version'
|
||||||
Deface::Override.new virtual_path: 'contacts/_form',
|
Deface::Override.new virtual_path: 'contacts/_form',
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Deface::Override.new virtual_path: 'custom_fields/formats/_text',
|
Deface::Override.new virtual_path: 'custom_fields/formats/_text',
|
||||||
name: 'custom_fields-formats-text',
|
name: 'custom_fields-formats-text',
|
||||||
replace: 'erb[silent]:contains(\'if @custom_field.class.name == "IssueCustomField"\')',
|
replace: 'erb[silent]:contains(\'if @custom_field.class.name == "IssueCustomField"\')',
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Deface::Override.new virtual_path: 'issues/_edit',
|
Deface::Override.new virtual_path: 'issues/_edit',
|
||||||
name: 'edit-issue-permission',
|
name: 'edit-issue-permission',
|
||||||
replace: 'erb[silent]:contains("User.current.allowed_to?(:log_time, @project)")',
|
replace: 'erb[silent]:contains("User.current.allowed_to?(:log_time, @project)")',
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Deface::Override.new virtual_path: 'issues/_list',
|
Deface::Override.new virtual_path: 'issues/_list',
|
||||||
name: 'list-issue-back-url',
|
name: 'list-issue-back-url',
|
||||||
replace: 'erb[loud]:contains("hidden_field_tag \'back_url\'")',
|
replace: 'erb[loud]:contains("hidden_field_tag \'back_url\'")',
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Deface::Override.new virtual_path: 'issues/_action_menu',
|
Deface::Override.new virtual_path: 'issues/_action_menu',
|
||||||
name: 'show-issue-log-time',
|
name: 'show-issue-log-time',
|
||||||
replace: 'erb[loud]:contains("User.current.allowed_to?(:log_time, @project)")',
|
replace: 'erb[loud]:contains("User.current.allowed_to?(:log_time, @project)")',
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Deface::Override.new virtual_path: 'reports/_simple',
|
Deface::Override.new virtual_path: 'reports/_simple',
|
||||||
name: 'report-simple-user-scope',
|
name: 'report-simple-user-scope',
|
||||||
insert_before: 'erb[silent]:contains("rows.empty?")',
|
insert_before: 'erb[silent]:contains("rows.empty?")',
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Deface::Override.new virtual_path: 'roles/_form',
|
Deface::Override.new virtual_path: 'roles/_form',
|
||||||
name: 'roles-form-hide',
|
name: 'roles-form-hide',
|
||||||
insert_before: 'p.manage_members_shown',
|
insert_before: 'p.manage_members_shown',
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
unless Redmine::Plugin.installed? 'redmine_hrm'
|
unless Redmine::Plugin.installed? 'redmine_hrm'
|
||||||
if Redmine::VERSION.to_s >= '4.2'
|
if Redmine::VERSION.to_s >= '4.2'
|
||||||
Deface::Override.new virtual_path: 'users/show',
|
Deface::Override.new virtual_path: 'users/show',
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Deface::Override.new virtual_path: 'wiki/edit',
|
Deface::Override.new virtual_path: 'wiki/edit',
|
||||||
name: 'wiki-edit-bottom',
|
name: 'wiki-edit-bottom',
|
||||||
insert_before: 'fieldset',
|
insert_before: 'fieldset',
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Deface::Override.new virtual_path: 'wiki/show',
|
Deface::Override.new virtual_path: 'wiki/show',
|
||||||
name: 'wiki-show-bottom',
|
name: 'wiki-show-bottom',
|
||||||
insert_before: 'p.wiki-update-info',
|
insert_before: 'p.wiki-update-info',
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
div id="#{export_format}-export-options" style="display: none"
|
div id="#{export_format}-export-options" style="display: none"
|
||||||
h3.title = l(:label_export_options, export_format: export_format.upcase)
|
h3.title = l :label_export_options, export_format: export_format.upcase
|
||||||
|
|
||||||
= form_tag(url, method: :get, id: "#{export_format}-export-form") do
|
= form_tag url, method: :get, id: "#{export_format}-export-form" do
|
||||||
= query_as_hidden_field_tags @query
|
= query_as_hidden_field_tags @query
|
||||||
- if defined?(selected_columns_only) && selected_columns_only
|
- if defined?(selected_columns_only) && selected_columns_only
|
||||||
= hidden_field_tag 'c[]', ''
|
= hidden_field_tag 'c[]', ''
|
||||||
= l(:description_selected_columns)
|
= l :description_selected_columns
|
||||||
- else
|
- else
|
||||||
p
|
p
|
||||||
label
|
label
|
||||||
= radio_button_tag 'c[]', '', true
|
= radio_button_tag 'c[]', '', true
|
||||||
= l(:description_selected_columns)
|
= l :description_selected_columns
|
||||||
br
|
br
|
||||||
label
|
label
|
||||||
= radio_button_tag 'c[]', 'all_inline'
|
= radio_button_tag 'c[]', 'all_inline'
|
||||||
= l(:description_all_columns)
|
= l :description_all_columns
|
||||||
|
|
||||||
hr
|
hr
|
||||||
|
|
||||||
- if @query.available_filters.key?('description')
|
- if @query.available_filters.key? 'description'
|
||||||
p
|
p
|
||||||
label
|
label
|
||||||
= check_box_tag 'c[]', 'description', @query.has_column?(:description)
|
= check_box_tag 'c[]', 'description', @query.has_column?(:description)
|
||||||
= l(:field_description)
|
= l :field_description
|
||||||
- if defined?(with_last_notes) && with_last_notes
|
- if defined?(with_last_notes) && with_last_notes
|
||||||
label
|
label
|
||||||
= check_box_tag 'c[]', 'last_notes', @query.has_column?(:last_notes)
|
= check_box_tag 'c[]', 'last_notes', @query.has_column?(:last_notes)
|
||||||
= l(:label_last_notes)
|
= l :label_last_notes
|
||||||
|
|
||||||
= export_csv_encoding_select_tag
|
= export_csv_encoding_select_tag
|
||||||
|
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
fieldset.box
|
fieldset.box
|
||||||
legend = l(:additionals_query_list_defaults)
|
legend = l :additionals_query_list_defaults
|
||||||
- setting_name_columns = "#{query_type}_list_defaults"
|
- setting_name_columns = "#{query_type}_list_defaults"
|
||||||
- query = query_class.new(@settings[setting_name_columns.to_sym])
|
- query = query_class.new @settings[setting_name_columns.to_sym]
|
||||||
.default-query-settings-label
|
.default-query-settings-label
|
||||||
= render_query_columns_selection(query, name: "settings[#{setting_name_columns}][column_names]")
|
= render_query_columns_selection query, name: "settings[#{setting_name_columns}][column_names]"
|
||||||
|
|
||||||
- columns = query_class.new.available_totalable_columns
|
- columns = query_class.new.available_totalable_columns
|
||||||
- if columns.count.positive?
|
- if columns.count.positive?
|
||||||
fieldset.box
|
fieldset.box
|
||||||
legend = l(:additionals_query_list_default_totals)
|
legend = l :additionals_query_list_default_totals
|
||||||
|
|
||||||
.default-query-settings-totals
|
.default-query-settings-totals
|
||||||
- setting_name_totals = "#{query_type}_list_default_totals"
|
- setting_name_totals = "#{query_type}_list_default_totals"
|
||||||
= hidden_field_tag("settings[#{setting_name_totals}][]", '')
|
= hidden_field_tag "settings[#{setting_name_totals}][]", ''
|
||||||
- columns.each do |s|
|
- columns.each do |s|
|
||||||
label.inline
|
label.inline
|
||||||
- value = @settings[setting_name_totals.to_sym].present? ? @settings[setting_name_totals.to_sym].include?(s.name.to_s) : false
|
- value = @settings[setting_name_totals.to_sym].present? ? @settings[setting_name_totals.to_sym].include?(s.name.to_s) : false
|
||||||
|
@ -1,47 +1,47 @@
|
|||||||
fieldset.settings
|
fieldset.settings
|
||||||
legend = l(:label_content_plural)
|
legend = l :label_content_plural
|
||||||
|
|
||||||
p
|
p
|
||||||
= additionals_settings_textarea :account_login_bottom
|
= additionals_settings_textarea :account_login_bottom
|
||||||
em.info
|
em.info
|
||||||
= l(:account_login_info)
|
= l :account_login_info
|
||||||
p
|
p
|
||||||
= additionals_settings_textarea :global_sidebar
|
= additionals_settings_textarea :global_sidebar
|
||||||
em.info
|
em.info
|
||||||
= l(:global_sidebar_info)
|
= l :global_sidebar_info
|
||||||
p
|
p
|
||||||
= additionals_settings_textarea :global_footer
|
= additionals_settings_textarea :global_footer
|
||||||
em.info
|
em.info
|
||||||
= l(:global_footer_info)
|
= l :global_footer_info
|
||||||
|
|
||||||
fieldset.settings
|
fieldset.settings
|
||||||
legend = l(:label_settings)
|
legend = l :label_settings
|
||||||
|
|
||||||
p
|
p
|
||||||
= additionals_settings_checkbox :open_external_urls
|
= additionals_settings_checkbox :open_external_urls
|
||||||
em.info
|
em.info
|
||||||
= t(:open_external_urls_info)
|
= t :open_external_urls_info
|
||||||
p
|
p
|
||||||
= additionals_settings_checkbox :add_go_to_top
|
= additionals_settings_checkbox :add_go_to_top
|
||||||
em.info
|
em.info
|
||||||
= t(:add_go_to_top_info)
|
= t :add_go_to_top_info
|
||||||
p
|
p
|
||||||
= additionals_settings_checkbox :legacy_smiley_support
|
= additionals_settings_checkbox :legacy_smiley_support
|
||||||
em.info
|
em.info
|
||||||
= t(:legacy_smiley_support_info_html)
|
= t :legacy_smiley_support_info_html
|
||||||
|
|
||||||
fieldset.settings
|
fieldset.settings
|
||||||
legend = l(:label_disabled_modules)
|
legend = l :label_disabled_modules
|
||||||
|
|
||||||
p
|
p
|
||||||
= tag.label l(:label_disabled_modules)
|
= tag.label l(:label_disabled_modules)
|
||||||
= hidden_field_tag('settings[disabled_modules][]', '')
|
= hidden_field_tag 'settings[disabled_modules][]', ''
|
||||||
- Redmine::AccessControl.available_project_modules_all.sort.each do |m|
|
- Redmine::AccessControl.available_project_modules_all.sort.each do |m|
|
||||||
label.block
|
label.block
|
||||||
- value = @settings[:disabled_modules].present? ? @settings[:disabled_modules].include?(m.to_s) : false
|
- value = @settings[:disabled_modules].present? ? @settings[:disabled_modules].include?(m.to_s) : false
|
||||||
= check_box_tag('settings[disabled_modules][]', m, value, id: nil)
|
= check_box_tag 'settings[disabled_modules][]', m, value, id: nil
|
||||||
= l_or_humanize(m, prefix: 'project_module_')
|
= l_or_humanize m, prefix: 'project_module_'
|
||||||
|
|
||||||
br
|
br
|
||||||
em.info
|
em.info
|
||||||
= l(:disabled_modules_info)
|
= l :disabled_modules_info
|
||||||
|
@ -38,7 +38,7 @@ p
|
|||||||
options_for_select(rule_status.collect { |column| [column.name, column.id] },
|
options_for_select(rule_status.collect { |column| [column.name, column.id] },
|
||||||
@settings[:issue_status_y]),
|
@settings[:issue_status_y]),
|
||||||
multiple: false, style: 'width:150px; vertical-align: top'
|
multiple: false, style: 'width:150px; vertical-align: top'
|
||||||
em.info = t(:rule_issue_status_change_info)
|
em.info = t :rule_issue_status_change_info
|
||||||
|
|
||||||
br
|
br
|
||||||
br
|
br
|
||||||
@ -51,7 +51,7 @@ p
|
|||||||
options_for_select(rule_status.collect { |column| [column.name, column.id] },
|
options_for_select(rule_status.collect { |column| [column.name, column.id] },
|
||||||
@settings[:issue_assign_to_x]),
|
@settings[:issue_assign_to_x]),
|
||||||
multiple: true, size: 6, style: 'width:150px'
|
multiple: true, size: 6, style: 'width:150px'
|
||||||
em.info = t(:rule_issue_current_user_status_info_html)
|
em.info = t :rule_issue_current_user_status_info_html
|
||||||
|
|
||||||
br
|
br
|
||||||
br
|
br
|
||||||
@ -77,7 +77,7 @@ br
|
|||||||
p
|
p
|
||||||
= additionals_settings_checkbox :issue_timelog_required
|
= additionals_settings_checkbox :issue_timelog_required
|
||||||
span[style="vertical-align: top; margin-left: 15px;"]
|
span[style="vertical-align: top; margin-left: 15px;"]
|
||||||
= l(:label_tracker_plural)
|
= l :label_tracker_plural
|
||||||
| :
|
| :
|
||||||
= select_tag 'settings[issue_timelog_required_tracker]',
|
= select_tag 'settings[issue_timelog_required_tracker]',
|
||||||
options_for_select(Tracker.all.sorted.collect { |column| [column.name, column.id] },
|
options_for_select(Tracker.all.sorted.collect { |column| [column.name, column.id] },
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
em.info
|
em.info
|
||||||
= l(:hidden_macros_in_toolbar_info)
|
= l :hidden_macros_in_toolbar_info
|
||||||
|
|
||||||
br
|
br
|
||||||
|
|
||||||
p
|
p
|
||||||
= tag.label l(:label_hidden_macros_in_toolbar)
|
= tag.label l(:label_hidden_macros_in_toolbar)
|
||||||
= hidden_field_tag('settings[hidden_macros_in_toolbar][]', '')
|
= hidden_field_tag 'settings[hidden_macros_in_toolbar][]', ''
|
||||||
- @available_macros = AdditionalsMacro.all(only_names: true).each do |m|
|
- @available_macros = AdditionalsMacro.all(only_names: true).each do |m|
|
||||||
label.block
|
label.block
|
||||||
- value = @settings[:hidden_macros_in_toolbar].present? ? @settings[:hidden_macros_in_toolbar].include?(m) : false
|
- value = @settings[:hidden_macros_in_toolbar].present? ? @settings[:hidden_macros_in_toolbar].include?(m) : false
|
||||||
= check_box_tag('settings[hidden_macros_in_toolbar][]', m, value, id: nil)
|
= check_box_tag 'settings[hidden_macros_in_toolbar][]', m, value, id: nil
|
||||||
= m
|
= m
|
||||||
|
|
||||||
br
|
br
|
||||||
|
@ -20,14 +20,14 @@ h3 = l :label_custom_menu_items
|
|||||||
p
|
p
|
||||||
label = h l(:label_permissions)
|
label = h l(:label_permissions)
|
||||||
- permission_field = "custom_menu#{i}_roles"
|
- permission_field = "custom_menu#{i}_roles"
|
||||||
- menu_roles = Struct.new(:id, :name)
|
- menu_roles = Struct.new :id, :name
|
||||||
= select_tag("settings[#{permission_field}]",
|
= select_tag("settings[#{permission_field}]",
|
||||||
options_from_collection_for_select(Role.sorted.collect { |m| menu_roles.new(m.id, m.name) },
|
options_from_collection_for_select(Role.sorted.collect { |m| menu_roles.new m.id, m.name },
|
||||||
:id,
|
:id,
|
||||||
:name,
|
:name,
|
||||||
@settings[permission_field]),
|
@settings[permission_field]),
|
||||||
multiple: true, style: 'height: 100px;')
|
multiple: true, style: 'height: 100px;')
|
||||||
em.info = l(:menu_roles_info)
|
em.info = l :menu_roles_info
|
||||||
|
|
||||||
br
|
br
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
p
|
p
|
||||||
= additionals_settings_textfield :google_maps_api_key, size: 60
|
= additionals_settings_textfield :google_maps_api_key, size: 60
|
||||||
em.info = t(:google_maps_embed_api_html)
|
em.info = t :google_maps_embed_api_html
|
||||||
|
|
||||||
= call_hook :additionals_settings_web_apis, settings: @settings
|
= call_hook :additionals_settings_web_apis, settings: @settings
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
em.info = t(:top_wiki_help)
|
em.info = t :top_wiki_help
|
||||||
|
|
||||||
br
|
br
|
||||||
|
|
||||||
fieldset.settings
|
fieldset.settings
|
||||||
legend = l(:label_content_plural)
|
legend = l :label_content_plural
|
||||||
|
|
||||||
p
|
p
|
||||||
= additionals_settings_textarea :global_wiki_sidebar
|
= additionals_settings_textarea :global_wiki_sidebar
|
||||||
em.info
|
em.info
|
||||||
= l(:global_wiki_sidebar_info)
|
= l :global_wiki_sidebar_info
|
||||||
|
|
||||||
fieldset.settings
|
fieldset.settings
|
||||||
legend = l(:label_pdf_wiki_settings)
|
legend = l :label_pdf_wiki_settings
|
||||||
|
|
||||||
p
|
p
|
||||||
= additionals_settings_checkbox :wiki_pdf_remove_title
|
= additionals_settings_checkbox :wiki_pdf_remove_title
|
||||||
em.info
|
em.info
|
||||||
= l(:wiki_pdf_remove_title_info)
|
= l :wiki_pdf_remove_title_info
|
||||||
p
|
p
|
||||||
= additionals_settings_checkbox :wiki_pdf_remove_attachments
|
= additionals_settings_checkbox :wiki_pdf_remove_attachments
|
||||||
em.info
|
em.info
|
||||||
= l(:wiki_pdf_remove_attachments_info)
|
= l :wiki_pdf_remove_attachments_info
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
= call_hook :view_dashboard_top, dashboard: dashboard, project: @project
|
= call_hook :view_dashboard_top, dashboard: dashboard, project: @project
|
||||||
|
|
||||||
#my-page.splitcontent class="#{dashboard_css_classes(dashboard)}"
|
#my-page.splitcontent class="#{dashboard_css_classes dashboard}"
|
||||||
- dashboard.available_groups.each do |group|
|
- dashboard.available_groups.each do |group|
|
||||||
.block-receiver id="list-#{group}" class="splitcontent#{group}"
|
.block-receiver id="list-#{group}" class="splitcontent#{group}"
|
||||||
= render_dashboard_blocks dashboard.layout[group], dashboard
|
= render_dashboard_blocks dashboard.layout[group], dashboard
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
{},
|
{},
|
||||||
disabled: !@dashboard.project_id_can_change?
|
disabled: !@dashboard.project_id_can_change?
|
||||||
em.info
|
em.info
|
||||||
= l(:info_dashboard_project_select)
|
= l :info_dashboard_project_select
|
||||||
- else
|
- else
|
||||||
= hidden_field_tag 'dashboard[project_id]', @project&.id
|
= hidden_field_tag 'dashboard[project_id]', @project&.id
|
||||||
|
|
||||||
@ -27,19 +27,19 @@
|
|||||||
User.current.allowed_to?(:set_system_dashboards, @project, global: true)
|
User.current.allowed_to?(:set_system_dashboards, @project, global: true)
|
||||||
|
|
||||||
p
|
p
|
||||||
label = l(:field_visible)
|
label = l :field_visible
|
||||||
label.block
|
label.block
|
||||||
= radio_button 'dashboard', 'visibility', Dashboard::VISIBILITY_PRIVATE
|
= radio_button 'dashboard', 'visibility', Dashboard::VISIBILITY_PRIVATE
|
||||||
'
|
'
|
||||||
= l(:label_visibility_private)
|
= l :label_visibility_private
|
||||||
label.block
|
label.block
|
||||||
= radio_button 'dashboard', 'visibility', Dashboard::VISIBILITY_PUBLIC
|
= radio_button 'dashboard', 'visibility', Dashboard::VISIBILITY_PUBLIC
|
||||||
'
|
'
|
||||||
= l(:label_visibility_public)
|
= l :label_visibility_public
|
||||||
label.block
|
label.block
|
||||||
= radio_button 'dashboard', 'visibility', Dashboard::VISIBILITY_ROLES
|
= radio_button 'dashboard', 'visibility', Dashboard::VISIBILITY_ROLES
|
||||||
'
|
'
|
||||||
= l(:label_visibility_roles)
|
= l :label_visibility_roles
|
||||||
' :
|
' :
|
||||||
- Role.givable.sorted.each do |role|
|
- Role.givable.sorted.each do |role|
|
||||||
label.block.role-visibility
|
label.block.role-visibility
|
||||||
|
@ -11,7 +11,7 @@ h3 = block_definition[:label]
|
|||||||
= l :field_homepage
|
= l :field_homepage
|
||||||
' :
|
' :
|
||||||
= link_to_if uri_with_safe_scheme?(@project.homepage), @project.homepage, @project.homepage, class: 'external'
|
= link_to_if uri_with_safe_scheme?(@project.homepage), @project.homepage, @project.homepage, class: 'external'
|
||||||
- render_custom_field_values(@project) do |custom_field, formatted|
|
- render_custom_field_values @project do |custom_field, formatted|
|
||||||
li class="#{custom_field.css_classes}"
|
li class="#{custom_field.css_classes}"
|
||||||
span.label
|
span.label
|
||||||
= custom_field.name
|
= custom_field.name
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
- dashboard_async_cache dashboard, block, async, settings do
|
- dashboard_async_cache dashboard, block, async, settings do
|
||||||
|
|
||||||
- query = klass.visible.find_by(id: settings[:query_id])
|
- query = klass.visible.find_by id: settings[:query_id]
|
||||||
- if query
|
- if query
|
||||||
ruby:
|
ruby:
|
||||||
query.project = @project if query_block[:with_project]
|
query.project = @project if query_block[:with_project]
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
h2 = l(:button_dashboard_edit)
|
h2 = l :button_dashboard_edit
|
||||||
= labelled_form_for :dashboard,
|
= labelled_form_for :dashboard,
|
||||||
@dashboard,
|
@dashboard,
|
||||||
html: { multipart: true, id: 'dashboard-form' } do |f|
|
html: { multipart: true, id: 'dashboard-form' } do |f|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
h2 = l(:label_new_additional_dashboard)
|
h2 = l :label_new_additional_dashboard
|
||||||
= labelled_form_for :dashboard,
|
= labelled_form_for :dashboard,
|
||||||
@dashboard,
|
@dashboard,
|
||||||
url: { action: 'create', project_id: @project },
|
url: { action: 'create', project_id: @project },
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
- if show_issue_change_author?(issue) && issue.safe_attribute?('author_id')
|
- if show_issue_change_author?(issue) && issue.safe_attribute?('author_id')
|
||||||
- author_options = author_options_for_select(issue.project, issue)
|
- author_options = author_options_for_select issue.project, issue
|
||||||
- if author_options.present?
|
- if author_options.present?
|
||||||
p#change_author
|
p#change_author
|
||||||
= form.label_for_field :author_id
|
= form.label_for_field :author_id
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
- if @project && User.current.allowed_to?(:edit_issue_author, @project)
|
- if @project && User.current.allowed_to?(:edit_issue_author, @project)
|
||||||
- author_options = author_options_for_select(@project)
|
- author_options = author_options_for_select @project
|
||||||
- if author_options.present?
|
- if author_options.present?
|
||||||
p#change_author
|
p#change_author
|
||||||
= label_tag('issue[author_id]', l(:field_author))
|
= label_tag 'issue[author_id]', l(:field_author)
|
||||||
= select_tag('issue[author_id]',
|
= select_tag 'issue[author_id]',
|
||||||
tag.option(l(:label_no_change_option), value: '') + author_options)
|
tag.option(l(:label_no_change_option), value: '') + author_options
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
= actions_dropdown do
|
= actions_dropdown do
|
||||||
- if User.current.allowed_to? :add_subprojects, @project
|
- if User.current.allowed_to? :add_subprojects, @project
|
||||||
= link_to l(:label_subproject_new), new_project_path(parent_id: @project), class: 'icon icon-add'
|
= link_to l(:label_subproject_new), new_project_path(parent_id: @project), class: 'icon icon-add'
|
||||||
- if User.current.allowed_to?(:close_project, @project)
|
- if User.current.allowed_to? :close_project, @project
|
||||||
- if @project.active?
|
- if @project.active?
|
||||||
= link_to l(:button_close),
|
= link_to l(:button_close),
|
||||||
close_project_path(@project),
|
close_project_path(@project),
|
||||||
@ -46,14 +46,13 @@
|
|||||||
class: 'icon icon-add new-additionals-dashboard'
|
class: 'icon icon-add new-additionals-dashboard'
|
||||||
|
|
||||||
- if @dashboard&.destroyable?
|
- if @dashboard&.destroyable?
|
||||||
= delete_dashboard_link project_dashboard_path(@project, @dashboard),
|
= delete_dashboard_link project_dashboard_path(@project, @dashboard)
|
||||||
class: 'icon icon-del'
|
|
||||||
|
|
||||||
= sidebar_action_toggle @dashboard_sidebar, @dashboard, @project
|
= sidebar_action_toggle @dashboard_sidebar, @dashboard, @project
|
||||||
= render_dashboard_actionlist @dashboard, @project unless @dashboard_sidebar
|
= render_dashboard_actionlist @dashboard, @project unless @dashboard_sidebar
|
||||||
= call_hook :view_project_actions_dropdown, project: @project
|
= call_hook :view_project_actions_dropdown, project: @project
|
||||||
|
|
||||||
- if User.current.allowed_to?(:edit_project, @project)
|
- if User.current.allowed_to? :edit_project, @project
|
||||||
= link_to_if_authorized l(:label_settings),
|
= link_to_if_authorized l(:label_settings),
|
||||||
{ controller: 'projects', action: 'settings', id: @project },
|
{ controller: 'projects', action: 'settings', id: @project },
|
||||||
class: 'icon icon-settings'
|
class: 'icon icon-settings'
|
||||||
@ -63,7 +62,7 @@ h2 = project_overview_name @project, @dashboard
|
|||||||
- unless @project.active?
|
- unless @project.active?
|
||||||
p.warning
|
p.warning
|
||||||
span.icon.icon-lock
|
span.icon.icon-lock
|
||||||
= l(:text_project_closed)
|
= l :text_project_closed
|
||||||
|
|
||||||
= render partial: 'common/dashboard', locals: { dashboard: @dashboard }
|
= render partial: 'common/dashboard', locals: { dashboard: @dashboard }
|
||||||
|
|
||||||
|
@ -9,5 +9,5 @@ tr.group.open
|
|||||||
span.badge.badge-count.count = group_count
|
span.badge.badge-count.count = group_count
|
||||||
'
|
'
|
||||||
span.totals = group_totals
|
span.totals = group_totals
|
||||||
= link_to_function("#{l :button_collapse_all}/#{l :button_expand_all}",
|
= link_to_function "#{l :button_collapse_all}/#{l :button_expand_all}",
|
||||||
'toggleAllRowGroups(this)', class: 'toggle-all')
|
'toggleAllRowGroups(this)', class: 'toggle-all'
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
p
|
p
|
||||||
= f.check_box :hide, disabled: @role.users_visibility != 'members_of_visible_projects'
|
= f.check_box :hide, disabled: @role.users_visibility != 'members_of_visible_projects'
|
||||||
em.info
|
em.info
|
||||||
= t(:info_hidden_roles_html)
|
= t :info_hidden_roles_html
|
||||||
|
|
||||||
javascript:
|
javascript:
|
||||||
$(function() {
|
$(function() {
|
||||||
|
@ -18,8 +18,7 @@
|
|||||||
new_dashboard_path,
|
new_dashboard_path,
|
||||||
class: 'icon icon-add new-additionals-dashboard'
|
class: 'icon icon-add new-additionals-dashboard'
|
||||||
- if @dashboard&.destroyable?
|
- if @dashboard&.destroyable?
|
||||||
= delete_dashboard_link dashboard_path(@dashboard),
|
= delete_dashboard_link dashboard_path(@dashboard)
|
||||||
class: 'icon icon-del'
|
|
||||||
= sidebar_action_toggle @dashboard_sidebar, @dashboard
|
= sidebar_action_toggle @dashboard_sidebar, @dashboard
|
||||||
= render_dashboard_actionlist @dashboard unless @dashboard_sidebar
|
= render_dashboard_actionlist @dashboard unless @dashboard_sidebar
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
h3 = list_title
|
h3 = list_title
|
||||||
|
|
||||||
table.list.projects
|
table.list.projects
|
||||||
- project_tree(@projects, init_level: false) do |project, level|
|
- project_tree @projects, init_level: false do |project, level|
|
||||||
tr id="project-#{project.id}" class="#{project_list_css_classes project, level}"
|
tr id="project-#{project.id}" class="#{project_list_css_classes project, level}"
|
||||||
td.name
|
td.name
|
||||||
span[style='font-weight: bold;']
|
span[style='font-weight: bold;']
|
||||||
@ -13,7 +13,7 @@
|
|||||||
= link_to_project project
|
= link_to_project project
|
||||||
- if project.homepage?
|
- if project.homepage?
|
||||||
' :
|
' :
|
||||||
= link_to(project.homepage, project.homepage, @html_options)
|
= link_to project.homepage, project.homepage, @html_options
|
||||||
- if with_create_issue && User.current.allowed_to?(:add_issues, project)
|
- if with_create_issue && User.current.allowed_to?(:add_issues, project)
|
||||||
= link_to '',
|
= link_to '',
|
||||||
new_project_issue_path(project_id: project),
|
new_project_issue_path(project_id: project),
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
- users.each do |user|
|
- users.each do |user|
|
||||||
.user.box class="#{cycle 'odd', 'even'}"
|
.user.box class="#{cycle 'odd', 'even'}"
|
||||||
div[style="float: left; display: block; margin-right: 5px;"]
|
div[style="float: left; display: block; margin-right: 5px;"]
|
||||||
= avatar(user, size: 50)
|
= avatar user, size: 50
|
||||||
.user.line[style="font-weight: bold;"]
|
.user.line[style="font-weight: bold;"]
|
||||||
= link_to_user user
|
= link_to_user user
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Rails.application.routes.draw do
|
Rails.application.routes.draw do
|
||||||
resources :issues, only: [] do
|
resources :issues, only: [] do
|
||||||
resource 'assign_to_me', only: %i[update], controller: 'additionals_assign_to_me'
|
resource 'assign_to_me', only: %i[update], controller: 'additionals_assign_to_me'
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# see https://github.com/nagix/chartjs-plugin-colorschemes
|
# see https://github.com/nagix/chartjs-plugin-colorschemes
|
||||||
# see https://nagix.github.io/chartjs-plugin-colorschemes/colorchart.html
|
# see https://nagix.github.io/chartjs-plugin-colorschemes/colorchart.html
|
||||||
#
|
#
|
||||||
@ -16,8 +18,8 @@ colorschemes_files = [{ name: 'brewer', src: "#{working_path}/src/colorschemes/c
|
|||||||
FileUtils.rm_rf working_path
|
FileUtils.rm_rf working_path
|
||||||
system "git clone https://github.com/nagix/chartjs-plugin-colorschemes.git #{working_path}"
|
system "git clone https://github.com/nagix/chartjs-plugin-colorschemes.git #{working_path}"
|
||||||
|
|
||||||
File.open(target_file, 'w') do |file|
|
File.open target_file, 'w' do |file|
|
||||||
file.write("---\n")
|
file.write "---\n"
|
||||||
colorschemes_files.each do |color_scheme_file|
|
colorschemes_files.each do |color_scheme_file|
|
||||||
file.write "#{color_scheme_file[:name].capitalize}:\n"
|
file.write "#{color_scheme_file[:name].capitalize}:\n"
|
||||||
File.readlines(color_scheme_file[:src]).each do |line|
|
File.readlines(color_scheme_file[:src]).each do |line|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AddAutowatchInvolvedIssueToUser < ActiveRecord::Migration[4.2]
|
class AddAutowatchInvolvedIssueToUser < ActiveRecord::Migration[4.2]
|
||||||
def change
|
def change
|
||||||
add_column :user_preferences, :autowatch_involved_issue, :boolean, default: true, null: false
|
add_column :user_preferences, :autowatch_involved_issue, :boolean, default: true, null: false
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AddHideToRoles < ActiveRecord::Migration[4.2]
|
class AddHideToRoles < ActiveRecord::Migration[4.2]
|
||||||
def change
|
def change
|
||||||
add_column :roles, :hide, :boolean, default: false, null: false
|
add_column :roles, :hide, :boolean, default: false, null: false
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class CreateDashboards < ActiveRecord::Migration[5.2]
|
class CreateDashboards < ActiveRecord::Migration[5.2]
|
||||||
def change
|
def change
|
||||||
create_table :dashboards do |t|
|
create_table :dashboards do |t|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class CreateDashboardRoles < ActiveRecord::Migration[5.2]
|
class CreateDashboardRoles < ActiveRecord::Migration[5.2]
|
||||||
def change
|
def change
|
||||||
create_table :dashboard_roles do |t|
|
create_table :dashboard_roles do |t|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class CreateDashboardDefaults < ActiveRecord::Migration[5.2]
|
class CreateDashboardDefaults < ActiveRecord::Migration[5.2]
|
||||||
def up
|
def up
|
||||||
User.current = User.find_by(id: ENV['DEFAULT_USER_ID'].presence || User.admin.active.first.id)
|
User.current = User.find_by(id: ENV['DEFAULT_USER_ID'].presence || User.admin.active.first.id)
|
||||||
|
|
||||||
unless Dashboard.exists?(dashboard_type: DashboardContentWelcome::TYPE_NAME)
|
unless Dashboard.exists? dashboard_type: DashboardContentWelcome::TYPE_NAME
|
||||||
Dashboard.create! name: 'Welcome dashboard',
|
Dashboard.create! name: 'Welcome dashboard',
|
||||||
dashboard_type: DashboardContentWelcome::TYPE_NAME,
|
dashboard_type: DashboardContentWelcome::TYPE_NAME,
|
||||||
system_default: true,
|
system_default: true,
|
||||||
@ -10,7 +12,7 @@ class CreateDashboardDefaults < ActiveRecord::Migration[5.2]
|
|||||||
visibility: 2
|
visibility: 2
|
||||||
end
|
end
|
||||||
|
|
||||||
return if Dashboard.exists?(dashboard_type: DashboardContentProject::TYPE_NAME)
|
return if Dashboard.exists? dashboard_type: DashboardContentProject::TYPE_NAME
|
||||||
|
|
||||||
Dashboard.create! name: 'Project dashboard',
|
Dashboard.create! name: 'Project dashboard',
|
||||||
dashboard_type: DashboardContentProject::TYPE_NAME,
|
dashboard_type: DashboardContentProject::TYPE_NAME,
|
||||||
|
@ -24,13 +24,13 @@ master_doc = 'index'
|
|||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u'additionals'
|
project = u'additionals'
|
||||||
copyright = u'2013-2020, AlphaNodes GmbH'
|
copyright = u'2013-2021, AlphaNodes GmbH'
|
||||||
author = u'Alexander Meindl'
|
author = u'Alexander Meindl'
|
||||||
|
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = u'3.0.0'
|
version = u'3.0.3'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = u'3.0.0'
|
release = u'3.0.3'
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
# List of patterns, relative to source directory, that match files and
|
||||||
# directories to ignore when looking for source files.
|
# directories to ignore when looking for source files.
|
||||||
|
6
init.rb
6
init.rb
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Redmine::Plugin.register :additionals do
|
Redmine::Plugin.register :additionals do
|
||||||
name 'Additionals'
|
name 'Additionals'
|
||||||
author 'AlphaNodes GmbH'
|
author 'AlphaNodes GmbH'
|
||||||
@ -14,7 +16,7 @@ Redmine::Plugin.register :additionals do
|
|||||||
default_settings["custom_menu#{i}_title"] = ''
|
default_settings["custom_menu#{i}_title"] = ''
|
||||||
end
|
end
|
||||||
|
|
||||||
settings(default: default_settings, partial: 'additionals/settings/additionals')
|
settings default: default_settings, partial: 'additionals/settings/additionals'
|
||||||
|
|
||||||
permission :show_hidden_roles_in_memberbox, {}
|
permission :show_hidden_roles_in_memberbox, {}
|
||||||
permission :set_system_dashboards,
|
permission :set_system_dashboards,
|
||||||
@ -56,7 +58,7 @@ end
|
|||||||
|
|
||||||
Rails.application.paths['app/overrides'] ||= []
|
Rails.application.paths['app/overrides'] ||= []
|
||||||
Dir.glob(Rails.root.join('plugins/*/app/overrides')).each do |dir|
|
Dir.glob(Rails.root.join('plugins/*/app/overrides')).each do |dir|
|
||||||
Rails.application.paths['app/overrides'] << dir unless Rails.application.paths['app/overrides'].include?(dir)
|
Rails.application.paths['app/overrides'] << dir unless Rails.application.paths['app/overrides'].include? dir
|
||||||
end
|
end
|
||||||
|
|
||||||
Rails.configuration.to_prepare do
|
Rails.configuration.to_prepare do
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'additionals/version'
|
require 'additionals/version'
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
MAX_CUSTOM_MENU_ITEMS = 5
|
MAX_CUSTOM_MENU_ITEMS = 5
|
||||||
SELECT2_INIT_ENTRIES = 20
|
SELECT2_INIT_ENTRIES = 20
|
||||||
DEFAULT_MODAL_WIDTH = '350px'.freeze
|
DEFAULT_MODAL_WIDTH = '350px'
|
||||||
GOTO_LIST = " \xc2\xbb".freeze
|
GOTO_LIST = " \xc2\xbb"
|
||||||
LIST_SEPARATOR = "#{GOTO_LIST} ".freeze
|
LIST_SEPARATOR = "#{GOTO_LIST} "
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def setup
|
def setup
|
||||||
@ -27,6 +29,7 @@ module Additionals
|
|||||||
ReportsController
|
ReportsController
|
||||||
Principal
|
Principal
|
||||||
QueryFilter
|
QueryFilter
|
||||||
|
QueriesHelper
|
||||||
Role
|
Role
|
||||||
User
|
User
|
||||||
UserPreference]
|
UserPreference]
|
||||||
@ -95,7 +98,8 @@ module Additionals
|
|||||||
def debug(message)
|
def debug(message)
|
||||||
return if Rails.env.production?
|
return if Rails.env.production?
|
||||||
|
|
||||||
Rails.logger.debug "#{Time.current.strftime('%H:%M:%S')} DEBUG [#{caller_locations(1..1).first.label}]: #{message}"
|
msg = message.is_a?(String) ? message : message.inspect
|
||||||
|
Rails.logger.debug "#{Time.current.strftime '%H:%M:%S'} DEBUG [#{caller_locations(1..1).first.label}]: #{msg}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def class_prefix(klass)
|
def class_prefix(klass)
|
||||||
@ -113,19 +117,19 @@ module Additionals
|
|||||||
|
|
||||||
def incompatible_plugins(plugins = [], title = 'additionals')
|
def incompatible_plugins(plugins = [], title = 'additionals')
|
||||||
plugins.each do |plugin|
|
plugins.each do |plugin|
|
||||||
raise "\n\033[31m#{title} plugin cannot be used with #{plugin} plugin.\033[0m" if Redmine::Plugin.installed?(plugin)
|
raise "\n\033[31m#{title} plugin cannot be used with #{plugin} plugin.\033[0m" if Redmine::Plugin.installed? plugin
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def patch(patches = [], plugin_id = 'additionals')
|
def patch(patches = [], plugin_id = 'additionals')
|
||||||
patches.each do |name|
|
patches.each do |name|
|
||||||
patch_dir = Rails.root.join("plugins/#{plugin_id}/lib/#{plugin_id}/patches")
|
patch_dir = Rails.root.join "plugins/#{plugin_id}/lib/#{plugin_id}/patches"
|
||||||
require "#{patch_dir}/#{name.underscore}_patch"
|
require "#{patch_dir}/#{name.underscore}_patch"
|
||||||
|
|
||||||
target = name.constantize
|
target = name.constantize
|
||||||
patch = "#{plugin_id.camelize}::Patches::#{name}Patch".constantize
|
patch = "#{plugin_id.camelize}::Patches::#{name}Patch".constantize
|
||||||
|
|
||||||
target.include(patch) unless target.included_modules.include?(patch)
|
target.include patch unless target.included_modules.include? patch
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
module EntityMethods
|
module EntityMethods
|
||||||
def assignable_users(prj = nil)
|
def assignable_users(prj = nil)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
# Formater
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
module Formatter
|
module Formatter
|
||||||
SMILEYS = { 'smiley' => ':-?\)', # :)
|
SMILEYS = { 'smiley' => ':-?\)', # :)
|
||||||
@ -27,16 +28,16 @@ module Additionals
|
|||||||
def render_inline_smileys(text)
|
def render_inline_smileys(text)
|
||||||
return text if text.blank?
|
return text if text.blank?
|
||||||
|
|
||||||
inline_smileys(text)
|
inline_smileys text
|
||||||
text
|
text
|
||||||
end
|
end
|
||||||
|
|
||||||
def inline_smileys(text)
|
def inline_smileys(text)
|
||||||
SMILEYS.each do |name, regexp|
|
SMILEYS.each do |name, regexp|
|
||||||
text.gsub!(/(\s|^|>|\))(!)?(#{regexp})(?=\W|$|<)/m) do
|
text.gsub!(/(\s|^|>|\))(!)?(#{regexp})(?=\W|$|<)/m) do
|
||||||
leading = Regexp.last_match(1)
|
leading = Regexp.last_match 1
|
||||||
esc = Regexp.last_match(2)
|
esc = Regexp.last_match 2
|
||||||
smiley = Regexp.last_match(3)
|
smiley = Regexp.last_match 3
|
||||||
if esc.nil?
|
if esc.nil?
|
||||||
leading + tag.span(class: "additionals smiley smiley-#{name}",
|
leading + tag.span(class: "additionals smiley smiley-#{name}",
|
||||||
title: smiley)
|
title: smiley)
|
||||||
@ -49,8 +50,8 @@ module Additionals
|
|||||||
|
|
||||||
def inline_emojify(text)
|
def inline_emojify(text)
|
||||||
text.gsub!(/:([\w+-]+):/) do |match|
|
text.gsub!(/:([\w+-]+):/) do |match|
|
||||||
emoji_code = Regexp.last_match(1)
|
emoji_code = Regexp.last_match 1
|
||||||
emoji = Emoji.find_by_alias(emoji_code) # rubocop:disable Rails/DynamicFindBy
|
emoji = Emoji.find_by_alias emoji_code # rubocop:disable Rails/DynamicFindBy
|
||||||
if emoji.present?
|
if emoji.present?
|
||||||
tag.img src: inline_emojify_image_path(emoji.image_filename),
|
tag.img src: inline_emojify_image_path(emoji.image_filename),
|
||||||
title: ":#{emoji_code}:",
|
title: ":#{emoji_code}:",
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
class Gemify
|
class Gemify
|
||||||
class << self
|
class << self
|
||||||
@ -10,11 +12,11 @@ module Additionals
|
|||||||
return unless File.directory? source
|
return unless File.directory? source
|
||||||
|
|
||||||
source_files = Dir["#{source}/**/*"]
|
source_files = Dir["#{source}/**/*"]
|
||||||
source_dirs = source_files.select { |d| File.directory?(d) }
|
source_dirs = source_files.select { |d| File.directory? d }
|
||||||
source_files -= source_dirs
|
source_files -= source_dirs
|
||||||
|
|
||||||
unless source_files.empty?
|
unless source_files.empty?
|
||||||
base_target_dir = File.join(destination, File.dirname(source_files.first).gsub(source, ''))
|
base_target_dir = File.join destination, File.dirname(source_files.first).gsub(source, '')
|
||||||
begin
|
begin
|
||||||
FileUtils.mkdir_p base_target_dir
|
FileUtils.mkdir_p base_target_dir
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
@ -23,9 +25,9 @@ module Additionals
|
|||||||
end
|
end
|
||||||
|
|
||||||
source_dirs.each do |dir|
|
source_dirs.each do |dir|
|
||||||
target_dir = File.join(destination, dir.gsub(source, ''))
|
target_dir = File.join destination, dir.gsub(source, '')
|
||||||
begin
|
begin
|
||||||
FileUtils.mkdir_p(target_dir)
|
FileUtils.mkdir_p target_dir
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
raise "Could not create directory #{target_dir}: " + e.message
|
raise "Could not create directory #{target_dir}: " + e.message
|
||||||
end
|
end
|
||||||
@ -33,7 +35,7 @@ module Additionals
|
|||||||
|
|
||||||
source_files.each do |file|
|
source_files.each do |file|
|
||||||
target = File.join destination, file.gsub(source, '')
|
target = File.join destination, file.gsub(source, '')
|
||||||
FileUtils.cp(file, target) unless File.exist?(target) && FileUtils.identical?(file, target)
|
FileUtils.cp file, target unless File.exist?(target) && FileUtils.identical?(file, target)
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
raise "Could not copy #{file} to #{target}: " + e.message
|
raise "Could not copy #{file} to #{target}: " + e.message
|
||||||
end
|
end
|
||||||
@ -42,12 +44,12 @@ module Additionals
|
|||||||
# Create text file to Redmine's plugins directory.
|
# Create text file to Redmine's plugins directory.
|
||||||
# The purpose is telling plugins directory to users.
|
# The purpose is telling plugins directory to users.
|
||||||
def create_plugin_hint(plugin_id = 'additionals')
|
def create_plugin_hint(plugin_id = 'additionals')
|
||||||
plugins_dir = File.join(Bundler.root, 'plugins')
|
plugins_dir = File.join Bundler.root, 'plugins'
|
||||||
path = File.join plugins_dir, plugin_id
|
path = File.join plugins_dir, plugin_id
|
||||||
return if File.exist? path
|
return if File.exist? path
|
||||||
|
|
||||||
File.open(path, 'w') do |f|
|
File.open path, 'w' do |f|
|
||||||
f.write(<<PLUGIN_HINT)
|
f.write <<PLUGIN_HINT
|
||||||
This plugin was installed as gem wrote to Gemfile.local instead of putting Redmine's plugin directory.
|
This plugin was installed as gem wrote to Gemfile.local instead of putting Redmine's plugin directory.
|
||||||
See #{plugin_id} gem installed directory.
|
See #{plugin_id} gem installed directory.
|
||||||
PLUGIN_HINT
|
PLUGIN_HINT
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
module Helpers
|
module Helpers
|
||||||
def live_search_title_info(entity)
|
def live_search_title_info(entity)
|
||||||
@ -6,7 +8,7 @@ module Additionals
|
|||||||
l :label_live_search_hints, value: all_fields
|
l :label_live_search_hints, value: all_fields
|
||||||
end
|
end
|
||||||
|
|
||||||
def link_to_external(name, link, options = {})
|
def link_to_external(name, link, **options)
|
||||||
options[:class] ||= 'external'
|
options[:class] ||= 'external'
|
||||||
options[:class] = "#{options[:class]} external" if options[:class].exclude? 'external'
|
options[:class] = "#{options[:class]} external" if options[:class].exclude? 'external'
|
||||||
|
|
||||||
@ -16,17 +18,17 @@ module Additionals
|
|||||||
link_to name, link, options
|
link_to name, link, options
|
||||||
end
|
end
|
||||||
|
|
||||||
def additionals_list_title(options)
|
def additionals_list_title(name: nil, issue: nil, user: nil, query: nil)
|
||||||
title = []
|
title = []
|
||||||
if options[:issue]
|
if issue
|
||||||
title << link_to(h("#{options[:issue].subject} ##{options[:issue].id}"),
|
title << link_to(h("#{issue.subject} ##{issue.id}"),
|
||||||
issue_path(options[:issue]),
|
issue_path(issue),
|
||||||
class: options[:issue].css_classes)
|
class: issue.css_classes)
|
||||||
elsif options[:user]
|
elsif user
|
||||||
title << safe_join([avatar(options[:user], size: 50), options[:user].name], ' ')
|
title << safe_join([avatar(user, size: 50), user.name], ' ')
|
||||||
end
|
end
|
||||||
title << options[:name] if options[:name]
|
title << name if name
|
||||||
title << h(options[:query].name) if options[:query] && !options[:query].new_record?
|
title << h(query.name) if query && !query.new_record?
|
||||||
safe_join title, Additionals::LIST_SEPARATOR
|
safe_join title, Additionals::LIST_SEPARATOR
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -53,7 +55,7 @@ module Additionals
|
|||||||
|
|
||||||
def render_issue_macro_link(issue, text, comment_id = nil)
|
def render_issue_macro_link(issue, text, comment_id = nil)
|
||||||
only_path = controller_path.split('_').last != 'mailer'
|
only_path = controller_path.split('_').last != 'mailer'
|
||||||
content = link_to(text, issue_url(issue, only_path: only_path), class: issue.css_classes)
|
content = link_to text, issue_url(issue, only_path: only_path), class: issue.css_classes
|
||||||
if comment_id.nil?
|
if comment_id.nil?
|
||||||
content
|
content
|
||||||
else
|
else
|
||||||
@ -76,7 +78,7 @@ module Additionals
|
|||||||
comment = 'N/A'
|
comment = 'N/A'
|
||||||
comment_link = comment_id
|
comment_link = comment_id
|
||||||
else
|
else
|
||||||
comment_link = link_to(comment_id, issue_url(issue, only_path: only_path, anchor: "note-#{comment_id}"))
|
comment_link = link_to comment_id, issue_url(issue, only_path: only_path, anchor: "note-#{comment_id}")
|
||||||
end
|
end
|
||||||
|
|
||||||
tag.div class: 'issue-macro box' do
|
tag.div class: 'issue-macro box' do
|
||||||
@ -105,14 +107,14 @@ module Additionals
|
|||||||
# if more than one projects available, we do not use project url for a new issue
|
# if more than one projects available, we do not use project url for a new issue
|
||||||
if project_count > 1
|
if project_count > 1
|
||||||
if permission == :edit_issues
|
if permission == :edit_issues
|
||||||
new_issue_path('issue[assigned_to_id]' => user.id, 'issue[project_id]' => project_id)
|
new_issue_path 'issue[assigned_to_id]' => user.id, 'issue[project_id]' => project_id
|
||||||
else
|
else
|
||||||
new_issue_path('issue[project_id]' => project_id)
|
new_issue_path 'issue[project_id]' => project_id
|
||||||
end
|
end
|
||||||
elsif permission == :edit_issues
|
elsif permission == :edit_issues
|
||||||
new_project_issue_path(project_id, 'issue[assigned_to_id]' => user.id)
|
new_project_issue_path project_id, 'issue[assigned_to_id]' => user.id
|
||||||
else
|
else
|
||||||
new_project_issue_path(project_id)
|
new_project_issue_path project_id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -125,10 +127,10 @@ module Additionals
|
|||||||
return rc
|
return rc
|
||||||
end
|
end
|
||||||
|
|
||||||
uri = URI.parse(url)
|
uri = URI.parse url
|
||||||
# support issue_id plugin
|
# support issue_id plugin
|
||||||
# see https://www.redmine.org/plugins/issue_id
|
# see https://www.redmine.org/plugins/issue_id
|
||||||
issue_id_parts = url.split('-')
|
issue_id_parts = url.split '-'
|
||||||
if uri.scheme.nil? && uri.path[0] != '/' && issue_id_parts.count == 2
|
if uri.scheme.nil? && uri.path[0] != '/' && issue_id_parts.count == 2
|
||||||
rc[:issue_id] = url
|
rc[:issue_id] = url
|
||||||
else
|
else
|
||||||
@ -153,10 +155,10 @@ module Additionals
|
|||||||
safe_join s
|
safe_join s
|
||||||
end
|
end
|
||||||
|
|
||||||
def autocomplete_select_entries(name, type, option_tags, options = {})
|
def autocomplete_select_entries(name, type, option_tags, **options)
|
||||||
unless option_tags.is_a?(String) || option_tags.blank?
|
unless option_tags.is_a?(String) || option_tags.blank?
|
||||||
# if option_tags is not an array, it should be an object
|
# if option_tags is not an array, it should be an object
|
||||||
option_tags = options_for_select([[option_tags.try(:name), option_tags.try(:id)]], option_tags.try(:id))
|
option_tags = options_for_select [[option_tags.try(:name), option_tags.try(:id)]], option_tags.try(:id)
|
||||||
end
|
end
|
||||||
options[:project] = @project if @project && options[:project].blank?
|
options[:project] = @project if @project && options[:project].blank?
|
||||||
|
|
||||||
@ -168,7 +170,7 @@ module Additionals
|
|||||||
multiple: options[:multiple],
|
multiple: options[:multiple],
|
||||||
disabled: options[:disabled])
|
disabled: options[:disabled])
|
||||||
s << render(layout: false,
|
s << render(layout: false,
|
||||||
partial: 'additionals/select2_ajax_call.js',
|
partial: 'additionals/select2_ajax_call',
|
||||||
formats: [:js],
|
formats: [:js],
|
||||||
locals: { field_id: sanitize_to_id(name),
|
locals: { field_id: sanitize_to_id(name),
|
||||||
ajax_url: send("#{type}_path", project_id: options[:project], user_id: options[:user_id]),
|
ajax_url: send("#{type}_path", project_id: options[:project], user_id: options[:user_id]),
|
||||||
@ -186,12 +188,12 @@ module Additionals
|
|||||||
classes.join ' '
|
classes.join ' '
|
||||||
end
|
end
|
||||||
|
|
||||||
def addtionals_textarea_cols(text, options = {})
|
def addtionals_textarea_cols(text, min: 8, max: 20)
|
||||||
[[(options[:min].presence || 8), text.to_s.length / 50].max, (options[:max].presence || 20)].min
|
[[min, text.to_s.length / 50].max, max].min
|
||||||
end
|
end
|
||||||
|
|
||||||
def title_with_fontawesome(title, symbole, wrapper = 'span')
|
def title_with_fontawesome(title, symbole, wrapper = 'span')
|
||||||
tag.send(wrapper) do
|
tag.send wrapper do
|
||||||
concat tag.i class: "#{symbole} for-fa-title", 'aria-hidden': 'true'
|
concat tag.i class: "#{symbole} for-fa-title", 'aria-hidden': 'true'
|
||||||
concat title
|
concat title
|
||||||
end
|
end
|
||||||
@ -202,7 +204,7 @@ module Additionals
|
|||||||
def additionals_already_loaded(scope, js_name)
|
def additionals_already_loaded(scope, js_name)
|
||||||
locked = "#{js_name}.#{scope}"
|
locked = "#{js_name}.#{scope}"
|
||||||
@alreaded_loaded = [] if @alreaded_loaded.nil?
|
@alreaded_loaded = [] if @alreaded_loaded.nil?
|
||||||
return true if @alreaded_loaded.include?(locked)
|
return true if @alreaded_loaded.include? locked
|
||||||
|
|
||||||
@alreaded_loaded << locked
|
@alreaded_loaded << locked
|
||||||
false
|
false
|
||||||
@ -276,21 +278,19 @@ module Additionals
|
|||||||
additionals_include_js 'd3plus-network.full.min'
|
additionals_include_js 'd3plus-network.full.min'
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_with_avatar(user, options = {})
|
def user_with_avatar(user, no_link: false, css_class: 'additionals-avatar', size: 14)
|
||||||
return if user.nil?
|
return if user.nil?
|
||||||
|
|
||||||
if user.type == 'Group'
|
if user.type == 'Group'
|
||||||
if options[:no_link] || !Redmine::Plugin.installed?('redmine_hrm')
|
if no_link || !Redmine::Plugin.installed?('redmine_hrm')
|
||||||
user.name
|
user.name
|
||||||
else
|
else
|
||||||
link_to_hrm_group user
|
link_to_hrm_group user
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
options[:size] = 14 if options[:size].nil?
|
|
||||||
options[:class] = 'additionals-avatar' if options[:class].nil?
|
|
||||||
s = []
|
s = []
|
||||||
s << avatar(user, options)
|
s << avatar(user, { size: size, class: css_class })
|
||||||
s << if options[:no_link]
|
s << if no_link
|
||||||
user.name
|
user.name
|
||||||
else
|
else
|
||||||
link_to_user user
|
link_to_user user
|
||||||
@ -305,10 +305,10 @@ module Additionals
|
|||||||
l(:label_app_menu) => 'app' }, active)
|
l(:label_app_menu) => 'app' }, active)
|
||||||
end
|
end
|
||||||
|
|
||||||
def human_float_number(value, options = {})
|
def human_float_number(value, precision: 2, separator: '.')
|
||||||
ActionController::Base.helpers.number_with_precision(value,
|
ActionController::Base.helpers.number_with_precision(value,
|
||||||
precision: options[:precision].presence || 2,
|
precision: precision,
|
||||||
separator: options[:separator].presence || '.',
|
separator: separator,
|
||||||
strip_insignificant_zeros: true)
|
strip_insignificant_zeros: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
class AdditionalsHookListener < Redmine::Hook::ViewListener
|
class AdditionalsHookListener < Redmine::Hook::ViewListener
|
||||||
include IssuesHelper
|
include IssuesHelper
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
module Patches
|
module Patches
|
||||||
module AccessControlPatch
|
module AccessControlPatch
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
module Patches
|
module Patches
|
||||||
module ApplicationControllerPatch
|
module ApplicationControllerPatch
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
module Patches
|
module Patches
|
||||||
module AutoCompletesControllerPatch
|
module AutoCompletesControllerPatch
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
module Patches
|
module Patches
|
||||||
module FormatterMarkdownPatch
|
module FormatterMarkdownPatch
|
||||||
@ -8,7 +10,7 @@ module Additionals
|
|||||||
|
|
||||||
# Add a postprocess hook to redcarpet's html formatter
|
# Add a postprocess hook to redcarpet's html formatter
|
||||||
def postprocess(text)
|
def postprocess(text)
|
||||||
if Additionals.setting?(:legacy_smiley_support)
|
if Additionals.setting? :legacy_smiley_support
|
||||||
render_inline_smileys(inline_emojify(text))
|
render_inline_smileys(inline_emojify(text))
|
||||||
else
|
else
|
||||||
text
|
text
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
module Patches
|
module Patches
|
||||||
module FormatterTextilePatch
|
module FormatterTextilePatch
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
module Patches
|
module Patches
|
||||||
module FormattingHelperPatch
|
module FormattingHelperPatch
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
module Patches
|
module Patches
|
||||||
module IssuePatch
|
module IssuePatch
|
||||||
@ -23,27 +25,22 @@ module Additionals
|
|||||||
end
|
end
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
||||||
def join_issue_status(options = {})
|
def join_issue_status(is_closed: nil)
|
||||||
sql = "JOIN #{IssueStatus.table_name} ON #{IssueStatus.table_name}.id = #{table_name}.status_id"
|
sql = +"JOIN #{IssueStatus.table_name} ON #{IssueStatus.table_name}.id = #{table_name}.status_id"
|
||||||
return sql unless options.key?(:is_closed)
|
return sql if is_closed.nil?
|
||||||
|
|
||||||
sql << " AND #{IssueStatus.table_name}.is_closed ="
|
sql << " AND #{IssueStatus.table_name}.is_closed = #{is_closed ? connection.quoted_true : connection.quoted_false}"
|
||||||
sql << if options[:is_closed]
|
|
||||||
" #{connection.quoted_true}"
|
|
||||||
else
|
|
||||||
" #{connection.quoted_false}"
|
|
||||||
end
|
|
||||||
sql
|
sql
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module InstanceMethods
|
module InstanceMethods
|
||||||
def sidbar_change_status_allowed_to(user, new_status_id = nil)
|
def sidbar_change_status_allowed_to(user, new_status_id = nil)
|
||||||
statuses = new_statuses_allowed_to(user)
|
statuses = new_statuses_allowed_to user
|
||||||
if new_status_id.present?
|
if new_status_id.present?
|
||||||
statuses.detect { |s| new_status_id == s.id && !timelog_required?(s.id) }
|
statuses.detect { |s| new_status_id == s.id && !timelog_required?(s.id) }
|
||||||
else
|
else
|
||||||
statuses.reject { |s| timelog_required?(s.id) }
|
statuses.reject { |s| timelog_required? s.id }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -63,7 +60,7 @@ module Additionals
|
|||||||
return if Redmine::Plugin.installed?('redmine_automation') && author_id == RedmineAutomation.bot_user_id
|
return if Redmine::Plugin.installed?('redmine_automation') && author_id == RedmineAutomation.bot_user_id
|
||||||
|
|
||||||
add_autowatcher User.current
|
add_autowatcher User.current
|
||||||
add_autowatcher(author) if (new_record? || author_id != author_id_was) && author != User.current
|
add_autowatcher author if (new_record? || author_id != author_id_was) && author != User.current
|
||||||
|
|
||||||
if !assigned_to_id.nil? && assigned_to_id != User.current.id && (new_record? || assigned_to_id != assigned_to_id_was)
|
if !assigned_to_id.nil? && assigned_to_id != User.current.id && (new_record? || assigned_to_id != assigned_to_id_was)
|
||||||
add_autowatcher assigned_to
|
add_autowatcher assigned_to
|
||||||
@ -127,7 +124,7 @@ module Additionals
|
|||||||
end
|
end
|
||||||
|
|
||||||
def auto_assigned_to_user
|
def auto_assigned_to_user
|
||||||
manager_role = Role.builtin.find_by(id: Additionals.setting(:issue_auto_assign_role))
|
manager_role = Role.builtin.find_by id: Additionals.setting(:issue_auto_assign_role)
|
||||||
groups = autoassign_get_group_list
|
groups = autoassign_get_group_list
|
||||||
return groups[manager_role].first.id unless groups.nil? || groups[manager_role].blank?
|
return groups[manager_role].first.id unless groups.nil? || groups[manager_role].blank?
|
||||||
|
|
||||||
@ -150,7 +147,7 @@ module Additionals
|
|||||||
end
|
end
|
||||||
|
|
||||||
def validate_timelog_required
|
def validate_timelog_required
|
||||||
return true unless timelog_required?(status_id)
|
return true unless timelog_required? status_id
|
||||||
|
|
||||||
errors.add :base, :issue_requires_timelog
|
errors.add :base, :issue_requires_timelog
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
module Patches
|
module Patches
|
||||||
module IssuePriorityPatch
|
module IssuePriorityPatch
|
||||||
@ -13,7 +15,7 @@ module Additionals
|
|||||||
module InstanceMethods
|
module InstanceMethods
|
||||||
def css_classes_with_additionals
|
def css_classes_with_additionals
|
||||||
classes = [css_classes_without_additionals, css_name_based_class]
|
classes = [css_classes_without_additionals, css_name_based_class]
|
||||||
classes.join(' ')
|
classes.join ' '
|
||||||
end
|
end
|
||||||
|
|
||||||
# css class based on priority name
|
# css class based on priority name
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
module Patches
|
module Patches
|
||||||
module PrincipalPatch
|
module PrincipalPatch
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
||||||
scope :assignable, -> { active.visible.where(type: %w[User Group]) }
|
scope :assignable, -> { active.visible.where type: %w[User Group] }
|
||||||
|
|
||||||
scope :assignable_for_issues, lambda { |*args|
|
scope :assignable_for_issues, lambda { |*args|
|
||||||
project = args.first
|
project = args.first
|
||||||
users = assignable
|
users = assignable
|
||||||
users = users.where.not(type: 'Group') unless Setting.issue_group_assignment?
|
users = users.where.not type: 'Group' unless Setting.issue_group_assignment?
|
||||||
users = users.joins(members: :roles)
|
users = users.joins(members: :roles)
|
||||||
.where(roles: { assignable: true })
|
.where(roles: { assignable: true })
|
||||||
.distinct
|
.distinct
|
||||||
@ -35,7 +37,7 @@ module Additionals
|
|||||||
active
|
active
|
||||||
else
|
else
|
||||||
# self and members of visible projects
|
# self and members of visible projects
|
||||||
scope = if user.allowed_to?(:show_hidden_roles_in_memberbox, nil, global: true)
|
scope = if user.allowed_to? :show_hidden_roles_in_memberbox, nil, global: true
|
||||||
active.where("#{table_name}.id = ? OR #{table_name}.id IN (SELECT user_id " \
|
active.where("#{table_name}.id = ? OR #{table_name}.id IN (SELECT user_id " \
|
||||||
"FROM #{Member.table_name} WHERE project_id IN (?))",
|
"FROM #{Member.table_name} WHERE project_id IN (?))",
|
||||||
user.id, user.visible_project_ids)
|
user.id, user.visible_project_ids)
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
module Patches
|
module Patches
|
||||||
module ProjectPatch
|
module ProjectPatch
|
||||||
@ -52,12 +54,12 @@ module Additionals
|
|||||||
end
|
end
|
||||||
|
|
||||||
def visible_principals
|
def visible_principals
|
||||||
query = ::Query.new(project: self, name: '_')
|
query = ::Query.new project: self, name: '_'
|
||||||
query&.principals
|
query&.principals
|
||||||
end
|
end
|
||||||
|
|
||||||
def visible_users
|
def visible_users
|
||||||
query = ::Query.new(project: self, name: '_')
|
query = ::Query.new project: self, name: '_'
|
||||||
query&.users
|
query&.users
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_dependency 'projects_controller'
|
require_dependency 'projects_controller'
|
||||||
|
|
||||||
module Additionals
|
module Additionals
|
||||||
@ -27,7 +29,7 @@ module Additionals
|
|||||||
def find_dashboard
|
def find_dashboard
|
||||||
if params[:dashboard_id].present?
|
if params[:dashboard_id].present?
|
||||||
begin
|
begin
|
||||||
@dashboard = Dashboard.project_only.find(params[:dashboard_id])
|
@dashboard = Dashboard.project_only.find params[:dashboard_id]
|
||||||
raise ::Unauthorized unless @dashboard.visible?
|
raise ::Unauthorized unless @dashboard.visible?
|
||||||
raise ::Unauthorized unless @dashboard.project.nil? || @dashboard.project == @project
|
raise ::Unauthorized unless @dashboard.project.nil? || @dashboard.project == @project
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
14
lib/additionals/patches/queries_helper_patch.rb
Normal file
14
lib/additionals/patches/queries_helper_patch.rb
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Additionals
|
||||||
|
module Patches
|
||||||
|
module QueriesHelperPatch
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
included do
|
||||||
|
def additional_csv_separator
|
||||||
|
l(:general_csv_separator) == ',' ? ';' : ','
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user