<commit_before># frozen_string_literal: true

require_relative '../../../gzr'
require_relative '../../command'
require_relative '../../modules/dashboard'
require_relative '../../modules/look'
require_relative '../../modules/user'
require_relative '../../modules/plan'
require_relative '../../modules/filehelper'

module Gzr
  module Commands
    class Dashboard
      class Import < Gzr::Command
        include Gzr::Dashboard
        include Gzr::Look
        include Gzr::User
        include Gzr::Plan
        include Gzr::FileHelper
        def initialize(file, dest_space_id, options)
          super()
          @file = file
          @dest_space_id = dest_space_id
          @options = options
        end

        def execute(input: $stdin, output: $stdout)
          say_warning("options: #{@options.inspect}") if @options[:debug]
          with_session("3.1") do

            @me ||= query_me("id")

            read_file(@file) do |data|

              dashboard = sync_dashboard(data,@dest_space_id)

              pairs(data[:dashboard_filters],dashboard.dashboard_filters,dashboard.id) do |source,target,id|
                say_warning "Synching dashboard filter for dashboard #{id}" if @options[:debug]
                sync_dashboard_filter(source,target,id)
              end

              elem_table = pairs(data[:dashboard_elements],dashboard.dashboard_elements,dashboard.id) do |source,target,id|
                sync_dashboard_element(source,target,id)
              end

              pairs(data[:dashboard_layouts],dashboard.dashboard_layouts) do |s,t|
                sync_dashboard_layout(dashboard.id,s,t) do |s,t|
                  sync_dashboard_layout_component(s,t,elem_table)
                end
              end
              upsert_plans_for_dashboard(dashboard.id,@me.id,data[:scheduled_plans]) if data[:scheduled_plans]
              output.puts "Imported dashboard #{dashboard.id}" unless @options[:plain] 
              output.puts dashboard.id if @options[:plain] 
            end
          end
        end

        def sync_dashboard(source,target_space_id)
          existing_dashboard = search_dashboards_by_title(source[:title], target_space_id).fetch(0,nil)
          slug_used = search_dashboards_by_slug(source[:slug]).fetch(0,nil) if source[:slug]

          if slug_used then
            if existing_dashboard then
              if !(existing_dashboard.space_id == slug_used.space_id && existing_dashboard.title == slug_used.title) then
                say_warning "slug #{slug_used.slug} already used for dashboard #{slug_used.title} in space #{slug_used.space_id}"
                say_warning "dashboard will be imported with new slug"
              end
            else
              say_warning "slug #{slug_used.slug} already used for dashboard #{slug_used.title} in space #{slug_used.space_id}"
              say_warning "dashboard will be imported with new slug"
            end
          end

          if existing_dashboard then
            if @options[:force] then
              say_ok "Modifying existing dashboard #{existing_dashboard.id} #{existing_dashboard[:title]} in space #{target_space_id}"
              new_dash = source.select do |k,v|
                (keys_to_keep('update_dashboard') - [:space_id,:user_id,:title,:slug]).include? k
              end
              new_dash[:slug] = source[:slug] unless slug_used
              return update_dashboard(existing_dashboard.id,new_dash)
            else
              raise Gzr::CLI::Error, "Dashboard #{source[:title]} already exists in space #{target_space_id}\nUse --force if you want to overwrite it"
            end
          else
            new_dash = source.select do |k,v|
              (keys_to_keep('create_dashboard') - [:space_id,:user_id,:slug]).include? k
            end
            new_dash[:slug] = source[:slug] unless slug_used
            new_dash[:space_id] = target_space_id
            new_dash[:user_id] = @me.id
            return create_dashboard(new_dash)
          end
        end

        def sync_dashboard_filter(new_filter,existing_filter,dashboard_id)
          if new_filter && !existing_filter then
            filter = new_filter.select do |k,v|
              (keys_to_keep('create_dashboard_filter') + [:row]).include? k
            end
            filter[:dashboard_id] = dashboard_id
            say_warning "Creating filter" if @options[:debug]
            return create_dashboard_filter(filter)
          end
          if existing_filter && new_filter then
            filter = new_filter.select do |k,v|
              (keys_to_keep('update_dashboard_filter') + [:row]).include? k
            end
            say_warning "Updating filter #{existing_filter.id}" if @options[:debug]
            return update_dashboard_filter(existing_filter.id,filter)
          end
          say_warning "Deleting filter #{existing_filter.id}" if @options[:debug]
          return delete_dashboard_filter(existing_filter.id)
        end

        def sync_dashboard_element(new_element,existing_element,dashboard_id)
          if new_element && !existing_element then
            element = new_element.select do |k,v|
              (keys_to_keep('create_dashboard_element') - [:dashboard_id, :look_id, :query_id, :merge_result_id]).include? k
            end
            (element[:query_id],element[:look_id]) = process_dashboard_element(new_element) 
            say_warning "Creating dashboard element #{element.inspect}" if @options[:debug]
            element[:dashboard_id] = dashboard_id
            return [new_element[:id], create_dashboard_element(element).id]
          end
          if existing_element && new_element then
            element = keys_to_keep('update_dashboard_element').collect do |e|
              [e,nil]
            end.to_h

            element.merge!( new_element.select do |k,v|
              (keys_to_keep('update_dashboard_element') - [:dashboard_id, :look_id, :query_id, :merge_result_id]).include? k
            end
            )
            (element[:query_id],element[:look_id]) = process_dashboard_element(new_element) 
            say_warning "Updating dashboard element #{existing_element.id}" if @options[:debug]
            return [new_element[:id], update_dashboard_element(existing_element.id,element).id]
          end
          say_warning "Deleting dashboard element #{existing_element.id}" if @options[:debug]
          delete_dashboard_element(existing_element.id)
          return [nil,existing_element.id]
        end

        def process_dashboard_element(dash_elem)
          return [create_fetch_query(dash_elem[:query]).id, nil] if dash_elem[:query]
          return [nil, upsert_look(@me.id, create_fetch_query(dash_elem[:look][:query]).id, @dest_space_id, dash_elem[:look]).id] if dash_elem[:look]
          [nil,nil]
        end
