# HG changeset patch
# User luisf
# Date 1357735299 0
# Node ID 9b2f28ecd1252eb7a792b0f79cbd55f94895a381
# Parent 2681af99688fb45691a437c6bda0b07c3f89299f
RedmineTags plugin: merged exiting with the most up-to-date version from the repo.
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/Gemfile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/redmine_tags/Gemfile Wed Jan 09 12:41:39 2013 +0000
@@ -0,0 +1,1 @@
+gem "acts-as-taggable-on", "2.3.3"
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/HISTORY.md
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/redmine_tags/HISTORY.md Wed Jan 09 12:41:39 2013 +0000
@@ -0,0 +1,4 @@
+## 2.0.1 (unreleased)
+
+- Added Simplified Chinese translation. Thanks to archonwang.
+- Added Bulgarian translation. Thanks to Ivan Cenov.
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/README.md
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/redmine_tags/README.md Wed Jan 09 12:41:39 2013 +0000
@@ -0,0 +1,41 @@
+Redmine Tags
+============
+
+Allows marking up different models in Redmine with tags.
+Inspired by original redmine\_tags of Eric Davis.
+
+
+Supported models
+----------------
+
+- Issues
+
+
+Requirements
+------------
+
+- Redmine `>= 2.1.0`
+- acts-as-taggable-on `= 2.3.3`
+
+
+Installation
+------------
+
+- Clone this repository into `redmine/plugins/redmine_tags`
+- Install dependencies and migrate database:
+
+ cd redmine/
+ bundle install
+ RAILS_ENV=production rails generate acts_as_taggable_on:migration
+ RAILS_ENV=production rake db:migrate
+ RAILS_ENV=production rake redmine:plugins:migrate
+
+- Restart your Redmine web server (e.g. mongrel, thin, mod\_rails)
+
+
+License
+-------
+
+This plugin is licensed under the terms of GNU/GPL v3+.
+See COPYING and LICENSE for details.
+
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/app/helpers/issues_helper.rb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/redmine_tags/app/helpers/issues_helper.rb Wed Jan 09 12:41:39 2013 +0000
@@ -0,0 +1,42 @@
+# This file is a part of redmine_tags
+# redMine plugin, that adds tagging support.
+#
+# Copyright (c) 2010 Aleksey V Zapparov AKA ixti
+#
+# redmine_tags is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# redmine_tags is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with redmine_tags. If not, see .
+
+module IssuesHelper
+ include TagsHelper
+
+ def sidebar_tags
+ unless @sidebar_tags
+ @sidebar_tags = []
+ if :none != RedmineTags.settings[:issues_sidebar].to_sym
+ @sidebar_tags = Issue.available_tags({
+ :project => @project,
+ :open_only => (RedmineTags.settings[:issues_open_only].to_i == 1)
+ })
+ end
+ end
+ @sidebar_tags
+ end
+
+ def render_sidebar_tags
+ render_tags_list(sidebar_tags, {
+ :show_count => (RedmineTags.settings[:issues_show_count].to_i == 1),
+ :open_only => (RedmineTags.settings[:issues_open_only].to_i == 1),
+ :style => RedmineTags.settings[:issues_sidebar].to_sym
+ })
+ end
+end
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/app/helpers/tags_helper.rb
--- a/plugins/redmine_tags/app/helpers/tags_helper.rb Wed Jan 09 11:53:24 2013 +0000
+++ b/plugins/redmine_tags/app/helpers/tags_helper.rb Wed Jan 09 12:41:39 2013 +0000
@@ -63,8 +63,21 @@
def render_tags_list(tags, options = {})
unless tags.nil? or tags.empty?
content, style = '', options.delete(:style)
-
- tags.sort! { |a,b| b.count <=> a.count }
+
+ # prevent ActsAsTaggableOn::TagsHelper from calling `all`
+ # otherwise we will need sort tags after `tag_cloud`
+ tags = tags.all if tags.respond_to?(:all)
+
+ case sorting = "#{RedmineTags.settings[:issues_sort_by]}:#{RedmineTags.settings[:issues_sort_order]}"
+ when "name:asc"; tags.sort! { |a,b| a.name <=> b.name }
+ when "name:desc"; tags.sort! { |a,b| b.name <=> a.name }
+ when "count:asc"; tags.sort! { |a,b| a.count <=> b.count }
+ when "count:desc"; tags.sort! { |a,b| b.count <=> a.count }
+ # Unknown sorting option. Fallback to default one
+ else
+ logger.warn "[redmine_tags] Unknown sorting option: <#{sorting}>"
+ tags.sort! { |a,b| a.name <=> b.name }
+ end
if :list == style
list_el, item_el = 'ul', 'li'
@@ -75,8 +88,9 @@
raise "Unknown list style"
end
+ content = content.html_safe
tag_cloud tags, (1..8).to_a do |tag, weight|
- content << " " + content_tag(item_el, render_project_tag_link(tag, options), :class => "tag-nube-#{weight}") + " "
+ content << " ".html_safe + content_tag(item_el, render_tag_link(tag, options), :class => "tag-nube-#{weight}") + " ".html_safe
end
content_tag(list_el, content, :class => 'tags')
@@ -84,7 +98,8 @@
end
private
- # put most massive tags in the middle
+
+ # make snowball. first tags comes in th middle.
def cloudify(tags)
temp, tags, trigger = tags, [], true
temp.each do |tag|
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/app/views/auto_completes/_tag_list.html.erb
--- a/plugins/redmine_tags/app/views/auto_completes/_tag_list.html.erb Wed Jan 09 11:53:24 2013 +0000
+++ b/plugins/redmine_tags/app/views/auto_completes/_tag_list.html.erb Wed Jan 09 12:41:39 2013 +0000
@@ -1,6 +1,4 @@
-
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/assets/javascripts/tag-it.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/redmine_tags/assets/javascripts/tag-it.js Wed Jan 09 12:41:39 2013 +0000
@@ -0,0 +1,392 @@
+/*
+* jQuery UI Tag-it!
+*
+* @version v2.0 (06/2011)
+*
+* Copyright 2011, Levy Carneiro Jr.
+* Released under the MIT license.
+* http://aehlke.github.com/tag-it/LICENSE
+*
+* Homepage:
+* http://aehlke.github.com/tag-it/
+*
+* Authors:
+* Levy Carneiro Jr.
+* Martin Rehfeld
+* Tobias Schmidt
+* Skylar Challand
+* Alex Ehlke
+*
+* Maintainer:
+* Alex Ehlke - Twitter: @aehlke
+*
+* Dependencies:
+* jQuery v1.4+
+* jQuery UI v1.8+
+*/
+(function($) {
+
+ $.widget('ui.tagit', {
+ options: {
+ itemName : 'item',
+ fieldName : 'tags',
+ availableTags : [],
+ tagSource : null,
+ removeConfirmation: false,
+ caseSensitive : true,
+ placeholderText : null,
+
+ // When enabled, quotes are not neccesary
+ // for inputting multi-word tags.
+ allowSpaces: false,
+
+ // Whether to animate tag removals or not.
+ animate: true,
+
+ // The below options are for using a single field instead of several
+ // for our form values.
+ //
+ // When enabled, will use a single hidden field for the form,
+ // rather than one per tag. It will delimit tags in the field
+ // with singleFieldDelimiter.
+ //
+ // The easiest way to use singleField is to just instantiate tag-it
+ // on an INPUT element, in which case singleField is automatically
+ // set to true, and singleFieldNode is set to that element. This
+ // way, you don't need to fiddle with these options.
+ singleField: false,
+
+ singleFieldDelimiter: ',',
+
+ // Set this to an input DOM node to use an existing form field.
+ // Any text in it will be erased on init. But it will be
+ // populated with the text of tags as they are created,
+ // delimited by singleFieldDelimiter.
+ //
+ // If this is not set, we create an input node for it,
+ // with the name given in settings.fieldName,
+ // ignoring settings.itemName.
+ singleFieldNode: null,
+
+ // Optionally set a tabindex attribute on the input that gets
+ // created for tag-it.
+ tabIndex: null,
+
+
+ // Event callbacks.
+ onTagAdded : null,
+ onTagRemoved: null,
+ onTagClicked: null
+ },
+
+
+ _create: function() {
+ // for handling static scoping inside callbacks
+ var that = this;
+
+ // There are 2 kinds of DOM nodes this widget can be instantiated on:
+ // 1. UL, OL, or some element containing either of these.
+ // 2. INPUT, in which case 'singleField' is overridden to true,
+ // a UL is created and the INPUT is hidden.
+ if (this.element.is('input')) {
+ this.tagList = $('
').insertAfter(this.element);
+ this.options.singleField = true;
+ this.options.singleFieldNode = this.element;
+ this.element.css('display', 'none');
+ } else {
+ this.tagList = this.element.find('ul, ol').andSelf().last();
+ }
+
+ this._tagInput = $('').addClass('ui-widget-content');
+ if (this.options.tabIndex) {
+ this._tagInput.attr('tabindex', this.options.tabIndex);
+ }
+ if (this.options.placeholderText) {
+ this._tagInput.attr('placeholder', this.options.placeholderText);
+ }
+
+ this.options.tagSource = this.options.tagSource || function(search, showChoices) {
+ var filter = search.term.toLowerCase();
+ var choices = $.grep(this.options.availableTags, function(element) {
+ // Only match autocomplete options that begin with the search term.
+ // (Case insensitive.)
+ return (element.toLowerCase().indexOf(filter) === 0);
+ });
+ showChoices(this._subtractArray(choices, this.assignedTags()));
+ };
+
+ // Bind tagSource callback functions to this context.
+ if ($.isFunction(this.options.tagSource)) {
+ this.options.tagSource = $.proxy(this.options.tagSource, this);
+ }
+
+ this.tagList
+ .addClass('tagit')
+ .addClass('ui-widget ui-widget-content ui-corner-all')
+ // Create the input field.
+ .append($('').append(this._tagInput))
+ .click(function(e) {
+ var target = $(e.target);
+ if (target.hasClass('tagit-label')) {
+ that._trigger('onTagClicked', e, target.closest('.tagit-choice'));
+ } else {
+ // Sets the focus() to the input field, if the user
+ // clicks anywhere inside the UL. This is needed
+ // because the input field needs to be of a small size.
+ that._tagInput.focus();
+ }
+ });
+
+ // Add existing tags from the list, if any.
+ this.tagList.children('li').each(function() {
+ if (!$(this).hasClass('tagit-new')) {
+ that.createTag($(this).html(), $(this).attr('class'));
+ $(this).remove();
+ }
+ });
+
+ // Single field support.
+ if (this.options.singleField) {
+ if (this.options.singleFieldNode) {
+ // Add existing tags from the input field.
+ var node = $(this.options.singleFieldNode);
+ var tags = node.val().split(this.options.singleFieldDelimiter);
+ node.val('');
+ $.each(tags, function(index, tag) {
+ that.createTag(tag);
+ });
+ } else {
+ // Create our single field input after our list.
+ this.options.singleFieldNode = this.tagList.after('');
+ }
+ }
+
+ // Events.
+ this._tagInput
+ .keydown(function(event) {
+ // Backspace is not detected within a keypress, so it must use keydown.
+ if (event.which == $.ui.keyCode.BACKSPACE && that._tagInput.val() === '') {
+ var tag = that._lastTag();
+ if (!that.options.removeConfirmation || tag.hasClass('remove')) {
+ // When backspace is pressed, the last tag is deleted.
+ that.removeTag(tag);
+ } else if (that.options.removeConfirmation) {
+ tag.addClass('remove ui-state-highlight');
+ }
+ } else if (that.options.removeConfirmation) {
+ that._lastTag().removeClass('remove ui-state-highlight');
+ }
+
+ // Comma/Space/Enter are all valid delimiters for new tags,
+ // except when there is an open quote or if setting allowSpaces = true.
+ // Tab will also create a tag, unless the tag input is empty, in which case it isn't caught.
+ if (
+ event.which == $.ui.keyCode.COMMA ||
+ event.which == $.ui.keyCode.ENTER ||
+ (
+ event.which == $.ui.keyCode.TAB &&
+ that._tagInput.val() !== ''
+ ) ||
+ (
+ event.which == $.ui.keyCode.SPACE &&
+ that.options.allowSpaces !== true &&
+ (
+ $.trim(that._tagInput.val()).replace( /^s*/, '' ).charAt(0) != '"' ||
+ (
+ $.trim(that._tagInput.val()).charAt(0) == '"' &&
+ $.trim(that._tagInput.val()).charAt($.trim(that._tagInput.val()).length - 1) == '"' &&
+ $.trim(that._tagInput.val()).length - 1 !== 0
+ )
+ )
+ )
+ ) {
+ event.preventDefault();
+ that.createTag(that._cleanedInput());
+
+ // The autocomplete doesn't close automatically when TAB is pressed.
+ // So let's ensure that it closes.
+ that._tagInput.autocomplete('close');
+ }
+ }).blur(function(e){
+ // Create a tag when the element loses focus (unless it's empty).
+ that.createTag(that._cleanedInput());
+ });
+
+
+ // Autocomplete.
+ if (this.options.availableTags || this.options.tagSource) {
+ this._tagInput.autocomplete({
+ source: this.options.tagSource,
+ select: function(event, ui) {
+ // Delete the last tag if we autocomplete something despite the input being empty
+ // This happens because the input's blur event causes the tag to be created when
+ // the user clicks an autocomplete item.
+ // The only artifact of this is that while the user holds down the mouse button
+ // on the selected autocomplete item, a tag is shown with the pre-autocompleted text,
+ // and is changed to the autocompleted text upon mouseup.
+ if (that._tagInput.val() === '') {
+ that.removeTag(that._lastTag(), false);
+ }
+ that.createTag(ui.item.value);
+ // Preventing the tag input to be updated with the chosen value.
+ return false;
+ }
+ });
+ }
+ },
+
+ _cleanedInput: function() {
+ // Returns the contents of the tag input, cleaned and ready to be passed to createTag
+ return $.trim(this._tagInput.val().replace(/^"(.*)"$/, '$1'));
+ },
+
+ _lastTag: function() {
+ return this.tagList.children('.tagit-choice:last');
+ },
+
+ assignedTags: function() {
+ // Returns an array of tag string values
+ var that = this;
+ var tags = [];
+ if (this.options.singleField) {
+ tags = $(this.options.singleFieldNode).val().split(this.options.singleFieldDelimiter);
+ if (tags[0] === '') {
+ tags = [];
+ }
+ } else {
+ this.tagList.children('.tagit-choice').each(function() {
+ tags.push(that.tagLabel(this));
+ });
+ }
+ return tags;
+ },
+
+ _updateSingleTagsField: function(tags) {
+ // Takes a list of tag string values, updates this.options.singleFieldNode.val to the tags delimited by this.options.singleFieldDelimiter
+ $(this.options.singleFieldNode).val(tags.join(this.options.singleFieldDelimiter));
+ },
+
+ _subtractArray: function(a1, a2) {
+ var result = [];
+ for (var i = 0; i < a1.length; i++) {
+ if ($.inArray(a1[i], a2) == -1) {
+ result.push(a1[i]);
+ }
+ }
+ return result;
+ },
+
+ tagLabel: function(tag) {
+ // Returns the tag's string label.
+ if (this.options.singleField) {
+ return $(tag).children('.tagit-label').text();
+ } else {
+ return $(tag).children('input').val();
+ }
+ },
+
+ _isNew: function(value) {
+ var that = this;
+ var isNew = true;
+ this.tagList.children('.tagit-choice').each(function(i) {
+ if (that._formatStr(value) == that._formatStr(that.tagLabel(this))) {
+ isNew = false;
+ return false;
+ }
+ });
+ return isNew;
+ },
+
+ _formatStr: function(str) {
+ if (this.options.caseSensitive) {
+ return str;
+ }
+ return $.trim(str.toLowerCase());
+ },
+
+ createTag: function(value, additionalClass) {
+ var that = this;
+ // Automatically trims the value of leading and trailing whitespace.
+ value = $.trim(value);
+
+ if (!this._isNew(value) || value === '') {
+ return false;
+ }
+
+ var label = $(this.options.onTagClicked ? '' : '').text(value);
+
+ // Create tag.
+ var tag = $('')
+ .addClass('tagit-choice ui-widget-content ui-state-default ui-corner-all')
+ .addClass(additionalClass)
+ .append(label);
+
+ // Button for removing the tag.
+ var removeTagIcon = $('')
+ .addClass('ui-icon ui-icon-close');
+ var removeTag = $('\xd7') // \xd7 is an X
+ .addClass('tagit-close')
+ .append(removeTagIcon)
+ .click(function(e) {
+ // Removes a tag when the little 'x' is clicked.
+ that.removeTag(tag);
+ });
+ tag.append(removeTag);
+
+ // Unless options.singleField is set, each tag has a hidden input field inline.
+ if (this.options.singleField) {
+ var tags = this.assignedTags();
+ tags.push(value);
+ this._updateSingleTagsField(tags);
+ } else {
+ var escapedValue = label.html();
+ tag.append('');
+ }
+
+ this._trigger('onTagAdded', null, tag);
+
+ // Cleaning the input.
+ this._tagInput.val('');
+
+ // insert tag
+ this._tagInput.parent().before(tag);
+ },
+
+ removeTag: function(tag, animate) {
+ animate = animate || this.options.animate;
+
+ tag = $(tag);
+
+ this._trigger('onTagRemoved', null, tag);
+
+ if (this.options.singleField) {
+ var tags = this.assignedTags();
+ var removedTagLabel = this.tagLabel(tag);
+ tags = $.grep(tags, function(el){
+ return el != removedTagLabel;
+ });
+ this._updateSingleTagsField(tags);
+ }
+ // Animate the removal.
+ if (animate) {
+ tag.fadeOut('fast').hide('blind', {direction: 'horizontal'}, 'fast', function(){
+ tag.remove();
+ }).dequeue();
+ } else {
+ tag.remove();
+ }
+ },
+
+ removeAll: function() {
+ // Removes all tags.
+ var that = this;
+ this.tagList.children('.tagit-choice').each(function(index, tag) {
+ that.removeTag(tag, false);
+ });
+ }
+
+ });
+
+})(jQuery);
+
+
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/assets/stylesheets/jquery.tagit.css
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/redmine_tags/assets/stylesheets/jquery.tagit.css Wed Jan 09 12:41:39 2013 +0000
@@ -0,0 +1,54 @@
+ul.tagit {
+ padding: 1px 5px;
+ overflow: auto;
+ margin-left: inherit; /* usually we don't want the regular ul margins. */
+ margin-right: inherit;
+}
+ul.tagit li {
+ display: block;
+ float: left;
+ margin: 2px 5px 2px 0;
+}
+ul.tagit li.tagit-choice {
+ padding: .2em 18px .2em .5em;
+ position: relative;
+ line-height: inherit;
+}
+ul.tagit li.tagit-new {
+ padding: .25em 4px .25em 0;
+}
+
+ul.tagit li.tagit-choice a.tagit-label {
+ cursor: pointer;
+ text-decoration: none;
+}
+ul.tagit li.tagit-choice .tagit-close {
+ cursor: pointer;
+ position: absolute;
+ right: .1em;
+ top: 50%;
+ margin-top: -8px;
+}
+
+/* used for some custom themes that don't need image icons */
+ul.tagit li.tagit-choice .tagit-close .text-icon {
+ display: none;
+}
+
+ul.tagit li.tagit-choice input {
+ display: block;
+ float: left;
+ margin: 2px 5px 2px 0;
+}
+ul.tagit input[type="text"] {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+
+ border: none;
+ margin: 0;
+ padding: 0;
+ width: inherit;
+ background-color: inherit;
+ outline: none;
+}
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/assets/stylesheets/redmine_tags.css
--- a/plugins/redmine_tags/assets/stylesheets/redmine_tags.css Wed Jan 09 11:53:24 2013 +0000
+++ b/plugins/redmine_tags/assets/stylesheets/redmine_tags.css Wed Jan 09 12:41:39 2013 +0000
@@ -16,13 +16,12 @@
*
* You should have received a copy of the GNU General Public License
* along with redmine_tags. If not, see .
- */
+*/
ul.tags { list-style: none; padding: 0px; }
ul.tags li { margin: .25em 0px; }
div.tags { text-align: center; }
-div.tags h3 { text-align: left; }
div.tags .tag-label { margin: .25em; }
div.tags .tag-nube-1 { font-size: .8em; }
div.tags .tag-nube-2 { font-size: .9em; }
@@ -35,6 +34,24 @@
.tag-count { font-size: .75em; margin-left: .5em; }
+.tagit.ui-widget {
+ font-size: 1em;
+ margin: 0px;
+}
+
+ul.tagit li.tagit-choice {
+ color: #505050;
+ font-weight: normal;
+}
+
+ul.tagit li.tagit-choice:hover, ul.tagit li.tagit-choice.remove {
+ border-color: #6D95E0;
+}
+
+ul.tagit input[type="text"] {
+ background: transparent;
+}
+
ul.projects .tags, ul.projects .no-tags { padding-left: 0.5em; color: #3e442c; font-size: 0.95em }
table.projects th.tags { color: #3e442c; }
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/config/locales/bg.yml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/redmine_tags/config/locales/bg.yml Wed Jan 09 12:41:39 2013 +0000
@@ -0,0 +1,41 @@
+# This file is a part of redmine_tags
+# redMine plugin, that adds tagging support.
+#
+# Bulgarian translation for redmine_tags
+# by Ivan Cenov (jwalker_@Skype) i_cenov@botevgrad.com
+#
+# Copyright (c) 2010 Aleksey V Zapparov AKA ixti
+#
+# redmine_tags is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# redmine_tags is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with redmine_tags. If not, see .
+
+bg:
+ tags: Маркери
+ field_tags: Маркери
+ field_tag_list: Маркери
+ setting_issue_tags: Маркери на задачите
+ issues_sidebar: Показване на страничния панел като
+ issues_show_count: Показване на броя на задачите
+ issues_open_only: Само отворените задачи
+ issues_sort_by: Подреждане на маркерите по
+
+ issue_tags_sidebar_none: Да не се показват
+ issue_tags_sidebar_list: Списък
+ issue_tags_sidebar_cloud: Облак
+
+ issues_sort_by_name: Наименование
+ issues_sort_by_count: Количество задачи
+ issues_sort_order_asc: Нарастване
+ issues_sort_order_desc: Намаляване
+
+ auto_complete_new_tag: Добавяне на нов...
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/config/locales/de.yml
--- a/plugins/redmine_tags/config/locales/de.yml Wed Jan 09 11:53:24 2013 +0000
+++ b/plugins/redmine_tags/config/locales/de.yml Wed Jan 09 12:41:39 2013 +0000
@@ -2,9 +2,11 @@
# redMine plugin, that adds tagging support.
#
# German translation for redmine_tags
-# by Terence Miller aka cforce,
+# by: Terence Miller AKA cforce, ,
+# Jörg Jans
#
-# Copyright (c) 2010 Aleksey V Zapparov AKA ixti
+# Copyright (c) 2010 Terence Miller AKA cforce
+# Copyright (c) 2010 Jörg Jans
#
# redmine_tags is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -20,16 +22,22 @@
# along with redmine_tags. If not, see .
de:
- tags: Tags
- field_tags: Tags
- field_tag_list: Tags
- setting_issue_tags: Ticket Tags
- issues_sidebar: Zeige die Tags auf der Sidebar
- issues_show_count: Zeige die Ticketanzahl an
- issues_open_only: Zeige nur noch offene Tickets
+ tags: Tags
+ field_tags: Tags
+ field_tag_list: Tags
+ setting_issue_tags: Ticket Tags
+ issues_sidebar: Zeige die Tags auf der Sidebar
+ issues_show_count: Zeige die Ticketanzahl an
+ issues_open_only: Zeige nur noch offene Tickets
+ issues_sort_by: Sortiere Tags nach
- issue_tags_sidebar_none: Keine
- issue_tags_sidebar_list: Liste
- issue_tags_sidebar_cloud: Cloud
+ issue_tags_sidebar_none: Keine
+ issue_tags_sidebar_list: Liste
+ issue_tags_sidebar_cloud: Cloud
- auto_complete_new_tag: Hinzufügen...
+ issues_sort_by_name: Name
+ issues_sort_by_count: Anzahl tickets
+ issues_sort_order_asc: Aufsteigend
+ issues_sort_order_desc: Absteigend
+
+ auto_complete_new_tag: Hinzufügen...
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/config/locales/en.yml
--- a/plugins/redmine_tags/config/locales/en.yml Wed Jan 09 11:53:24 2013 +0000
+++ b/plugins/redmine_tags/config/locales/en.yml Wed Jan 09 12:41:39 2013 +0000
@@ -23,23 +23,26 @@
tags: Tags
field_tags: Tags
field_tag_list: Tags
- field_no_tags: "No tags"
- label_tags_search: "Tags: "
setting_issue_tags: Issues Tags
issues_sidebar: Display tags on sidebar as
issues_show_count: Display amount of issues
issues_open_only: Display open issues only
+ issues_sort_by: Sort tags by
issue_tags_sidebar_none: None
issue_tags_sidebar_list: List
issue_tags_sidebar_cloud: Cloud
+ issues_sort_by_name: Name
+ issues_sort_by_count: Issues amount
+ issues_sort_order_asc: Ascending
+ issues_sort_order_desc: Descending
+
auto_complete_new_tag: Add new...
-
+
project_filtering_q_label: "Search for text:"
project_filter_no_results: "No matching projects found"
button_filter: "Filter"
text_tags_info: "A tag can be any text you like, but they're most useful if you choose tags that are already being used for the same thing by other projects (where possible). Some tag examples are: library, plugin, paper, c++, mir, alpha, stable, bsd, android, ... Tags help others find your work: please don't forget to tag your projects!"
-
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/config/locales/fr.yml
--- a/plugins/redmine_tags/config/locales/fr.yml Wed Jan 09 11:53:24 2013 +0000
+++ b/plugins/redmine_tags/config/locales/fr.yml Wed Jan 09 12:41:39 2013 +0000
@@ -2,9 +2,9 @@
# redMine plugin, that adds tagging support.
#
# French translation for redmine_tags
-# by Stphane HANNEQUIN,
+# by Stephane HANNEQUIN,
#
-# Copyright (c) 2010 Aleksey V Zapparov AKA ixti
+# Copyright (c) 2010 Stephane HANNEQUIN
#
# redmine_tags is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -27,9 +27,15 @@
issues_sidebar: Afficher les Tags comme
issues_show_count: Afficher le nombre de demande
issues_open_only: N'afficher que les demandes ouvertes
+ issues_sort_by: (en) Sort tags by
issue_tags_sidebar_none: Ne pas afficher
issue_tags_sidebar_list: Liste
issue_tags_sidebar_cloud: Nuage
+ issues_sort_by_name: (en) Name
+ issues_sort_by_count: (en) Issues amount
+ issues_sort_order_asc: (en) Ascending
+ issues_sort_order_desc: (en) Descending
+
auto_complete_new_tag: Nouveau...
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/config/locales/ru.yml
--- a/plugins/redmine_tags/config/locales/ru.yml Wed Jan 09 11:53:24 2013 +0000
+++ b/plugins/redmine_tags/config/locales/ru.yml Wed Jan 09 12:41:39 2013 +0000
@@ -27,9 +27,15 @@
issues_sidebar: Боковую панель как
issues_show_count: Показать кол-во задач
issues_open_only: Только открытые задачи
+ issues_sort_by: Упорядочить метки по
issue_tags_sidebar_none: Не показывать
issue_tags_sidebar_list: Список
issue_tags_sidebar_cloud: Облако
+ issues_sort_by_name: Названию
+ issues_sort_by_count: Кол-ву задач
+ issues_sort_order_asc: по возрастанию
+ issues_sort_order_desc: по убыванию
+
auto_complete_new_tag: Добавить...
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/config/locales/zh.yml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/redmine_tags/config/locales/zh.yml Wed Jan 09 12:41:39 2013 +0000
@@ -0,0 +1,41 @@
+# This file is a part of redmine_tags
+# redMine plugin, that adds tagging support.
+#
+# Simplified Chinese translation for redmine_tags
+# by archonwang (https://github.com/archonwang)
+#
+# Copyright (c) 2010 Aleksey V Zapparov AKA ixti
+#
+# redmine_tags is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# redmine_tags is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with redmine_tags. If not, see .
+
+zh:
+ tags: 标签
+ field_tags: 标签
+ field_tag_list: 标签
+ setting_issue_tags: 问题标签
+ issues_sidebar: 在侧边栏显示标签
+ issues_show_count: 显示问题计数
+ issues_open_only: 仅显示打开的问题
+ issues_sort_by: 标签按何种方式排序
+
+ issue_tags_sidebar_none: 无
+ issue_tags_sidebar_list: 列表显示
+ issue_tags_sidebar_cloud: 云显示
+
+ issues_sort_by_name: 名称
+ issues_sort_by_count: 问题计数
+ issues_sort_order_asc: 顺序
+ issues_sort_order_desc: 倒序
+
+ auto_complete_new_tag: 添加新标签 ... ...
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/config/routes.rb
--- a/plugins/redmine_tags/config/routes.rb Wed Jan 09 11:53:24 2013 +0000
+++ b/plugins/redmine_tags/config/routes.rb Wed Jan 09 12:41:39 2013 +0000
@@ -1,3 +1,4 @@
RedmineApp::Application.routes.draw do
+ match '/issue_tags/auto_complete/:project_id', :to => 'auto_completes#issue_tags', :via => :get, :as => 'auto_complete_issue_tags'
match 'projects/set_fieldset_status' => 'projects#set_fieldset_status', :constraints => {:method => :post}
-end
\ No newline at end of file
+end
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/init.rb
--- a/plugins/redmine_tags/init.rb Wed Jan 09 11:53:24 2013 +0000
+++ b/plugins/redmine_tags/init.rb Wed Jan 09 12:41:39 2013 +0000
@@ -17,21 +17,25 @@
# along with redmine_tags. If not, see .
require 'redmine'
+require 'redmine_tags'
+
Redmine::Plugin.register :redmine_tags do
name 'redmine_tags'
author 'Aleksey V Zapparov AKA "ixti"'
description 'redMine tagging support'
- version '1.1.4'
- url 'http://www.ixti.ru/'
- author_url 'http://www.ixti.ru/'
+ version '2.0.1-dev'
+ url 'https://github.com/ixti/redmine_tags/'
+ author_url 'http://www.ixti.net/'
- requires_redmine :version_or_higher => '1.0.0'
+ requires_redmine :version_or_higher => '1.2.0'
settings :default => {
:issues_sidebar => 'none',
:issues_show_count => 0,
- :issues_open_only => 0
+ :issues_open_only => 0,
+ :issues_sort_by => 'name',
+ :issues_sort_order => 'asc'
}, :partial => 'tags/settings'
end
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/lib/redmine_tags.rb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/redmine_tags/lib/redmine_tags.rb Wed Jan 09 12:41:39 2013 +0000
@@ -0,0 +1,21 @@
+# This file is a part of redmine_tags
+# redMine plugin, that adds tagging support.
+#
+# Copyright (c) 2010 Aleksey V Zapparov AKA ixti
+#
+# redmine_tags is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# redmine_tags is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with redmine_tags. If not, see .
+
+module RedmineTags
+ def self.settings() Setting[:plugin_redmine_tags] end
+end
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/lib/redmine_tags/hooks/model_issue_hook.rb
--- a/plugins/redmine_tags/lib/redmine_tags/hooks/model_issue_hook.rb Wed Jan 09 11:53:24 2013 +0000
+++ b/plugins/redmine_tags/lib/redmine_tags/hooks/model_issue_hook.rb Wed Jan 09 12:41:39 2013 +0000
@@ -24,6 +24,10 @@
save_tags_to_issue(context, true)
end
+ def controller_issues_bulk_edit_before_save(context={})
+ save_tags_to_issue(context, true)
+ end
+
# Issue has an after_save method that calls reload (update_nested_set_attributes)
# This makes it impossible for a new record to get a tag_list, it's
# cleared on reload. So instead, hook in after the Issue#save to update
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/lib/redmine_tags/hooks/views_issues_hook.rb
--- a/plugins/redmine_tags/lib/redmine_tags/hooks/views_issues_hook.rb Wed Jan 09 11:53:24 2013 +0000
+++ b/plugins/redmine_tags/lib/redmine_tags/hooks/views_issues_hook.rb Wed Jan 09 12:41:39 2013 +0000
@@ -22,6 +22,7 @@
render_on :view_issues_show_details_bottom, :partial => 'issues/tags'
render_on :view_issues_form_details_bottom, :partial => 'issues/tags_form'
render_on :view_issues_sidebar_planning_bottom, :partial => 'issues/tags_sidebar'
+ render_on :view_issues_bulk_edit_details_bottom, :partial => 'issues/tags_form'
end
end
end
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/lib/redmine_tags/patches/auto_completes_controller_patch.rb
--- a/plugins/redmine_tags/lib/redmine_tags/patches/auto_completes_controller_patch.rb Wed Jan 09 11:53:24 2013 +0000
+++ b/plugins/redmine_tags/lib/redmine_tags/patches/auto_completes_controller_patch.rb Wed Jan 09 12:41:39 2013 +0000
@@ -23,13 +23,20 @@
module AutoCompletesControllerPatch
def self.included(base)
base.send(:include, InstanceMethods)
+
+ base.class_eval do
+ unloadable
+ end
end
module InstanceMethods
def issue_tags
@name = params[:q].to_s
- @tags = Issue.available_tags :project_id => @project, :name_like => @name
+ @tags = Issue.available_tags({
+ :project_id => @project,
+ :name_like => @name
+ })
render :layout => false, :partial => 'tag_list'
end
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/lib/redmine_tags/patches/issue_patch.rb
--- a/plugins/redmine_tags/lib/redmine_tags/patches/issue_patch.rb Wed Jan 09 11:53:24 2013 +0000
+++ b/plugins/redmine_tags/lib/redmine_tags/patches/issue_patch.rb Wed Jan 09 12:41:39 2013 +0000
@@ -27,10 +27,25 @@
base.class_eval do
unloadable
acts_as_taggable
+
+ scope :on_project, lambda { |project|
+ project = project.id if project.is_a? Project
+ { :conditions => ["#{Project.table_name}.id=?", project] }
+ }
+
+ Issue.safe_attributes 'tag_list'
end
end
module ClassMethods
+ TAGGING_IDS_LIMIT_SQL = <<-SQL
+ tag_id IN (
+ SELECT #{ActsAsTaggableOn::Tagging.table_name}.tag_id
+ FROM #{ActsAsTaggableOn::Tagging.table_name}
+ WHERE #{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN (?)
+ )
+ SQL
+
# Returns available issue tags
# === Parameters
# * options = (optional) Options hash of
@@ -38,30 +53,22 @@
# * open_only - Boolean. Whenever search within open issues only.
# * name_like - String. Substring to filter found tags.
def available_tags(options = {})
- project = options[:project]
- open_only = options[:open_only]
- name_like = options[:name_like]
- options = {}
- visible = ARCondition.new
-
- if project
- project = project.id if project.is_a? Project
- visible << ["#{Issue.table_name}.project_id = ?", project]
+ ids_scope = Issue.visible
+ ids_scope = ids_scope.on_project(options[:project]) if options[:project]
+ ids_scope = ids_scope.open if options[:open_only]
+
+ conditions = [""]
+
+ # limit to the tags matching given %name_like%
+ if options[:name_like]
+ conditions[0] << "#{ActsAsTaggableOn::Tag.table_name}.name LIKE ? AND "
+ conditions << "%#{options[:name_like].downcase}%"
end
- if open_only
- visible << ["#{Issue.table_name}.status_id IN " +
- "( SELECT issue_status.id " +
- " FROM #{IssueStatus.table_name} issue_status " +
- " WHERE issue_status.is_closed = ? )", false]
- end
+ conditions[0] << TAGGING_IDS_LIMIT_SQL
+ conditions << ids_scope.map{ |issue| issue.id }.push(-1)
- if name_like
- visible << ["#{ActsAsTaggableOn::Tag.table_name}.name LIKE ?", "%#{name_like.downcase}%"]
- end
-
- options[:conditions] = visible.conditions
- self.all_tag_counts(options)
+ self.all_tag_counts(:conditions => conditions)
end
end
end
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/lib/redmine_tags/patches/issues_helper_patch.rb
--- a/plugins/redmine_tags/lib/redmine_tags/patches/issues_helper_patch.rb Wed Jan 09 11:53:24 2013 +0000
+++ b/plugins/redmine_tags/lib/redmine_tags/patches/issues_helper_patch.rb Wed Jan 09 12:41:39 2013 +0000
@@ -1,20 +1,3 @@
-# This file is a part of redmine_tags
-# redMine plugin, that adds tagging support.
-#
-# Copyright (c) 2010 Aleksey V Zapparov AKA ixti
-#
-# redmine_tags is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# redmine_tags is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with redmine_tags. If not, see .
require_dependency 'issues_helper'
@@ -28,27 +11,25 @@
module InstanceMethods
include TagsHelper
- def redmine_tags_settings
- @redmine_tags_settings = Setting.plugin_redmine_tags unless @redmine_tags_settings
- @redmine_tags_settings
- end
-
def sidebar_tags
unless @sidebar_tags
@sidebar_tags = []
- if :none != redmine_tags_settings[:issues_sidebar].to_sym
- @sidebar_tags = Issue.available_tags(:project => @project,
- :open_only => (redmine_tags_settings[:issues_open_only].to_i == 1))
+ if :none != RedmineTags.settings[:issues_sidebar].to_sym
+ @sidebar_tags = Issue.available_tags({
+ :project => @project,
+ :open_only => (RedmineTags.settings[:issues_open_only].to_i == 1)
+ })
end
end
@sidebar_tags
end
def render_sidebar_tags
- render_tags_list(sidebar_tags,
- :show_count => (redmine_tags_settings[:issues_show_count].to_i == 1),
- :open_only => (redmine_tags_settings[:issues_open_only].to_i == 1),
- :style => redmine_tags_settings[:issues_sidebar].to_sym)
+ render_tags_list(sidebar_tags, {
+ :show_count => (RedmineTags.settings[:issues_show_count].to_i == 1),
+ :open_only => (RedmineTags.settings[:issues_open_only].to_i == 1),
+ :style => RedmineTags.settings[:issues_sidebar].to_sym
+ })
end
end
end
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/lib/redmine_tags/patches/queries_helper_patch.rb
--- a/plugins/redmine_tags/lib/redmine_tags/patches/queries_helper_patch.rb Wed Jan 09 11:53:24 2013 +0000
+++ b/plugins/redmine_tags/lib/redmine_tags/patches/queries_helper_patch.rb Wed Jan 09 12:41:39 2013 +0000
@@ -25,6 +25,7 @@
base.send(:include, InstanceMethods)
base.class_eval do
+ unloadable
alias_method :column_content_original, :column_content
alias_method :column_content, :column_content_extended
end
diff -r 2681af99688f -r 9b2f28ecd125 plugins/redmine_tags/lib/redmine_tags/patches/query_patch.rb
--- a/plugins/redmine_tags/lib/redmine_tags/patches/query_patch.rb Wed Jan 09 11:53:24 2013 +0000
+++ b/plugins/redmine_tags/lib/redmine_tags/patches/query_patch.rb Wed Jan 09 12:41:39 2013 +0000
@@ -41,16 +41,26 @@
module InstanceMethods
def statement_extended
filter = filters.delete 'tags'
- clauses = statement_original
+ clauses = statement_original || ""
if filter
filters.merge!( 'tags' => filter )
- values = values_for('tags').clone
- compare = operator_for('tags').eql?('=') ? 'IN' : 'NOT IN'
- ids_list = Issue.tagged_with(values).collect{ |issue| issue.id }.push(0).join(',')
+ op = operator_for('tags')
+ case op
+ when '=', '!'
+ issues = Issue.tagged_with(values_for('tags').clone)
+ when '!*'
+ issues = Issue.tagged_with(ActsAsTaggableOn::Tag.all.map(&:to_s), :exclude => true)
+ else
+ issues = Issue.tagged_with(ActsAsTaggableOn::Tag.all.map(&:to_s), :any => true)
+ end
- clauses << " AND ( #{Issue.table_name}.id #{compare} (#{ids_list}) ) "
+ compare = op.eql?('!') ? 'NOT IN' : 'IN'
+ ids_list = issues.collect{ |issue| issue.id }.push(0).join(',')
+
+ clauses << " AND " unless clauses.empty?
+ clauses << "( #{Issue.table_name}.id #{compare} (#{ids_list}) ) "
end
clauses
@@ -60,7 +70,8 @@
def available_filters_extended
unless @available_filters
available_filters_original.merge!({ 'tags' => {
- :type => :list,
+ :name => l(:tags),
+ :type => :list_optional,
:order => 6,
:values => Issue.available_tags(:project => project).collect{ |t| [t.name, t.name] }
}})