diff --git a/app/controllers/application_controller/miq_request_methods.rb b/app/controllers/application_controller/miq_request_methods.rb index 3bc90454e214..2bf378fe40d6 100644 --- a/app/controllers/application_controller/miq_request_methods.rb +++ b/app/controllers/application_controller/miq_request_methods.rb @@ -651,7 +651,7 @@ def prov_req_submit # Get variables from provisioning form def prov_get_form_vars if params[:ids_checked] # User checked/unchecked a tree node - ids = params[:ids_checked].split(",") + ids = params[:ids_checked] # for some reason if tree is not expanded clicking on radiobuttons this.getAllChecked() sends up extra blanks @edit.store_path(:new, tag_symbol_for_workflow, ids.select(&:present?).collect(&:to_i)) end @@ -984,69 +984,35 @@ def workflow_instance_from_vars(req) end def build_tags_tree(wf, vm_tags, edit_mode) - tags = wf.send("allowed_tags") - @curr_tag = nil - # Build the default filters tree for the search views - all_tags = [] # Array to hold all CIs - kids_checked = false - tags.each_with_index do |t, i| # Go thru all of the Searches - if @curr_tag.blank? || @curr_tag != t[:name] - if @curr_tag != t[:name] && @ci_node - @ci_node[:expand] = true if kids_checked - kids_checked = false - @ci_node[:children] = @ci_kids if @ci_kids.present? - all_tags.push(@ci_node) if @ci_kids.present? - end - @curr_tag = t[:name] - @ci_node = {} # Build the ci node - @ci_node[:key] = t[:id].to_s - @ci_node[:title] = t[:description] - @ci_node[:title] += " *" if t[:single_value] - @ci_node[:tooltip] = t[:description] - @ci_node[:addClass] = "cfme-no-cursor-node" # No cursor pointer - @ci_node[:icon] = 'pficon pficon-folder-close' - @ci_node[:hideCheckbox] = @ci_node[:cfmeNoClick] = true - @ci_node[:addClass] = "cfme-bold-node" # Show node as different - @ci_kids = [] - end - if @curr_tag.present? && @curr_tag == t[:name] - t[:children].each do |c| - temp = {} - temp[:key] = c[0].to_s - # only add cfme_parent_key for single value tags, need to use in JS onclick handler - temp[:selectable] = false - temp[:title] = temp[:tooltip] = c[1][:description] - temp[:addClass] = "cfme-no-cursor-node" - temp[:icon] = 'fa fa-tag' - if edit_mode # Don't show checkboxes/radio buttons in non-edit mode - if vm_tags && vm_tags.include?(c[0].to_i) - temp[:select] = true - kids_checked = true - else - temp[:select] = false - end - if @edit && @edit[:current][tag_symbol_for_workflow] != @edit[:new][tag_symbol_for_workflow] - # checking to see if id is in current but not in new, change them to blue OR if id is in current but deleted from new - if (!@edit[:current][tag_symbol_for_workflow].include?(c[0].to_i) && @edit[:new][tag_symbol_for_workflow].include?(c[0].to_i)) || - (!@edit[:new][tag_symbol_for_workflow].include?(c[0].to_i) && @edit[:current][tag_symbol_for_workflow].include?(c[0].to_i)) - temp[:addClass] = "cfme-blue-bold-node" - end - end - @ci_kids.push(temp) unless @ci_kids.include?(temp) - else - temp[:hideCheckbox] = true - @ci_kids.push(temp) unless @ci_kids.include?(temp) || !vm_tags.include?(c[0].to_i) - end - end - end - if i == tags.length - 1 # Adding last node - @ci_node[:expand] = true if kids_checked - kids_checked = false - @ci_node[:children] = @ci_kids if @ci_kids.present? - all_tags.push(@ci_node) if @ci_kids.present? + # for some reason @tags is set in wf, and it is changed by map bellow which causes bugs + wf.instance_variable_set(:@tags, nil) + tags = wf.allowed_tags + tags.each do |cat| + cat[:values] = cat[:children].map do |tag| + { :id => tag.first, :description => tag.second[:description] } end + cat[:id] = cat[:name] + cat[:singleValue] = cat[:single_value] + cat.delete(:children) + cat.delete(:name) end - @all_tags_tree = TreeBuilder.convert_bs_tree(all_tags).to_json # Add ci node array to root of tree + + assignments = Classification.select { |tag| vm_tags.include?(tag.id) } + assigned_tags = assignments.map do |tag| + { + :description => tag.parent.description, + :id => tag.parent.id, + :values => assignments.select { |assignment| assignment.parent_id == tag.parent_id }.map do |assignment| + { :description => assignment.description, :id => assignment.id } + end + } + end.uniq + + @button_urls = { + :save_url => '', + :cancel_url => '' + } + @tags = {:tags => tags, :assignedTags => assigned_tags, :affectedItems => []} end def build_template_filter diff --git a/app/javascript/components/taggingWrapper.jsx b/app/javascript/components/taggingWrapper.jsx index 86f7054f316c..cb613ff4ff1e 100644 --- a/app/javascript/components/taggingWrapper.jsx +++ b/app/javascript/components/taggingWrapper.jsx @@ -5,6 +5,26 @@ import { Spinner } from 'patternfly-react'; import { TaggingWithButtonsConnected, TaggingConnected, taggingApp } from '@manageiq/react-ui-components/dist/tagging'; import { http } from '../http_api'; +const params = (type = 'default', state, tag = {}) => ({ + provision: { + id: "new", + ids_checked: [state.tagging.appState.assignedTags.map(t => t.values.map(val => val.id)).flat(), tag.tagValue.id].flat(), + tree_typ: 'tags' + }, + default: { + id: state.tagging.appState.affectedItems[0] || "new", + cat: tag.tagCategory.id, + val: tag.tagValue.id, + check: 1, + tree_typ: 'tags' + } +})[type] + +const onDelete = (type = 'default', params = [], deleted_element) => ({ + provision: {...params, ids_checked: params.ids_checked.filter(element => element !== deleted_element)}, + default: params, +})[type] + class TaggingWrapper extends React.Component { constructor(props) { super(props); @@ -22,7 +42,7 @@ class TaggingWrapper extends React.Component { render() { if (!this.props.isLoaded) return ; const { urls, options } = this.props; - return (options && options.hideButtons && || || ); } } diff --git a/app/javascript/miq-redux/middleware.js b/app/javascript/miq-redux/middleware.js index ad15b1d1906b..cc13e1f16c85 100644 --- a/app/javascript/miq-redux/middleware.js +++ b/app/javascript/miq-redux/middleware.js @@ -5,10 +5,11 @@ import promiseMiddleware from 'redux-promise-middleware'; export const taggingMiddleware = store => next => action => { const { type, meta, tagCategory, tag } = action; if (meta && meta.url) { - const params = {id: store.getState().tagging.appState.affectedItems[0], cat: tag.tagCategory.id, val: tag.tagValue.id, check: 1, tree_typ: 'tags' }; + let params = meta.params(meta.type, store.getState(), tag); if (type === 'UI-COMPONENTS_TAGGING_TOGGLE_TAG_VALUE_CHANGE') { $.post(meta.url, params) } else if (type === 'UI-COMPONENTS_TAGGING_DELETE_ASSIGNED_TAG') { + params = meta.onDelete(meta.type, params, tag.tagValue.id); $.post(meta.url, {...params, check: 0}) } } diff --git a/app/views/miq_request/_prov_field.html.haml b/app/views/miq_request/_prov_field.html.haml index 41c995f1b061..e11d1b074934 100644 --- a/app/views/miq_request/_prov_field.html.haml +++ b/app/views/miq_request/_prov_field.html.haml @@ -298,13 +298,7 @@ - check = @miq_request.id - else - check = 'new' - = render(:partial => "layouts/tree", - :locals => {:tree_id => "all_tags_treebox", - :tree_name => "all_tags_tree", - :bs_tree => @all_tags_tree, - :oncheck => "miqOnCheckProvTags", - :check_url => "/miq_request/prov_field_changed/#{check}", - :checkboxes => true}) + = react 'TaggingWrapperConnected', { :tags => @tags, :urls => @button_urls, :options => { :type => 'provision', :hideHeaders => true, :hideButtons => true, :url => url_for_only_path(:action => 'prov_field_changed')} } - unless field_hash[:notes_display] == :hide || field_hash[:notes].blank? -# Display notes if available = field_hash[:notes]