From 65ff2c7a427bdc4417ac2cdab7f7c27a39890e99 Mon Sep 17 00:00:00 2001 From: Michel Felipe Date: Sat, 30 May 2015 15:56:51 -0300 Subject: [PATCH] Each tags is defined in a task, store it in database. Added to the logged user like a tagger of tasks. jQuery plugin 'inputosaurus.js' was customize and a pull request was made in your github repo --- app/controllers/my_profile/tasks_controller.rb | 49 +++++++++++++++++++++++++++---------------------- app/models/person.rb | 2 ++ app/views/tasks/_task.html.erb | 2 +- app/views/tasks/index.html.erb | 8 +++++++- public/javascripts/inputosaurus.js | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------- 5 files changed, 98 insertions(+), 46 deletions(-) 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 @@
- <%= labelled_text_field(_('Tags'),"tasks[#{task.id}][task][tag_list]", task.tag_list.to_s, :size => 36, :class => 'tag-list') %> + <%= labelled_text_field(_('Tags'),"tasks[#{task.id}][task][tag_list]", task.tags_from(nil).to_s, :size => 36, :class => 'tag-list','data-submit-values'=>"{'task_id':'#{task.id}'}") %>
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