<commit_msg>Fix copy of result_maker filterable array https://github.com/deangelo-llooker/gzr/issues/9<commit_after># frozen_string_literal: true

require_relative '../../../gzr'
require_relative '../../command'
require_relative '../../modules/dashboard'
require_relative '../../modules/look'
require_relative '../../modules/user'
require_relative '../../modules/plan'
require_relative '../../modules/filehelper'

module Gzr
  module Commands
    class Dashboard
      class Import < Gzr::Command
        include Gzr::Dashboard
        include Gzr::Look
        include Gzr::User
        include Gzr::Plan
        include Gzr::FileHelper
        def initialize(file, dest_space_id, options)
          super()
          @file = file
          @dest_space_id = dest_space_id
          @options = options
        end

        def execute(input: $stdin, output: $stdout)
          say_warning("options: #{@options.inspect}") if @options[:debug]
          with_session("3.1") do

            @me ||= query_me("id")

            read_file(@file) do |data|

              dashboard = sync_dashboard(data,@dest_space_id)

              pairs(data[:dashboard_filters],dashboard.dashboard_filters,dashboard.id) do |source,target,id|
                say_warning "Synching dashboard filter for dashboard #{id}" if @options[:debug]
                sync_dashboard_filter(source,target,id)
              end

              elem_table = pairs(data[:dashboard_elements],dashboard.dashboard_elements,dashboard.id) do |source,target,id|
                sync_dashboard_element(source,target,id)
              end

              pairs(data[:dashboard_layouts],dashboard.dashboard_layouts) do |s,t|
                sync_dashboard_layout(dashboard.id,s,t) do |s,t|
                  sync_dashboard_layout_component(s,t,elem_table)
                end
              end
              upsert_plans_for_dashboard(dashboard.id,@me.id,data[:scheduled_plans]) if data[:scheduled_plans]
              output.puts "Imported dashboard #{dashboard.id}" unless @options[:plain] 
              output.puts dashboard.id if @options[:plain] 
            end
          end
        end

        def sync_dashboard(source,target_space_id)
          existing_dashboard = search_dashboards_by_title(source[:title], target_space_id).fetch(0,nil)
          slug_used = search_dashboards_by_slug(source[:slug]).fetch(0,nil) if source[:slug]

          if slug_used then
            if existing_dashboard then
              if !(existing_dashboard.space_id == slug_used.space_id && existing_dashboard.title == slug_used.title) then
                say_warning "slug #{slug_used.slug} already used for dashboard #{slug_used.title} in space #{slug_used.space_id}"
                say_warning "dashboard will be imported with new slug"
              end
            else
              say_warning "slug #{slug_used.slug} already used for dashboard #{slug_used.title} in space #{slug_used.space_id}"
              say_warning "dashboard will be imported with new slug"
            end
          end

          if existing_dashboard then
            if @options[:force] then
              say_ok "Modifying existing dashboard #{existing_dashboard.id} #{existing_dashboard[:title]} in space #{target_space_id}"
              new_dash = source.select do |k,v|
                (keys_to_keep('update_dashboard') - [:space_id,:user_id,:title,:slug]).include? k
              end
              new_dash[:slug] = source[:slug] unless slug_used
              return update_dashboard(existing_dashboard.id,new_dash)
            else
              raise Gzr::CLI::Error, "Dashboard #{source[:title]} already exists in space #{target_space_id}\nUse --force if you want to overwrite it"
            end
          else
            new_dash = source.select do |k,v|
              (keys_to_keep('create_dashboard') - [:space_id,:user_id,:slug]).include? k
            end
            new_dash[:slug] = source[:slug] unless slug_used
            new_dash[:space_id] = target_space_id
            new_dash[:user_id] = @me.id
            return create_dashboard(new_dash)
          end
        end

        def sync_dashboard_filter(new_filter,existing_filter,dashboard_id)
          if new_filter && !existing_filter then
            filter = new_filter.select do |k,v|
              (keys_to_keep('create_dashboard_filter') + [:row]).include? k
            end
            filter[:dashboard_id] = dashboard_id
            say_warning "Creating filter" if @options[:debug]
            return create_dashboard_filter(filter)
          end
          if existing_filter && new_filter then
            filter = new_filter.select do |k,v|
              (keys_to_keep('update_dashboard_filter') + [:row]).include? k
            end
            say_warning "Updating filter #{existing_filter.id}" if @options[:debug]
            return update_dashboard_filter(existing_filter.id,filter)
          end
          say_warning "Deleting filter #{existing_filter.id}" if @options[:debug]
          return delete_dashboard_filter(existing_filter.id)
        end

        def copy_result_maker_filterables(new_element)
          if new_element.fetch(:result_maker,{}).fetch(:filterables,[]).length > 0
            result_maker = { :filterables => [] }
            new_element[:result_maker][:filterables].each do |filterable|
              result_maker[:filterables] << filterable.select do |k,v|
                true unless [:can].include? k
              end
            end
            return result_maker
          end
          nil
        end

        def sync_dashboard_element(new_element,existing_element,dashboard_id)
          if new_element && !existing_element then
            element = new_element.select do |k,v|
              (keys_to_keep('create_dashboard_element') - [:dashboard_id, :look_id, :query_id, :merge_result_id]).include? k
            end
            (element[:query_id],element[:look_id]) = process_dashboard_element(new_element) 
            say_warning "Creating dashboard element #{element.inspect}" if @options[:debug]
            element[:dashboard_id] = dashboard_id
            result_maker = copy_result_maker_filterables(new_element)
            element[:result_maker] = result_maker if result_maker
            return [new_element[:id], create_dashboard_element(element).id]
          end
          if existing_element && new_element then
            element = keys_to_keep('update_dashboard_element').collect do |e|
              [e,nil]
            end.to_h

            element.merge!( new_element.select do |k,v|
              (keys_to_keep('update_dashboard_element') - [:dashboard_id, :look_id, :query_id, :merge_result_id]).include? k
            end
            )
            (element[:query_id],element[:look_id]) = process_dashboard_element(new_element) 
            say_warning "Updating dashboard element #{existing_element.id}" if @options[:debug]
            result_maker = copy_result_maker_filterables(new_element)
            element[:result_maker] = result_maker if result_maker
            return [new_element[:id], update_dashboard_element(existing_element.id,element).id]
          end
          say_warning "Deleting dashboard element #{existing_element.id}" if @options[:debug]
          delete_dashboard_element(existing_element.id)
          return [nil,existing_element.id]
        end

        def process_dashboard_element(dash_elem)
          return [create_fetch_query(dash_elem[:query]).id, nil] if dash_elem[:query]
          return [nil, upsert_look(@me.id, create_fetch_query(dash_elem[:look][:query]).id, @dest_space_id, dash_elem[:look]).id] if dash_elem[:look]
          [nil,nil]
        end

{'fraction_non_alphanumeric': 0.10123269747262585, 'fraction_numerical': 0.0006886578059362303, 'mean_word_length': 2.4477682811016144, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '957321', 'n_tokens_mistral': 4050, 'n_tokens_neox': 4109, 'n_words': 823}