diff --git a/app/controllers/my_profile/tasks_controller.rb b/app/controllers/my_profile/tasks_controller.rb
index b83b14c..0473342 100644
--- a/app/controllers/my_profile/tasks_controller.rb
+++ b/app/controllers/my_profile/tasks_controller.rb
@@ -41,33 +41,18 @@ class TasksController < MyProfileController
def close
failed = {}
- save = false
if params[:tasks]
params[:tasks].each do |id, value|
decision = value[:decision]
-
- if value[:task].is_a?(Hash) && value[:task][:tag_list]
-
+ if request.post? && VALID_DECISIONS.include?(decision) && id && decision != 'skip'
task = profile.find_in_all_tasks(id)
- task.tag_list = value[:task][:tag_list]
- value[:task].delete('tag_list')
-
- save = true
- end
-
- if request.post?
- if VALID_DECISIONS.include?(decision) && id && decision != 'skip'
- task ||= profile.find_in_all_tasks(id)
- begin
- task.update_attributes(value[:task])
- task.send(decision)
- rescue Exception => ex
- message = "#{task.title} (#{task.requestor ? task.requestor.name : task.author_name})"
- failed[ex.message] ? failed[ex.message] << message : failed[ex.message] = [message]
- end
- elsif save
- task.save!
+ begin
+ task.update_attributes(value[:task])
+ task.send(decision)
+ rescue Exception => ex
+ message = "#{task.title} (#{task.requestor ? task.requestor.name : task.author_name})"
+ failed[ex.message] ? failed[ex.message] << message : failed[ex.message] = [message]
end
end
end
@@ -104,4 +89,24 @@ class TasksController < MyProfileController
@ticket = Ticket.find(:first, :conditions => ['(requestor_id = ? or target_id = ?) and id = ?', profile.id, profile.id, params[:id]])
end
+ def save_tags
+
+ if request.post? && params[:tag_list]
+ result = {
+ success: false
+ }
+
+ ActsAsTaggableOn.remove_unused_tags = true
+
+ task = Task.find_by_id params[:task_id]
+ save = user.tag(task, with: params[:tag_list], on: :tags)
+
+ if save
+ result[:success] = true
+ end
+ end
+
+ render json: result
+ end
+
end
diff --git a/app/models/person.rb b/app/models/person.rb
index 15582e9..7b35251 100644
--- a/app/models/person.rb
+++ b/app/models/person.rb
@@ -16,6 +16,8 @@ class Person < Profile
acts_as_trackable :after_add => Proc.new {|p,t| notify_activity(t)}
acts_as_accessor
+ acts_as_tagger
+
scope :members_of, lambda { |resources|
resources = [resources] if !resources.kind_of?(Array)
conditions = resources.map {|resource| "role_assignments.resource_type = '#{resource.class.base_class.name}' AND role_assignments.resource_id = #{resource.id || -1}"}.join(' OR ')
diff --git a/app/views/tasks/_task.html.erb b/app/views/tasks/_task.html.erb
index 2003f8c..25b481c 100644
--- a/app/views/tasks/_task.html.erb
+++ b/app/views/tasks/_task.html.erb
@@ -64,7 +64,7 @@
diff --git a/app/views/tasks/index.html.erb b/app/views/tasks/index.html.erb
index 9a5e990..69a433f 100644
--- a/app/views/tasks/index.html.erb
+++ b/app/views/tasks/index.html.erb
@@ -75,7 +75,13 @@
diff --git a/public/javascripts/inputosaurus.js b/public/javascripts/inputosaurus.js
index 999d1a0..174d9c9 100644
--- a/public/javascripts/inputosaurus.js
+++ b/public/javascripts/inputosaurus.js
@@ -1,5 +1,5 @@
/**
- * Inputosaurus Text
+ * Inputosaurus Text
*
* Must be instantiated on an element
* Allows multiple input items. Each item is represented with a removable tag that appears to be inside the input area.
@@ -30,7 +30,7 @@
//
// 'change' - triggered whenever a tag is added or removed (should be similar to binding the the change event of the instantiated input
// 'keyup' - keyup event on the newly created input
-
+
// while typing, the user can separate values using these delimiters
// the value tags are created on the fly when an inputDelimiter is detected
inputDelimiters : [',', ';'],
@@ -56,12 +56,15 @@
// manipulate and return the input value after parseInput() parsing
// the array of tag names is passed and expected to be returned as an array after manipulation
parseHook : null,
-
+
// define a placeholder to display when the input is empty
placeholder: null,
-
+
// when you check for duplicates it check for the case
- caseSensitiveDuplicates: false
+ caseSensitiveDuplicates: false,
+
+ //Ajax options to send tags
+ submitTags: null
},
_create: function() {
@@ -69,7 +72,7 @@
els = {},
o = widget.options,
placeholder = o.placeholder || this.element.attr('placeholder') || null;
-
+
this._chosenValues = [];
// Create the elements
@@ -77,11 +80,11 @@
els.input = $(' ');
els.inputCont = $(' ');
els.origInputCont = $('');
-
+
// define starting placeholder
- if (placeholder) {
+ if (placeholder) {
o.placeholder = placeholder;
- els.input.attr('placeholder', o.placeholder);
+ els.input.attr('placeholder', o.placeholder);
if (o.width) {
els.input.css('min-width', o.width - 50);
}
@@ -90,11 +93,11 @@
o.wrapperElement && o.wrapperElement.append(els.ul);
this.element.replaceWith(o.wrapperElement || els.ul);
els.origInputCont.append(this.element).hide();
-
+
els.inputCont.append(els.input);
els.ul.append(els.inputCont);
els.ul.append(els.origInputCont);
-
+
o.width && els.ul.css('width', o.width);
this.elements = els;
@@ -130,8 +133,8 @@
var auto = $(this).data('ui-autocomplete') || $(this).data('autocomplete');
var menu = auto.menu,
$menuItems;
-
-
+
+
// zIndex will force the element on top of anything (like a dialog it's in)
menu.element.zIndex && menu.element.zIndex($(this).zIndex() + 1);
menu.element.width(widget.elements.ul.outerWidth());
@@ -241,7 +244,7 @@
widget.elements.input.width(txtWidth < maxWidth ? txtWidth : maxWidth);
},
-
+
// resets placeholder on representative input
_resetPlaceholder: function () {
var placeholder = this.options.placeholder,
@@ -266,7 +269,7 @@
ev.preventDefault();
lastTag.find('a').focus();
}
-
+
},
_editTag : function(ev) {
@@ -285,6 +288,7 @@
v.key === tagKey && (tagName = v.value);
});
+ widget.beforeEditValue = widget.element.val();
widget.elements.input.val(tagName);
widget._removeTag(ev);
@@ -295,7 +299,7 @@
var widget = ev.data.widget;
switch(ev.which){
- case $.ui.keyCode.BACKSPACE:
+ case $.ui.keyCode.BACKSPACE:
ev && ev.preventDefault();
ev && ev.stopPropagation();
$(ev.currentTarget).trigger('click');
@@ -409,11 +413,18 @@
},
_setValue : function(value) {
- var val = this.element.val();
+
+ if(arguments[1] && (arguments[1].type == 'dblclick' && value == '')){
+ return false;
+ }
+ var val = this.element.val().replace(/,\s*/g,',');
if(val !== value){
this.element.val(value);
this._trigger('change');
+ if($.isPlainObject(this.options.submitTags)){
+ this._sendTags();
+ }
}
},
@@ -439,7 +450,7 @@
},
_removeTag : function(ev) {
- var $closest = $(ev.currentTarget).closest('li'),
+ var $closest = $(ev.currentTarget).closest('li'),
key = $closest.data('ui-inputosaurus') || $closest.data('inputosaurus'),
indexFound = false,
widget = (ev && ev.data.widget) || this;
@@ -453,7 +464,7 @@
indexFound !== false && widget._chosenValues.splice(indexFound, 1);
- widget._setValue(widget._buildValue());
+ widget._setValue(widget._buildValue(),ev);
$(ev.currentTarget).closest('li').remove();
widget.elements.input.focus();
@@ -477,7 +488,7 @@
var delim = this.options.outputDelimiter,
val = this.element.val(),
values = [];
-
+
values.push(val);
delim && (values = val.split(delim));
@@ -515,9 +526,37 @@
this.elements.ul.replaceWith(this.element);
+ },
+
+ _sendTags: function(){
+
+ var requestTags = this.options.submitTags;
+ if(this.element.val() != '' && this.beforeEditValue != this.element.val()) {
+
+ opts = $.extend({
+ url: requestTags.url,
+ dataType: 'json',
+ data:{},
+ type:'POST'
+ },requestTags);
+
+ var extraValues = this.element.data('submit-values');
+ if(typeof extraValues == 'string' && /\{*/.test(extraValues)){
+ extraValues = $.parseJSON(extraValues.replace(/\'/g,'\"'));
+ }
+
+ if(!$.isEmptyObject(extraValues)){
+ for(v in extraValues){
+ opts.data[v] = extraValues[v];
+ }
+ }
+
+ opts.data.tag_list = this.element.val();
+
+ $.ajax(opts);
+ }
}
};
$.widget("ui.inputosaurus", inputosaurustext);
-})(jQuery);
-
+})($ || jQuery);
--
libgit2 0.21.2