Actualiza a Redmine 3.4.13
This commit is contained in:
parent
807ff3308d
commit
ecddcaf1d3
224 changed files with 2222 additions and 1000 deletions
|
@ -87,7 +87,7 @@ class AccountController < ApplicationController
|
|||
@user.must_change_passwd = false
|
||||
if @user.save
|
||||
@token.destroy
|
||||
Mailer.password_updated(@user)
|
||||
Mailer.password_updated(@user, { remote_ip: request.remote_ip })
|
||||
flash[:notice] = l(:notice_account_password_updated)
|
||||
redirect_to signin_path
|
||||
return
|
||||
|
|
|
@ -60,7 +60,7 @@ class AttachmentsController < ApplicationController
|
|||
@attachment.increment_download
|
||||
end
|
||||
|
||||
if stale?(:etag => @attachment.digest)
|
||||
if stale?(:etag => @attachment.digest, :template => false)
|
||||
# images are sent inline
|
||||
send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
|
||||
:type => detect_content_type(@attachment),
|
||||
|
@ -70,7 +70,7 @@ class AttachmentsController < ApplicationController
|
|||
|
||||
def thumbnail
|
||||
if @attachment.thumbnailable? && tbnail = @attachment.thumbnail(:size => params[:size])
|
||||
if stale?(:etag => tbnail)
|
||||
if stale?(:etag => tbnail, :template => false)
|
||||
send_file tbnail,
|
||||
:filename => filename_for_content_disposition(@attachment.filename),
|
||||
:type => detect_content_type(@attachment),
|
||||
|
|
|
@ -19,7 +19,7 @@ class AutoCompletesController < ApplicationController
|
|||
before_action :find_project
|
||||
|
||||
def issues
|
||||
@issues = []
|
||||
issues = []
|
||||
q = (params[:q] || params[:term]).to_s.strip
|
||||
status = params[:status].to_s
|
||||
issue_id = params[:issue_id].to_s
|
||||
|
@ -32,13 +32,14 @@ class AutoCompletesController < ApplicationController
|
|||
scope = scope.where.not(:id => issue_id.to_i)
|
||||
end
|
||||
if q.match(/\A#?(\d+)\z/)
|
||||
@issues << scope.find_by_id($1.to_i)
|
||||
issues << scope.find_by_id($1.to_i)
|
||||
end
|
||||
|
||||
@issues += scope.like(q).order(:id => :desc).limit(10).to_a
|
||||
@issues.compact!
|
||||
issues += scope.like(q).order(:id => :desc).limit(10).to_a
|
||||
issues.compact!
|
||||
end
|
||||
render :layout => false
|
||||
|
||||
render :json => format_issues_json(issues)
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -50,4 +51,13 @@ class AutoCompletesController < ApplicationController
|
|||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
|
||||
def format_issues_json(issues)
|
||||
issues.map {|issue| {
|
||||
'id' => issue.id,
|
||||
'label' => "#{issue.tracker} ##{issue.id}: #{issue.subject.to_s.truncate(60)}",
|
||||
'value' => issue.id
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -91,8 +91,10 @@ class EnumerationsController < ApplicationController
|
|||
|
||||
def build_new_enumeration
|
||||
class_name = params[:enumeration] && params[:enumeration][:type] || params[:type]
|
||||
@enumeration = Enumeration.new_subclass_instance(class_name, enumeration_params)
|
||||
if @enumeration.nil?
|
||||
@enumeration = Enumeration.new_subclass_instance(class_name)
|
||||
if @enumeration
|
||||
@enumeration.attributes = enumeration_params || {}
|
||||
else
|
||||
render_404
|
||||
end
|
||||
end
|
||||
|
@ -105,6 +107,7 @@ class EnumerationsController < ApplicationController
|
|||
|
||||
def enumeration_params
|
||||
# can't require enumeration on #new action
|
||||
params.permit(:enumeration => [:name, :active, :is_default, :position])[:enumeration]
|
||||
cf_ids = @enumeration.available_custom_fields.map{|c| c.id.to_s}
|
||||
params.permit(:enumeration => [:name, :active, :is_default, :position, :custom_field_values => cf_ids])[:enumeration]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -40,7 +40,8 @@ class IssuesController < ApplicationController
|
|||
helper :timelog
|
||||
|
||||
def index
|
||||
retrieve_query
|
||||
use_session = !request.format.csv?
|
||||
retrieve_query(IssueQuery, use_session)
|
||||
|
||||
if @query.valid?
|
||||
respond_to do |format|
|
||||
|
@ -367,7 +368,12 @@ class IssuesController < ApplicationController
|
|||
when 'destroy'
|
||||
# nothing to do
|
||||
when 'nullify'
|
||||
if Setting.timelog_required_fields.include?('issue_id')
|
||||
flash.now[:error] = l(:field_issue) + " " + ::I18n.t('activerecord.errors.messages.blank')
|
||||
return
|
||||
else
|
||||
time_entries.update_all(:issue_id => nil)
|
||||
end
|
||||
when 'reassign'
|
||||
reassign_to = @project && @project.issues.find_by_id(params[:reassign_to_id])
|
||||
if reassign_to.nil?
|
||||
|
|
|
@ -37,7 +37,7 @@ class SearchController < ApplicationController
|
|||
end
|
||||
|
||||
# quick jump to an issue
|
||||
if (m = @question.match(/^#?(\d+)$/)) && (issue = Issue.visible.find_by_id(m[1].to_i))
|
||||
if !api_request? && (m = @question.match(/^#?(\d+)$/)) && (issue = Issue.visible.find_by_id(m[1].to_i))
|
||||
redirect_to issue_path(issue)
|
||||
return
|
||||
end
|
||||
|
@ -49,7 +49,7 @@ class SearchController < ApplicationController
|
|||
when 'my_projects'
|
||||
User.current.projects
|
||||
when 'subprojects'
|
||||
@project ? (@project.self_and_descendants.active.to_a) : nil
|
||||
@project ? (@project.self_and_descendants.to_a) : nil
|
||||
else
|
||||
@project
|
||||
end
|
||||
|
|
|
@ -114,6 +114,7 @@ class TimelogController < ApplicationController
|
|||
:time_entry => {
|
||||
:project_id => params[:time_entry][:project_id],
|
||||
:issue_id => @time_entry.issue_id,
|
||||
:spent_on => @time_entry.spent_on,
|
||||
:activity_id => @time_entry.activity_id
|
||||
},
|
||||
:back_url => params[:back_url]
|
||||
|
|
|
@ -106,6 +106,6 @@ class TrackersController < ApplicationController
|
|||
return
|
||||
end
|
||||
@trackers = Tracker.sorted.to_a
|
||||
@custom_fields = IssueCustomField.all.sort
|
||||
@custom_fields = IssueCustomField.sorted
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
class WikiController < ApplicationController
|
||||
default_search_scope :wiki_pages
|
||||
before_action :find_wiki, :authorize
|
||||
before_action :find_existing_or_new_page, :only => [:show, :edit, :update]
|
||||
before_action :find_existing_or_new_page, :only => [:show, :edit]
|
||||
before_action :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy, :destroy_version]
|
||||
before_action :find_attachments, :only => [:preview]
|
||||
accept_api_auth :index, :show, :update, :destroy
|
||||
|
@ -42,8 +42,6 @@ class WikiController < ApplicationController
|
|||
helper :watchers
|
||||
include Redmine::Export::PDF
|
||||
|
||||
include ActionView::Helpers::SanitizeHelper
|
||||
|
||||
# List of pages, sorted alphabetically and by parent (hierarchy)
|
||||
def index
|
||||
load_pages_for_index
|
||||
|
@ -109,7 +107,7 @@ class WikiController < ApplicationController
|
|||
send_data(export, :type => 'text/html', :filename => filename_for_content_disposition("#{@page.title}.html"))
|
||||
return
|
||||
elsif params[:format] == 'txt'
|
||||
send_data(strip_tags(@content.text), :type => 'text/plain', :filename => filename_for_content_disposition("#{@page.title}.txt"))
|
||||
send_data(@content.text, :type => 'text/plain', :filename => filename_for_content_disposition("#{@page.title}.txt"))
|
||||
return
|
||||
end
|
||||
end
|
||||
|
@ -152,6 +150,8 @@ class WikiController < ApplicationController
|
|||
|
||||
# Creates a new page or updates an existing one
|
||||
def update
|
||||
@page = @wiki.find_or_new_page(params[:id])
|
||||
|
||||
return render_403 unless editable?
|
||||
was_new_page = @page.new_record?
|
||||
@page.safe_attributes = params[:wiki_page]
|
||||
|
|
|
@ -1272,7 +1272,7 @@ module ApplicationHelper
|
|||
link_to_function '',
|
||||
"toggleCheckboxesBySelector('#{selector}')",
|
||||
:title => "#{l(:button_check_all)} / #{l(:button_uncheck_all)}",
|
||||
:class => 'toggle-checkboxes'
|
||||
:class => 'icon icon-checked'
|
||||
end
|
||||
|
||||
def progress_bar(pcts, options={})
|
||||
|
@ -1423,10 +1423,13 @@ module ApplicationHelper
|
|||
end
|
||||
if email.present?
|
||||
gravatar(email.to_s.downcase, options) rescue nil
|
||||
else
|
||||
elsif user.is_a?(AnonymousUser)
|
||||
options[:size] &&= options[:size].to_s
|
||||
image_tag 'anonymous.png',
|
||||
GravatarHelper::DEFAULT_OPTIONS
|
||||
.except(:default, :rating, :ssl).merge(options)
|
||||
else
|
||||
nil
|
||||
end
|
||||
else
|
||||
''
|
||||
|
|
|
@ -127,8 +127,8 @@ module IssuesHelper
|
|||
content_tag('td', check_box_tag("ids[]", other_issue.id, false, :id => nil), :class => 'checkbox') +
|
||||
content_tag('td', relation.to_s(@issue) {|other| link_to_issue(other, :project => Setting.cross_project_issue_relations?)}.html_safe, :class => 'subject', :style => 'width: 50%') +
|
||||
content_tag('td', other_issue.status, :class => 'status') +
|
||||
content_tag('td', other_issue.start_date, :class => 'start_date') +
|
||||
content_tag('td', other_issue.due_date, :class => 'due_date') +
|
||||
content_tag('td', format_date(other_issue.start_date), :class => 'start_date') +
|
||||
content_tag('td', format_date(other_issue.due_date), :class => 'due_date') +
|
||||
content_tag('td', other_issue.disabled_core_fields.include?('done_ratio') ? '' : progress_bar(other_issue.done_ratio), :class=> 'done_ratio') +
|
||||
content_tag('td', link, :class => 'buttons'),
|
||||
:id => "relation-#{relation.id}",
|
||||
|
@ -246,8 +246,12 @@ module IssuesHelper
|
|||
issue_fields_rows do |rows|
|
||||
values.each_with_index do |value, i|
|
||||
css = "cf_#{value.custom_field.id}"
|
||||
attr_value = show_value(value)
|
||||
if value.custom_field.text_formatting == 'full'
|
||||
attr_value = content_tag('div', attr_value, class: 'wiki')
|
||||
end
|
||||
m = (i < half ? :left : :right)
|
||||
rows.send m, custom_field_name_tag(value.custom_field), show_value(value), :class => css
|
||||
rows.send m, custom_field_name_tag(value.custom_field), attr_value, :class => css
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -310,7 +314,7 @@ module IssuesHelper
|
|||
# Returns an array of users that are proposed as watchers
|
||||
# on the new issue form
|
||||
def users_for_new_issue_watchers(issue)
|
||||
users = issue.watcher_users
|
||||
users = issue.watcher_users.select{|u| u.status == User::STATUS_ACTIVE}
|
||||
if issue.project.users.count <= 20
|
||||
users = (users + issue.project.users.sort).uniq
|
||||
end
|
||||
|
|
|
@ -18,14 +18,11 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module SearchHelper
|
||||
include ActionView::Helpers::SanitizeHelper
|
||||
|
||||
def highlight_tokens(text, tokens)
|
||||
return text unless text && tokens && !tokens.empty?
|
||||
re_tokens = tokens.collect {|t| Regexp.escape(t)}
|
||||
regexp = Regexp.new "(#{re_tokens.join('|')})", Regexp::IGNORECASE
|
||||
result = ''
|
||||
text = strip_tags(text)
|
||||
text.split(regexp).each_with_index do |words, i|
|
||||
if result.length > 1200
|
||||
# maximum length of the preview reached
|
||||
|
|
|
@ -156,7 +156,7 @@ class Attachment < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def title
|
||||
title = filename.to_s
|
||||
title = filename.dup
|
||||
if description.present?
|
||||
title << " (#{description})"
|
||||
end
|
||||
|
|
|
@ -217,6 +217,7 @@ class Import < ActiveRecord::Base
|
|||
|
||||
csv_options = {:headers => false}
|
||||
csv_options[:encoding] = settings['encoding'].to_s.presence || 'UTF-8'
|
||||
csv_options[:encoding] = 'bom|UTF-8' if csv_options[:encoding] == 'UTF-8'
|
||||
separator = settings['separator'].to_s
|
||||
csv_options[:col_sep] = separator if separator.size == 1
|
||||
wrapper = settings['wrapper'].to_s
|
||||
|
|
|
@ -275,7 +275,8 @@ class Issue < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
unless options[:watchers] == false
|
||||
self.watcher_user_ids = issue.watcher_user_ids.dup
|
||||
self.watcher_user_ids =
|
||||
issue.watcher_users.select{|u| u.status == User::STATUS_ACTIVE}.map(&:id)
|
||||
end
|
||||
@copied_from = issue
|
||||
@copy_options = options
|
||||
|
@ -1086,7 +1087,7 @@ class Issue < ActiveRecord::Base
|
|||
if leaf?
|
||||
estimated_hours
|
||||
else
|
||||
@total_estimated_hours ||= self_and_descendants.sum(:estimated_hours)
|
||||
@total_estimated_hours ||= self_and_descendants.visible.sum(:estimated_hours)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1300,7 +1301,7 @@ class Issue < ActiveRecord::Base
|
|||
|
||||
# Reschedules the issue on the given date or the next working day and saves the record.
|
||||
# If the issue is a parent task, this is done by rescheduling its subtasks.
|
||||
def reschedule_on!(date)
|
||||
def reschedule_on!(date, journal=nil)
|
||||
return if date.nil?
|
||||
if leaf? || !dates_derived?
|
||||
if start_date.nil? || start_date != date
|
||||
|
@ -1308,6 +1309,9 @@ class Issue < ActiveRecord::Base
|
|||
# Issue can not be moved earlier than its soonest start date
|
||||
date = [soonest_start(true), date].compact.max
|
||||
end
|
||||
if journal
|
||||
init_journal(journal.user)
|
||||
end
|
||||
reschedule_on(date)
|
||||
begin
|
||||
save
|
||||
|
@ -1631,6 +1635,8 @@ class Issue < ActiveRecord::Base
|
|||
copy.author = author
|
||||
copy.project = project
|
||||
copy.parent_issue_id = copied_issue_ids[child.parent_id]
|
||||
copy.fixed_version_id = nil unless child.fixed_version.present? && child.fixed_version.status == 'open'
|
||||
copy.assigned_to = nil unless child.assigned_to_id.present? && child.assigned_to.status == User::STATUS_ACTIVE
|
||||
unless copy.save
|
||||
logger.error "Could not copy subtask ##{child.id} while copying ##{@copied_from.id} to ##{id} due to validation errors: #{copy.errors.full_messages.join(', ')}" if logger
|
||||
next
|
||||
|
@ -1789,7 +1795,7 @@ class Issue < ActiveRecord::Base
|
|||
def reschedule_following_issues
|
||||
if start_date_changed? || due_date_changed?
|
||||
relations_from.each do |relation|
|
||||
relation.set_issue_to_dates
|
||||
relation.set_issue_to_dates(@current_journal)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -122,7 +122,10 @@ class IssueImport < Import
|
|||
end
|
||||
end
|
||||
if issue.project && version_name = row_value(row, 'fixed_version')
|
||||
if version = issue.project.versions.named(version_name).first
|
||||
version =
|
||||
issue.project.versions.named(version_name).first ||
|
||||
issue.project.shared_versions.named(version_name).first
|
||||
if version
|
||||
attributes['fixed_version_id'] = version.id
|
||||
elsif create_versions?
|
||||
version = issue.project.versions.build
|
||||
|
|
|
@ -37,8 +37,8 @@ class IssueQuery < Query
|
|||
QueryColumn.new(:due_date, :sortable => "#{Issue.table_name}.due_date"),
|
||||
QueryColumn.new(:estimated_hours, :sortable => "#{Issue.table_name}.estimated_hours", :totalable => true),
|
||||
QueryColumn.new(:total_estimated_hours,
|
||||
:sortable => "COALESCE((SELECT SUM(estimated_hours) FROM #{Issue.table_name} subtasks" +
|
||||
" WHERE subtasks.root_id = #{Issue.table_name}.root_id AND subtasks.lft >= #{Issue.table_name}.lft AND subtasks.rgt <= #{Issue.table_name}.rgt), 0)",
|
||||
:sortable => -> { "COALESCE((SELECT SUM(estimated_hours) FROM #{Issue.table_name} subtasks" +
|
||||
" WHERE #{Issue.visible_condition(User.current).gsub(/\bissues\b/, 'subtasks')} AND subtasks.root_id = #{Issue.table_name}.root_id AND subtasks.lft >= #{Issue.table_name}.lft AND subtasks.rgt <= #{Issue.table_name}.rgt), 0)" },
|
||||
:default_order => 'desc'),
|
||||
QueryColumn.new(:done_ratio, :sortable => "#{Issue.table_name}.done_ratio", :groupable => true),
|
||||
QueryColumn.new(:created_on, :sortable => "#{Issue.table_name}.created_on", :default_order => 'desc'),
|
||||
|
@ -221,6 +221,7 @@ class IssueQuery < Query
|
|||
end
|
||||
|
||||
disabled_fields = Tracker.disabled_core_fields(trackers).map {|field| field.sub(/_id$/, '')}
|
||||
disabled_fields << "total_estimated_hours" if disabled_fields.include?("estimated_hours")
|
||||
@available_columns.reject! {|column|
|
||||
disabled_fields.include?(column.name.to_s)
|
||||
}
|
||||
|
@ -373,7 +374,7 @@ class IssueQuery < Query
|
|||
neg = (operator == '!' ? 'NOT' : '')
|
||||
subquery = "SELECT 1 FROM #{Journal.table_name} sj" +
|
||||
" WHERE sj.journalized_type='Issue' AND sj.journalized_id=#{Issue.table_name}.id AND (#{sql_for_field field, '=', value, 'sj', 'user_id'})" +
|
||||
" AND sj.id = (SELECT MAX(#{Journal.table_name}.id) FROM #{Journal.table_name}" +
|
||||
" AND sj.id IN (SELECT MAX(#{Journal.table_name}.id) FROM #{Journal.table_name}" +
|
||||
" WHERE #{Journal.table_name}.journalized_type='Issue' AND #{Journal.table_name}.journalized_id=#{Issue.table_name}.id" +
|
||||
" AND (#{Journal.visible_notes_condition(User.current, :skip_pre_condition => true)}))"
|
||||
|
||||
|
@ -382,8 +383,26 @@ class IssueQuery < Query
|
|||
|
||||
def sql_for_watcher_id_field(field, operator, value)
|
||||
db_table = Watcher.table_name
|
||||
"#{Issue.table_name}.id #{ operator == '=' ? 'IN' : 'NOT IN' } (SELECT #{db_table}.watchable_id FROM #{db_table} WHERE #{db_table}.watchable_type='Issue' AND " +
|
||||
sql_for_field(field, '=', value, db_table, 'user_id') + ')'
|
||||
|
||||
me, others = value.partition { |id| ['0', User.current.id.to_s].include?(id) }
|
||||
sql = if others.any?
|
||||
"SELECT #{Issue.table_name}.id FROM #{Issue.table_name} " +
|
||||
"INNER JOIN #{db_table} ON #{Issue.table_name}.id = #{db_table}.watchable_id AND #{db_table}.watchable_type = 'Issue' " +
|
||||
"LEFT OUTER JOIN #{Project.table_name} ON #{Project.table_name}.id = #{Issue.table_name}.project_id " +
|
||||
"WHERE (" +
|
||||
sql_for_field(field, '=', me, db_table, 'user_id') +
|
||||
') OR (' +
|
||||
Project.allowed_to_condition(User.current, :view_issue_watchers) +
|
||||
' AND ' +
|
||||
sql_for_field(field, '=', others, db_table, 'user_id') +
|
||||
')'
|
||||
else
|
||||
"SELECT #{db_table}.watchable_id FROM #{db_table} " +
|
||||
"WHERE #{db_table}.watchable_type='Issue' AND " +
|
||||
sql_for_field(field, '=', me, db_table, 'user_id')
|
||||
end
|
||||
|
||||
"#{Issue.table_name}.id #{ operator == '=' ? 'IN' : 'NOT IN' } (#{sql})"
|
||||
end
|
||||
|
||||
def sql_for_member_of_group_field(field, operator, value)
|
||||
|
|
|
@ -176,10 +176,10 @@ class IssueRelation < ActiveRecord::Base
|
|||
set_issue_to_dates
|
||||
end
|
||||
|
||||
def set_issue_to_dates
|
||||
def set_issue_to_dates(journal=nil)
|
||||
soonest_start = self.successor_soonest_start
|
||||
if soonest_start && issue_to
|
||||
issue_to.reschedule_on!(soonest_start)
|
||||
issue_to.reschedule_on!(soonest_start, journal)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ class MailHandler < ActionMailer::Base
|
|||
def self.safe_receive(*args)
|
||||
receive(*args)
|
||||
rescue Exception => e
|
||||
logger.error "MailHandler: an unexpected error occurred when receiving email: #{e.message}" if logger
|
||||
Rails.logger.error "MailHandler: an unexpected error occurred when receiving email: #{e.message}"
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -65,7 +65,7 @@ class MailHandler < ActionMailer::Base
|
|||
%w(project status tracker category priority assigned_to fixed_version).each do |option|
|
||||
options[:issue][option.to_sym] = env[option] if env[option]
|
||||
end
|
||||
%w(allow_override unknown_user no_permission_check no_account_notice default_group project_from_subaddress).each do |option|
|
||||
%w(allow_override unknown_user no_permission_check no_account_notice no_notification default_group project_from_subaddress).each do |option|
|
||||
options[option.to_sym] = env[option] if env[option]
|
||||
end
|
||||
if env['private']
|
||||
|
@ -250,8 +250,8 @@ class MailHandler < ActionMailer::Base
|
|||
|
||||
# add To and Cc as watchers before saving so the watchers can reply to Redmine
|
||||
add_watchers(issue)
|
||||
add_attachments(issue)
|
||||
issue.save!
|
||||
add_attachments(issue)
|
||||
if logger
|
||||
logger.info "MailHandler: issue ##{issue.id} updated by #{user}"
|
||||
end
|
||||
|
@ -286,7 +286,7 @@ class MailHandler < ActionMailer::Base
|
|||
reply
|
||||
else
|
||||
if logger
|
||||
logger.info "MailHandler: ignoring reply from [#{sender_email}] to a locked topic"
|
||||
logger.info "MailHandler: ignoring reply from [#{email.from.first}] to a locked topic"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -311,7 +311,7 @@ class Mailer < ActionMailer::Base
|
|||
end
|
||||
|
||||
# Notifies user that his password was updated
|
||||
def self.password_updated(user)
|
||||
def self.password_updated(user, options={})
|
||||
# Don't send a notification to the dummy email address when changing the password
|
||||
# of the default admin account which is required after the first login
|
||||
# TODO: maybe not the best way to handle this
|
||||
|
@ -320,6 +320,8 @@ class Mailer < ActionMailer::Base
|
|||
security_notification(user,
|
||||
message: :mail_body_password_updated,
|
||||
title: :button_change_password,
|
||||
remote_ip: options[:remote_ip],
|
||||
originator: user,
|
||||
url: {controller: 'my', action: 'password'}
|
||||
).deliver
|
||||
end
|
||||
|
@ -333,7 +335,6 @@ class Mailer < ActionMailer::Base
|
|||
end
|
||||
|
||||
def security_notification(recipients, options={})
|
||||
redmine_headers 'Sender' => User.current.login
|
||||
@user = Array(recipients).detect{|r| r.is_a? User }
|
||||
set_language_if_valid(@user.try :language)
|
||||
@message = l(options[:message],
|
||||
|
@ -341,7 +342,11 @@ class Mailer < ActionMailer::Base
|
|||
value: options[:value]
|
||||
)
|
||||
@title = options[:title] && l(options[:title])
|
||||
@originator = options[:originator] || User.current
|
||||
@remote_ip = options[:remote_ip] || @originator.remote_ip
|
||||
@url = options[:url] && (options[:url].is_a?(Hash) ? url_for(options[:url]) : options[:url])
|
||||
redmine_headers 'Sender' => @originator.login
|
||||
redmine_headers 'Url' => @url
|
||||
mail :to => recipients,
|
||||
:subject => "[#{Setting.app_title}] #{l(:mail_subject_security_notification)}"
|
||||
end
|
||||
|
|
|
@ -319,9 +319,10 @@ class Query < ActiveRecord::Base
|
|||
" INNER JOIN #{table_name_prefix}queries_roles#{table_name_suffix} qr on qr.query_id = q.id" +
|
||||
" INNER JOIN #{MemberRole.table_name} mr ON mr.role_id = qr.role_id" +
|
||||
" INNER JOIN #{Member.table_name} m ON m.id = mr.member_id AND m.user_id = ?" +
|
||||
" INNER JOIN #{Project.table_name} p ON p.id = m.project_id AND p.status <> ?" +
|
||||
" WHERE q.project_id IS NULL OR q.project_id = m.project_id))" +
|
||||
" OR #{table_name}.user_id = ?",
|
||||
VISIBILITY_PUBLIC, VISIBILITY_ROLES, user.id, user.id)
|
||||
VISIBILITY_PUBLIC, VISIBILITY_ROLES, user.id, Project::STATUS_ARCHIVED, user.id)
|
||||
elsif user.logged?
|
||||
scope.where("#{table_name}.visibility = ? OR #{table_name}.user_id = ?", VISIBILITY_PUBLIC, user.id)
|
||||
else
|
||||
|
@ -340,7 +341,7 @@ class Query < ActiveRecord::Base
|
|||
if project
|
||||
(user.roles_for_project(project) & roles).any?
|
||||
else
|
||||
Member.where(:user_id => user.id).joins(:roles).where(:member_roles => {:role_id => roles.map(&:id)}).any?
|
||||
user.memberships.joins(:member_roles).where(:member_roles => {:role_id => roles.map(&:id)}).any?
|
||||
end
|
||||
else
|
||||
user == self.user
|
||||
|
@ -398,6 +399,8 @@ class Query < ActiveRecord::Base
|
|||
params[:v][field] = options[:values]
|
||||
end
|
||||
params[:c] = column_names
|
||||
params[:group_by] = group_by.to_s if group_by.present?
|
||||
params[:t] = totalable_names.map(&:to_s) if totalable_names.any?
|
||||
params[:sort] = sort_criteria.to_param
|
||||
params[:set_filter] = 1
|
||||
params
|
||||
|
|
|
@ -45,7 +45,7 @@ class Version < ActiveRecord::Base
|
|||
scope :like, lambda {|arg|
|
||||
if arg.present?
|
||||
pattern = "%#{arg.to_s.strip}%"
|
||||
where("LOWER(#{Version.table_name}.name) LIKE :p", :p => pattern)
|
||||
where([Redmine::Database.like("#{Version.table_name}.name", '?'), pattern])
|
||||
end
|
||||
}
|
||||
scope :open, lambda { where(:status => 'open') }
|
||||
|
@ -268,7 +268,7 @@ class Version < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def deletable?
|
||||
fixed_issues.empty? && !referenced_by_a_custom_field?
|
||||
fixed_issues.empty? && !referenced_by_a_custom_field? && attachments.empty?
|
||||
end
|
||||
|
||||
def default_project_version
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<%= call_hook :view_account_login_top %>
|
||||
|
||||
<div id="login-form">
|
||||
<h2><%= l(:label_login) %></h2>
|
||||
<%= form_tag(signin_path, onsubmit: 'return keepAnchorOnSignIn(this);') do %>
|
||||
<%= back_url_hidden_field_tag %>
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<% end %>
|
||||
</table>
|
||||
<br />
|
||||
<div class="box">
|
||||
<div class="box autoscroll">
|
||||
<pre><%= Redmine::Info.environment %></pre>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
<%= title l(:label_plugins) %>
|
||||
|
||||
<% if @plugins.any? %>
|
||||
<table class="list plugins">
|
||||
<% @plugins.each do |plugin| %>
|
||||
<tr id="plugin-<%= plugin.id %>">
|
||||
<td class="name"><span class="name"><%= plugin.name %></span>
|
||||
<%= content_tag('span', plugin.description, :class => 'description') unless plugin.description.blank? %>
|
||||
<%= content_tag('span', link_to(plugin.url, plugin.url), :class => 'url') unless plugin.url.blank? %>
|
||||
</td>
|
||||
<td class="author"><%= plugin.author_url.blank? ? plugin.author : link_to(plugin.author, plugin.author_url) %></td>
|
||||
<td class="version"><span class="icon"><%= plugin.version %></span></td>
|
||||
<td class="configure"><%= link_to(l(:button_configure), plugin_settings_path(plugin)) if plugin.configurable? %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
<div class="autoscroll">
|
||||
<table class="list plugins">
|
||||
<% @plugins.each do |plugin| %>
|
||||
<tr id="plugin-<%= plugin.id %>">
|
||||
<td class="name"><span class="name"><%= plugin.name %></span>
|
||||
<%= content_tag('span', plugin.description, :class => 'description') unless plugin.description.blank? %>
|
||||
<%= content_tag('span', link_to(plugin.url, plugin.url), :class => 'url') unless plugin.url.blank? %>
|
||||
</td>
|
||||
<td class="author"><%= plugin.author_url.blank? ? plugin.author : link_to(plugin.author, plugin.author_url) %></td>
|
||||
<td class="version"><span class="icon"><%= plugin.version %></span></td>
|
||||
<td class="configure"><%= link_to(l(:button_configure), plugin_settings_path(plugin)) if plugin.configurable? %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
</div>
|
||||
<p><a href="#" id="check-for-updates"><%= l(:label_check_for_updates) %></a></p>
|
||||
<% else %>
|
||||
<p class="nodata"><%= l(:label_no_data) %></p>
|
||||
|
@ -27,7 +29,7 @@ $(document).ready(function(){
|
|||
dataType: "jsonp",
|
||||
url: "https://www.redmine.org/plugins/check_updates",
|
||||
data: <%= raw_json plugin_data_for_updates(@plugins) %>,
|
||||
timeout: 3000,
|
||||
timeout: 10000,
|
||||
beforeSend: function(){
|
||||
$('#ajax-indicator').show();
|
||||
},
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
<ul>
|
||||
<% @priorities.each do |p| -%>
|
||||
<li><%= context_menu_link p.name, bulk_update_issues_path(:ids => @issue_ids, :issue => {'priority_id' => p}, :back_url => @back), :method => :post,
|
||||
:selected => (@issue && p == @issue.priority), :disabled => (!@can[:edit]) %></li>
|
||||
:selected => (@issue && p == @issue.priority), :disabled => (!@can[:edit] || @issues.any?(&:priority_derived?)) %></li>
|
||||
<% end -%>
|
||||
</ul>
|
||||
</li>
|
||||
|
@ -97,7 +97,7 @@
|
|||
<ul>
|
||||
<% (0..10).map{|x|x*10}.each do |p| -%>
|
||||
<li><%= context_menu_link "#{p}%", bulk_update_issues_path(:ids => @issue_ids, :issue => {'done_ratio' => p}, :back_url => @back), :method => :post,
|
||||
:selected => (@issue && p == @issue.done_ratio), :disabled => (!@can[:edit] || @issues.detect {|i| !i.leaf?}) %></li>
|
||||
:selected => (@issue && p == @issue.done_ratio), :disabled => (!@can[:edit] || @issues.any?(&:done_ratio_derived?)) %></li>
|
||||
<% end -%>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
|
@ -6,41 +6,43 @@
|
|||
|
||||
<% delete_allowed = User.current.allowed_to?(:manage_files, @project) %>
|
||||
|
||||
<table class="list files">
|
||||
<thead><tr>
|
||||
<%= sort_header_tag('filename', :caption => l(:field_filename)) %>
|
||||
<%= sort_header_tag('created_on', :caption => l(:label_date), :default_order => 'desc') %>
|
||||
<%= sort_header_tag('size', :caption => l(:field_filesize), :default_order => 'desc') %>
|
||||
<%= sort_header_tag('downloads', :caption => l(:label_downloads_abbr), :default_order => 'desc') %>
|
||||
<th><%= l(:field_digest) %></th>
|
||||
<th></th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<% @containers.each do |container| %>
|
||||
<% next if container.attachments.empty? -%>
|
||||
<% if container.is_a?(Version) -%>
|
||||
<tr>
|
||||
<th colspan="6">
|
||||
<%= link_to(container, {:controller => 'versions', :action => 'show', :id => container}, :class => "icon icon-package") %>
|
||||
</th>
|
||||
</tr>
|
||||
<% end -%>
|
||||
<% container.attachments.each do |file| %>
|
||||
<tr class="file">
|
||||
<td class="filename"><%= link_to_attachment file, :title => file.description -%></td>
|
||||
<td class="created_on"><%= format_time(file.created_on) %></td>
|
||||
<td class="filesize"><%= number_to_human_size(file.filesize) %></td>
|
||||
<td class="downloads"><%= file.downloads %></td>
|
||||
<td class="digest"><%= file.digest_type %>: <%= file.digest %></td>
|
||||
<td class="buttons">
|
||||
<%= link_to_attachment file, class: 'icon-only icon-download', title: l(:button_download), download: true %>
|
||||
<%= link_to(l(:button_delete), attachment_path(file), :class => 'icon-only icon-del',
|
||||
:data => {:confirm => l(:text_are_you_sure)}, :method => :delete) if delete_allowed %>
|
||||
</td>
|
||||
</tr>
|
||||
<div class="autoscroll">
|
||||
<table class="list files">
|
||||
<thead><tr>
|
||||
<%= sort_header_tag('filename', :caption => l(:field_filename)) %>
|
||||
<%= sort_header_tag('created_on', :caption => l(:label_date), :default_order => 'desc') %>
|
||||
<%= sort_header_tag('size', :caption => l(:field_filesize), :default_order => 'desc') %>
|
||||
<%= sort_header_tag('downloads', :caption => l(:label_downloads_abbr), :default_order => 'desc') %>
|
||||
<th><%= l(:field_digest) %></th>
|
||||
<th></th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<% @containers.each do |container| %>
|
||||
<% next if container.attachments.empty? -%>
|
||||
<% if container.is_a?(Version) -%>
|
||||
<tr>
|
||||
<th colspan="6">
|
||||
<%= link_to(container, {:controller => 'versions', :action => 'show', :id => container}, :class => "icon icon-package") %>
|
||||
</th>
|
||||
</tr>
|
||||
<% end -%>
|
||||
<% container.attachments.each do |file| %>
|
||||
<tr class="file">
|
||||
<td class="filename"><%= link_to_attachment file, :title => file.description -%></td>
|
||||
<td class="created_on"><%= format_time(file.created_on) %></td>
|
||||
<td class="filesize"><%= number_to_human_size(file.filesize) %></td>
|
||||
<td class="downloads"><%= file.downloads %></td>
|
||||
<td class="digest"><%= file.digest_type %>: <%= file.digest %></td>
|
||||
<td class="buttons">
|
||||
<%= link_to_attachment file, class: 'icon-only icon-download', title: l(:button_download), download: true %>
|
||||
<%= link_to(l(:button_delete), attachment_path(file), :class => 'icon-only icon-del',
|
||||
:data => {:confirm => l(:text_are_you_sure)}, :method => :delete) if delete_allowed %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<% html_title(l(:label_attachment_plural)) -%>
|
||||
|
|
|
@ -2,6 +2,6 @@ $('#relations').html('<%= escape_javascript(render :partial => 'issues/relations
|
|||
<% if @relation.errors.empty? %>
|
||||
$('#relation_delay').val('');
|
||||
$('#relation_issue_to_id').val('');
|
||||
$('#relation_issue_to_id').focus();
|
||||
<% end %>
|
||||
$('#new-relation-form').show();
|
||||
$('#relation_issue_to_id').focus();
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
<% end %>
|
||||
<br />
|
||||
<span class="author"><%= authoring(changeset.committed_on, changeset.author) %></span></p>
|
||||
<div class="wiki changeset-comments"><%= format_changeset_comments changeset %></div>
|
||||
<div class="wiki changeset-comments">
|
||||
<%= format_changeset_comments changeset %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
<p><strong><%= l(:text_destroy_time_entries_question, :hours => number_with_precision(@hours, :precision => 2)) %></strong></p>
|
||||
<p>
|
||||
<label><%= radio_button_tag 'todo', 'destroy', true %> <%= l(:text_destroy_time_entries) %></label><br />
|
||||
<% unless Setting.timelog_required_fields.include?('issue_id') %>
|
||||
<label><%= radio_button_tag 'todo', 'nullify', false %> <%= l(:text_assign_time_entries_to_project) %></label><br />
|
||||
<% end %>
|
||||
<% if @project %>
|
||||
<label><%= radio_button_tag 'todo', 'reassign', false, :onchange => 'if (this.checked) { $("#reassign_to_id").focus(); }' %> <%= l(:text_reassign_time_entries) %></label>
|
||||
<%= text_field_tag 'reassign_to_id', params[:reassign_to_id], :size => 6, :onfocus => '$("#todo_reassign").attr("checked", true);' %>
|
||||
|
|
|
@ -2,31 +2,28 @@
|
|||
<html lang="<%= current_language %>">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<title><%= html_title %></title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<meta name="description" content="<%= Redmine::Info.app_name %>" />
|
||||
<meta name="keywords" content="issue,bug,tracker" />
|
||||
<%= csrf_meta_tag %>
|
||||
<%= favicon %>
|
||||
<%= stylesheet_link_tag 'jquery/jquery-ui-1.11.0', 'cookieconsent.min', 'application', 'responsive', :media => 'all' %>
|
||||
<%= stylesheet_link_tag 'jquery/jquery-ui-1.11.0', 'application', 'responsive', :media => 'all' %>
|
||||
<%= stylesheet_link_tag 'rtl', :media => 'all' if l(:direction) == 'rtl' %>
|
||||
<% is_welcome = !User.current.logged? && current_page?(:controller => 'welcome', :action => 'index') %>
|
||||
<%= stylesheet_link_tag 'frontpage', :media => 'all' if is_welcome %>
|
||||
|
||||
<%= javascript_heads %>
|
||||
<script src="/themes/circlepro/javascripts/cookieconsent.min.js"></script>
|
||||
<%= heads_for_theme %>
|
||||
<%= call_hook :view_layouts_base_html_head %>
|
||||
<!-- page specific tags -->
|
||||
<%= yield :header_tags -%>
|
||||
</head>
|
||||
<body class="<%= body_css_classes %><%= ' is-preload' if is_welcome %>">
|
||||
<body class="<%= body_css_classes %>">
|
||||
<%= call_hook :view_layouts_base_body_top %>
|
||||
<div id="wrapper">
|
||||
|
||||
<div class="flyout-menu js-flyout-menu">
|
||||
|
||||
|
||||
<% if User.current.logged? || !Setting.login_required? %>
|
||||
<div class="flyout-menu__search">
|
||||
<%= form_tag({:controller => 'search', :action => 'index', :id => @project}, :method => :get ) do %>
|
||||
|
@ -64,58 +61,45 @@
|
|||
<div id="wrapper2">
|
||||
<div id="wrapper3">
|
||||
<div id="top-menu">
|
||||
<div id="wrapper-top-menu">
|
||||
<ul class="social-menu">
|
||||
<li class="social-link-blog"><a href="https://manuel.cillero.es" title="<%= l(:link_my_blog) %>" class="icon-blog"><span><%= l(:link_my_blog) %></span></a></li>
|
||||
<li class="social-link-twitter"><a href="https://twitter.com/manuelcillero" title="Twitter" target="_blank" class="icon-twitter"><span>Twitter</span></a></li>
|
||||
<li class="social-link-facebook"><a href="https://facebook.com/manuelcillero" title="Facebook" target="_blank" class="icon-facebook"><span>Facebook</span></a></li>
|
||||
<li class="social-link-linkedin"><a href="https://es.linkedin.com/in/manuelcillero" title="Linkedin" target="_blank" class="icon-linkedin"><span>Linkedin</span></a></li>
|
||||
<li class="social-link-gitlab"><a href="https://gitlab.com/manuelcillero" title="Gitlab" target="_blank" class="icon-gitlab"><span>Gitlab</span></a></li>
|
||||
<li class="social-link-mail"><a href="https://manuel.cillero.es/contacto/#suitepro" title="Mail" class="icon-mail"><span>Mail</span></a></li>
|
||||
</ul>
|
||||
<div id="account">
|
||||
<%= render_menu :account_menu -%>
|
||||
</div>
|
||||
<%= content_tag('div', "#{l(:label_logged_as)} #{link_to_user(User.current, :format => :username)}".html_safe, :id => 'loggedas') if User.current.logged? %>
|
||||
<%= render_menu :top_menu if User.current.logged? || !Setting.login_required? -%>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="header">
|
||||
|
||||
<a href="#" class="mobile-toggle-button js-flyout-menu-toggle-button"></a>
|
||||
|
||||
<div id="wrapper-header">
|
||||
<% if User.current.logged? || !Setting.login_required? %>
|
||||
<div id="quick-search" class="hide-when-print">
|
||||
<div id="quick-search">
|
||||
<%= form_tag({:controller => 'search', :action => 'index', :id => @project}, :method => :get ) do %>
|
||||
<%= hidden_field_tag 'scope', default_search_project_scope, :id => nil %>
|
||||
<%= hidden_field_tag(controller.default_search_scope, 1, :id => nil) if controller.default_search_scope %>
|
||||
<label for='q'>
|
||||
<%= link_to l(:label_search), {:controller => 'search', :action => 'index', :id => @project}, :accesskey => accesskey(:search) %>:
|
||||
<%= link_to l(:label_search), {:controller => 'search', :action => 'index', :id => @project, :scope => default_search_project_scope}, :accesskey => accesskey(:search) %>:
|
||||
</label>
|
||||
<%= text_field_tag 'q', @question, :size => 20, :class => 'small', :accesskey => accesskey(:quick_search) %>
|
||||
<% end %>
|
||||
<%= render_project_jump_box %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<h1><%= page_header_title %></h1>
|
||||
</div>
|
||||
|
||||
|
||||
<% if display_main_menu?(@project) %>
|
||||
<div id="main-menu" class="tabs">
|
||||
<div id="wrapper-main-menu">
|
||||
<%= render_main_menu(@project) %>
|
||||
<div class="tabs-buttons" style="display:none;">
|
||||
<button class="tab-left" onclick="moveTabLeft(this); return false;"></button>
|
||||
<button class="tab-right" onclick="moveTabRight(this); return false;"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div id="main" class="<%= sidebar_content? ? '' : 'nosidebar' %>">
|
||||
<div id="wrapper-main">
|
||||
<div id="sidebar">
|
||||
<%= yield :sidebar %>
|
||||
<%= view_layouts_base_sidebar_hook_response %>
|
||||
|
@ -127,51 +111,19 @@
|
|||
<%= call_hook :view_layouts_base_content %>
|
||||
<div style="clear:both;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="#" id="scrollup" class="hide-when-print"><%=l(:label_sort_higher)%></a><%= javascript_tag "$('#scrollup').click(function(){$('html,body').animate({scrollTop:0},600);return false;});" %>
|
||||
|
||||
<div id="ajax-indicator" style="display:none;"><span><%= l(:label_loading) %></span></div>
|
||||
<div id="ajax-modal" style="display:none;"></div>
|
||||
|
||||
<div id="footer">
|
||||
<div id="wrapper-footer">
|
||||
<ul class="social-menu">
|
||||
<li class="social-link-blog"><a href="https://manuel.cillero.es" title="<%= l(:link_my_blog) %>" class="icon-blog"><span><%= l(:link_my_blog) %></span></a></li>
|
||||
<li class="social-link-twitter"><a href="https://twitter.com/manuelcillero" title="Twitter" target="_blank" class="icon-twitter"><span>Twitter</span></a></li>
|
||||
<li class="social-link-facebook"><a href="https://facebook.com/manuelcillero" title="Facebook" target="_blank" class="icon-facebook"><span>Facebook</span></a></li>
|
||||
<li class="social-link-linkedin"><a href="https://es.linkedin.com/in/manuelcillero" title="Linkedin" target="_blank" class="icon-linkedin"><span>Linkedin</span></a></li>
|
||||
<li class="social-link-gitlab"><a href="https://gitlab.com/manuelcillero" title="Gitlab" target="_blank" class="icon-gitlab"><span>Gitlab</span></a></li>
|
||||
<li class="social-link-mail"><a href="https://manuel.cillero.es/contacto/#suitepro" title="Mail" class="icon-mail"><span>Mail</span></a></li>
|
||||
</ul>
|
||||
<div class="bgl"><div class="bgr">
|
||||
<div id="legal">
|
||||
<span class="legal-legal"><a href="/projects/suitepro/wiki/Legal"><%= l(:label_legal) %></a></span>
|
||||
<span class="legal-terms"> | <a href="/projects/suitepro/wiki/Condiciones_de_uso"><%= l(:label_legal_terms) %></a></span>
|
||||
<span class="legal-privacy"> | <a href="/projects/suitepro/wiki/Política_de_privacidad"><%= l(:label_legal_privacy) %></a></span>
|
||||
<span class="legal-cookies"> | <a href="/projects/suitepro/wiki/Política_de_cookies"><%= l(:label_legal_cookies) %></a></span>
|
||||
</div>
|
||||
<%= Time.current.year %> © SuitePro (powered by <%= link_to Redmine::Info.app_name, Redmine::Info.url %>)
|
||||
</div></div>
|
||||
</div>
|
||||
<div class="bgl"><div class="bgr">
|
||||
Powered by <%= link_to Redmine::Info.app_name, Redmine::Info.url %> © 2006-2019 Jean-Philippe Lang
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%= call_hook :view_layouts_base_body_bottom %>
|
||||
|
||||
<script>
|
||||
//<![CDATA[
|
||||
window.addEventListener("load", function(){
|
||||
window.cookieconsent.initialise({
|
||||
"palette": { "popup": { "background": "rgba(20,20,20,0.8)" }, "button": { "background": "#fff" } },
|
||||
"theme": "classic",
|
||||
"position": "bottom-left",
|
||||
"content": { "message": "<a href='https://suitepro.cillero.es'>SuitePro</a> requiere el uso de cookies para ofrecer la mejor experiencia de acceso a sus contenidos. Puedes aceptar su uso o abandonar la página si lo deseas.", "dismiss": "ACEPTO SU USO", "link": "Más información", "href": "/projects/suitepro/wiki/Pol%C3%ADtica_de_cookies", "target": "_self" }
|
||||
})});
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<%= content_tag :h1, @title -%>
|
||||
<% end %></p>
|
||||
|
||||
<p><%= l(:field_user) %>: <strong><%= User.current.login %></strong><br/>
|
||||
<%= l(:field_remote_ip) %>: <strong><%= User.current.remote_ip %></strong><br/>
|
||||
<p><%= l(:field_user) %>: <strong><%= @originator.login %></strong><br/>
|
||||
<%= l(:field_remote_ip) %>: <strong><%= @remote_ip %></strong><br/>
|
||||
<%= l(:label_date) %>: <strong><%= format_time Time.now, true, @user %></strong></p>
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<%= @url || @title %>
|
||||
|
||||
<%= l(:field_user) %>: <%= User.current.login %>
|
||||
<%= l(:field_remote_ip) %>: <%= User.current.remote_ip %>
|
||||
<%= l(:field_user) %>: <%= @originator.login %>
|
||||
<%= l(:field_remote_ip) %>: <%= @remote_ip %>
|
||||
<%= l(:label_date) %>: <%= format_time Time.now, true, @user %>
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="box">
|
||||
<legend><%= l(:label_role_plural) %> <%= toggle_checkboxes_link('.roles-selection input') %></legend>
|
||||
<legend><%= toggle_checkboxes_link('.roles-selection input') %><%= l(:label_role_plural) %></legend>
|
||||
<div class="roles-selection">
|
||||
<% User.current.managed_roles(@project).each do |role| %>
|
||||
<label><%= check_box_tag 'membership[role_ids][]', role.id, false, :id => nil %> <%= role %></label>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<fieldset class="box">
|
||||
<legend><%= l(:label_project_plural) %> <%= toggle_checkboxes_link('.projects-selection input:enabled') %></legend>
|
||||
<legend><%= toggle_checkboxes_link('.projects-selection input:enabled') %><%= l(:label_project_plural) %></legend>
|
||||
<div class="objects-selection">
|
||||
<div class="projects-selection">
|
||||
<%= render_project_nested_lists(@projects) do |p| %>
|
||||
|
@ -12,7 +12,7 @@
|
|||
</fieldset>
|
||||
|
||||
<fieldset class="box">
|
||||
<legend><%= l(:label_role_plural) %> <%= toggle_checkboxes_link('.roles-selection input') %></legend>
|
||||
<legend><%= toggle_checkboxes_link('.roles-selection input') %><%= l(:label_role_plural) %></legend>
|
||||
<div class="roles-selection">
|
||||
<% @roles.each do |role| %>
|
||||
<label>
|
||||
|
|
|
@ -3,39 +3,41 @@
|
|||
<% end %>
|
||||
|
||||
<% if @project.repositories.any? %>
|
||||
<table class="list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><%= l(:field_identifier) %></th>
|
||||
<th><%= l(:field_repository_is_default) %></th>
|
||||
<th><%= l(:label_scm) %></th>
|
||||
<th><%= l(:label_repository) %></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @project.repositories.sort.each do |repository| %>
|
||||
<tr>
|
||||
<td class="name">
|
||||
<%= link_to repository.identifier,
|
||||
{:controller => 'repositories', :action => 'show',:id => @project, :repository_id => repository.identifier_param} if repository.identifier.present? %>
|
||||
</td>
|
||||
<td><%= checked_image repository.is_default? %></td>
|
||||
<td><%= repository.scm_name %></td>
|
||||
<td><%= repository.url %></td>
|
||||
<td class="buttons">
|
||||
<% if User.current.allowed_to?(:manage_repository, @project) %>
|
||||
<%= link_to(l(:label_user_plural), committers_repository_path(repository),
|
||||
:class => 'icon icon-user') %>
|
||||
<%= link_to(l(:button_edit), edit_repository_path(repository),
|
||||
:class => 'icon icon-edit') %>
|
||||
<%= delete_link repository_path(repository) %>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="autoscroll">
|
||||
<table class="list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><%= l(:field_identifier) %></th>
|
||||
<th><%= l(:field_repository_is_default) %></th>
|
||||
<th><%= l(:label_scm) %></th>
|
||||
<th><%= l(:label_repository) %></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @project.repositories.sort.each do |repository| %>
|
||||
<tr>
|
||||
<td class="name">
|
||||
<%= link_to repository.identifier,
|
||||
{:controller => 'repositories', :action => 'show',:id => @project, :repository_id => repository.identifier_param} if repository.identifier.present? %>
|
||||
</td>
|
||||
<td><%= checked_image repository.is_default? %></td>
|
||||
<td><%= repository.scm_name %></td>
|
||||
<td><%= repository.url %></td>
|
||||
<td class="buttons">
|
||||
<% if User.current.allowed_to?(:manage_repository, @project) %>
|
||||
<%= link_to(l(:label_user_plural), committers_repository_path(repository),
|
||||
:class => 'icon icon-user') %>
|
||||
<%= link_to(l(:button_edit), edit_repository_path(repository),
|
||||
:class => 'icon icon-edit') %>
|
||||
<%= delete_link repository_path(repository) %>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<% else %>
|
||||
<p class="nodata"><%= l(:label_no_data) %></p>
|
||||
<% end %>
|
||||
|
|
|
@ -33,7 +33,9 @@
|
|||
|
||||
</div>
|
||||
|
||||
<div class="wiki changeset-comments"><%= format_changeset_comments @changeset %></div>
|
||||
<div class="wiki changeset-comments">
|
||||
<%= format_changeset_comments @changeset %>
|
||||
</div>
|
||||
|
||||
<% if @changeset.issues.visible.any? || User.current.allowed_to?(:manage_related_issues, @repository.project) %>
|
||||
<%= render :partial => 'related_issues' %>
|
||||
|
|
|
@ -21,10 +21,11 @@
|
|||
</p>
|
||||
<%= hidden_field_tag 'tracker[core_fields][]', '' %>
|
||||
|
||||
<% if IssueCustomField.all.any? %>
|
||||
<% @issue_custom_fields = IssueCustomField.sorted %>
|
||||
<% if @issue_custom_fields.present? %>
|
||||
<p>
|
||||
<label><%= l(:label_custom_field_plural) %></label>
|
||||
<% IssueCustomField.all.each do |field| %>
|
||||
<% @issue_custom_fields.each do |field| %>
|
||||
<label class="block">
|
||||
<%= check_box_tag 'tracker[custom_field_ids][]',field.id, @tracker.custom_fields.to_a.include?(field), :id => nil %>
|
||||
<%= field.name %>
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
<% if User.current.logged? %>
|
||||
|
||||
<h2><%= l(:label_home) %></h2>
|
||||
|
||||
<div class="splitcontentleft">
|
||||
|
@ -26,149 +24,3 @@
|
|||
<%= auto_discovery_link_tag(:atom, {:controller => 'activities', :action => 'index', :key => User.current.rss_key, :format => 'atom'},
|
||||
:title => "#{Setting.app_title}: #{l(:label_activity)}") %>
|
||||
<% end %>
|
||||
|
||||
<% else %><!-- Frontpage -->
|
||||
|
||||
<div id="fp"><%= text_field_tag 'forcetop', nil, :style => 'display: none;' %>
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="fp-banner">
|
||||
<div class="inner">
|
||||
<h2>SuitePro</h2>
|
||||
<p><%= l(:welcome_suitepro) %></p>
|
||||
<ul class="actions special">
|
||||
<li><a href="#fp-login" class="button primary scrolly"><%= l(:label_login) %></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a href="#one" class="more scrolly"><%= l(:welcome_discover) %></a>
|
||||
</section>
|
||||
|
||||
<!-- One -->
|
||||
<section id="one" class="frapper style1 special">
|
||||
<div class="inner">
|
||||
<header class="major">
|
||||
<h2>A SIMPLE WAY TO GET WORK DONE ;)</h2>
|
||||
<p><%= raw l(:welcome_suitepro_is_redmine, :suitepro => '<strong>SuitePro</strong>', :redmine => '<a href="https://www.redmine.org"><strong>Redmine</strong></a>') %></p>
|
||||
</header>
|
||||
<ul class="icons major">
|
||||
<li><span class="fp-icon fp-icon_1 major style1"><span class="label">Lorem</span></span></li>
|
||||
<li><span class="fp-icon fp-icon_2 major style2"><span class="label">Ipsum</span></span></li>
|
||||
<li><span class="fp-icon fp-icon_3 major style3"><span class="label">Dolor</span></span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Two -->
|
||||
<section id="two" class="frapper alt style2">
|
||||
<section class="spotlight">
|
||||
<div class="image"><%= image_tag '/themes/circlepro/images/pic01.jpg' %></div><div class="content">
|
||||
<h2><%= raw l(:welcome_spotlight_1_title) %></h2>
|
||||
<p><%= l(:welcome_spotlight_1_text) %></p>
|
||||
</div>
|
||||
</section>
|
||||
<section class="spotlight">
|
||||
<div class="image"><%= image_tag '/themes/circlepro/images/pic02.jpg' %></div><div class="content">
|
||||
<h2><%= raw l(:welcome_spotlight_2_title) %></h2>
|
||||
<p><%= l(:welcome_spotlight_2_text) %></p>
|
||||
</div>
|
||||
</section>
|
||||
<section class="spotlight">
|
||||
<div class="image"><%= image_tag '/themes/circlepro/images/pic03.jpg' %></div><div class="content">
|
||||
<h2><%= raw l(:welcome_spotlight_3_title) %></h2>
|
||||
<p><%= l(:welcome_spotlight_3_text) %></p>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<!-- Three -->
|
||||
<section id="three" class="frapper style3 special">
|
||||
<div class="inner">
|
||||
<header class="major">
|
||||
<h2><%= l(:welcome_other_features) %></h2>
|
||||
</header>
|
||||
<ul class="features">
|
||||
<li class="fp-icon fp-icon_4">
|
||||
<h3><%= l(:welcome_feature_1_title) %></h3>
|
||||
<p><%= l(:welcome_feature_1_text) %></p>
|
||||
</li>
|
||||
<li class="fp-icon fp-icon_5">
|
||||
<h3><%= l(:welcome_feature_2_title) %></h3>
|
||||
<p><%= l(:welcome_feature_2_text) %></p>
|
||||
</li>
|
||||
<li class="fp-icon fp-icon_6">
|
||||
<h3><%= l(:welcome_feature_3_title) %></h3>
|
||||
<p><%= l(:welcome_feature_3_text) %></p>
|
||||
</li>
|
||||
<li class="fp-icon fp-icon_7">
|
||||
<h3><%= l(:welcome_feature_4_title) %></h3>
|
||||
<p><%= l(:welcome_feature_4_text) %></p>
|
||||
</li>
|
||||
<li class="fp-icon fp-icon_8">
|
||||
<h3><%= l(:welcome_feature_5_title) %></h3>
|
||||
<p><%= l(:welcome_feature_5_text) %></p>
|
||||
</li>
|
||||
<li class="fp-icon fp-icon_9">
|
||||
<h3><%= l(:welcome_feature_6_title) %></h3>
|
||||
<p><%= l(:welcome_feature_6_text) %></p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Login -->
|
||||
<section id="fp-login" class="frapper style4">
|
||||
<div class="inner">
|
||||
<%= call_hook :view_account_login_top %>
|
||||
|
||||
<div id="login-form">
|
||||
<h2><%= l(:label_login) %></h2>
|
||||
<%= form_tag(signin_path, onsubmit: 'return keepAnchorOnSignIn(this);') do %>
|
||||
<%= back_url_hidden_field_tag %>
|
||||
|
||||
<label for="username"><%=l(:field_login)%></label>
|
||||
<%= text_field_tag 'username', params[:username], :tabindex => '1' %>
|
||||
|
||||
<label for="password">
|
||||
<%=l(:field_password)%>
|
||||
<%= link_to l(:label_password_lost), lost_password_path, :class => "lost_password" if Setting.lost_password? %>
|
||||
</label>
|
||||
<%= password_field_tag 'password', nil, :tabindex => '2' %>
|
||||
|
||||
<% if Setting.openid? %>
|
||||
<label for="openid_url"><%=l(:field_identity_url)%></label>
|
||||
<%= text_field_tag "openid_url", nil, :tabindex => '3' %>
|
||||
<% end %>
|
||||
|
||||
<% if Setting.autologin? %>
|
||||
<label for="autologin"><%= check_box_tag 'autologin', 1, false, :tabindex => 4 %> <%= l(:label_stay_logged_in) %></label>
|
||||
<% end %>
|
||||
|
||||
<input type="submit" name="login" value="<%=l(:button_login)%>" tabindex="5" id="login-submit" />
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA -->
|
||||
<section id="fp-cta" class="frapper style4">
|
||||
<div class="inner">
|
||||
<header>
|
||||
<h2><%= l(:welcome_any_questions) %></h2>
|
||||
<p><%= l(:welcome_please_contact) %></p>
|
||||
</header>
|
||||
<ul class="actions stacked">
|
||||
<li><a href="https://manuel.cillero.es/contacto/#suitepro" class="button fit primary"><%= l(:welcome_contact) %></a></li>
|
||||
<li><a href="https://manuel.cillero.es/sobre-mi" class="button fit"><%= l(:welcome_about_me) %></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="/themes/circlepro/javascripts/frontpage/jquery.scrolly.min.js"></script>
|
||||
<script src="/themes/circlepro/javascripts/frontpage/browser.min.js"></script>
|
||||
<script src="/themes/circlepro/javascripts/frontpage/breakpoints.min.js"></script>
|
||||
<script src="/themes/circlepro/javascripts/frontpage/util.js"></script>
|
||||
<script src="/themes/circlepro/javascripts/frontpage/main.js"></script>
|
||||
|
||||
<% end %>
|
||||
|
|
|
@ -46,8 +46,7 @@
|
|||
|
||||
<%= render(:partial => "wiki/content", :locals => {:content => @content}) %>
|
||||
|
||||
<% if @page.attachments.length > 0 || (@editable && authorize_for('wiki', 'add_attachment')) %>
|
||||
<fieldset class="collapsible collapsed<% if @page.attachments.length == 0 %> hide-when-print<% end %>">
|
||||
<fieldset class="collapsible collapsed hide-when-print">
|
||||
<legend onclick="toggleFieldset(this);"><%= l(:label_attachment_plural) %> (<%= @page.attachments.length %>)</legend>
|
||||
<div style="display: none;">
|
||||
|
||||
|
@ -67,7 +66,6 @@
|
|||
<% end %>
|
||||
</div>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<% other_formats_links do |f| %>
|
||||
<%= f.link_to 'PDF', :url => {:id => @page.title, :version => params[:version]} %>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue