Skip to content

Commit

Permalink
Merge pull request #20 from rdytech/NEP-17500-update-tag-filter
Browse files Browse the repository at this point in the history
NEP-17500 Filter dashboards by array of tags
  • Loading branch information
jbat authored May 1, 2024
2 parents 054f657 + af1f2a8 commit 3247a47
Show file tree
Hide file tree
Showing 24 changed files with 568 additions and 28 deletions.
8 changes: 4 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ GIT
PATH
remote: .
specs:
superset (0.1.3)
superset (0.1.4)
dotenv (~> 2.7)
enumerate_it (~> 3.2)
enumerate_it (~> 1.7.0)
faraday (~> 1.0)
faraday-multipart (~> 1.0)
json (~> 2.6)
Expand Down Expand Up @@ -51,8 +51,8 @@ GEM
dotenv (2.8.1)
drb (2.2.0)
ruby2_keywords
enumerate_it (3.2.4)
activesupport (>= 5.0.7.2)
enumerate_it (1.7.0)
activesupport (>= 3.0.0)
faraday (1.10.3)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
Expand Down
40 changes: 40 additions & 0 deletions lib/superset/chart/bulk_delete.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true
# TODO: the gui delete has a confirmation step, this API call does not.
# Potentially we could add a confirm_delete parameter to the constructor that would ensure that all charts either
# 1 belong to only an expected dashboard before deleting
# 2 or do not belong to any dashboards
# ( not sure if this needed at this point )

module Superset
module Chart
class BulkDelete < Superset::Request
attr_reader :chart_ids

def initialize(chart_ids: [])
@chart_ids = chart_ids
end

def perform
raise InvalidParameterError, "chart_ids array of integers expected" unless chart_ids.is_a?(Array)
raise InvalidParameterError, "chart_ids array must contain Integer only values" unless chart_ids.all? { |item| item.is_a?(Integer) }

logger.info("Attempting to delete charts with id: #{chart_ids.join(', ')}")
response
end

def response
@response ||= client.delete(route, params)
end

private

def params
{ q: "!(#{chart_ids.join(',')})" }
end

def route
"chart/"
end
end
end
end
30 changes: 30 additions & 0 deletions lib/superset/chart/delete.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module Superset
module Chart
class Delete < Superset::Request
attr_reader :chart_id

def initialize(chart_id: )
@chart_id = chart_id
end

def perform
raise InvalidParameterError, "chart_id integer is required" unless chart_id.present? && chart_id.is_a?(Integer)

logger.info("Attempting to delete chart with id: #{chart_id}")
response
end

def response
@response ||= client.delete(route)
end

private

def route
"chart/#{chart_id}"
end
end
end
end
41 changes: 41 additions & 0 deletions lib/superset/dashboard/bulk_delete.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# frozen_string_literal: true

# TODO: the gui delete has a confirmation step, this API call does not.
# Potentially we could add a confirm_delete parameter to the constructor that would ensure that all dashboards either
# 1 have an expected set of charts or filters before deleting
# 2 or do not have any charts or filters linked to them
# ( not sure if this needed at this point )

module Superset
module Dashboard
class BulkDelete < Superset::Request
attr_reader :dashboard_ids

def initialize(dashboard_ids: [])
@dashboard_ids = dashboard_ids
end

def perform
raise InvalidParameterError, "dashboard_ids array of integers expected" unless dashboard_ids.is_a?(Array)
raise InvalidParameterError, "dashboard_ids array must contain Integer only values" unless dashboard_ids.all? { |item| item.is_a?(Integer) }

logger.info("Attempting to delete dashboards with id: #{dashboard_ids.join(', ')}")
response
end

def response
@response ||= client.delete(route, params)
end

private

def params
{ q: "!(#{dashboard_ids.join(',')})" }
end

def route
"dashboard/"
end
end
end
end
4 changes: 2 additions & 2 deletions lib/superset/dashboard/charts/list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def rows
c[:id],
c[:slice_name],
c[:form_data][:datasource],
c[:form_data][:dashboards]
# c[:form_data][:dashboards] # NOTE: form_data dashboards is not accurate .. looks to be bugs related to copying charts
]
end
end
Expand All @@ -34,7 +34,7 @@ def route
end

def list_attributes
['id', 'slice_name', 'datasource', 'dashboards'].map(&:to_sym)
['id', 'slice_name', 'datasource'].map(&:to_sym)
end

# when displaying a list of datasets, show dashboard id and title as well
Expand Down
42 changes: 42 additions & 0 deletions lib/superset/dashboard/delete.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# frozen_string_literal: true

module Superset
module Dashboard
class Delete < Superset::Request

attr_reader :dashboard_id, :confirm_zero_charts

def initialize(dashboard_id: , confirm_zero_charts: true)
@dashboard_id = dashboard_id
@confirm_zero_charts = confirm_zero_charts
end

def perform
raise InvalidParameterError, "dashboard_id integer is required" unless dashboard_id.present? && dashboard_id.is_a?(Integer)

confirm_zero_charts_on_dashboard if confirm_zero_charts

logger.info("Attempting to delete dashboard with id: #{dashboard_id}")
response
end

def response
@response ||= client.delete(route)
end

private

def confirm_zero_charts_on_dashboard
raise "Error: Dashboard includes #{dashboard_charts.count} charts. Please delete all charts before deleting the dashboard or override and set confirm_zero_charts: false" if dashboard_charts.count.positive?
end

def dashboard_charts
@dashboard_charts ||= Superset::Dashboard::Charts::List.new(dashboard_id).rows
end

def route
"dashboard/#{dashboard_id}"
end
end
end
end
2 changes: 1 addition & 1 deletion lib/superset/dashboard/embedded/get.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def initialize(id)
def response
@response ||= client.get(route)
rescue Happi::Error::NotFound => e
puts "Dashboard #{id} has no Embedded settings. (skipping)" # some dashboards don't have embedded settings, fine to ignore.
logger.info("Dashboard #{id} has no Embedded settings. (skipping)") # some dashboards don't have embedded settings, fine to ignore.
@response = { result: [] }.with_indifferent_access
@response
end
Expand Down
1 change: 1 addition & 0 deletions lib/superset/dashboard/info.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module Superset
module Dashboard
class Info < Superset::Request
alias result response

def filters
result['filters']
Expand Down
40 changes: 35 additions & 5 deletions lib/superset/dashboard/list.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
# Usage: Superset::Dashboard::List.new.list
# Usage: Superset::Dashboard::List.new(page_num: 1, title_contains: 'Test').list
# Usage: Superset::Dashboard::List.new(tags_equal: ['embedded', 'product:acme']).list

module Superset
module Dashboard
class List < Superset::Request
attr_reader :title_contains, :tag_equals
attr_reader :title_contains, :tags_equal, :ids_not_in

def initialize(page_num: 0, title_contains: '', tag_equals: '')
def initialize(page_num: 0, title_contains: '', tags_equal: [], ids_not_in: [])
@title_contains = title_contains
@tag_equals = tag_equals
@tags_equal = tags_equal
@ids_not_in = ids_not_in
super(page_num: page_num)
end

def self.call
self.new.list
end

def response
validate_constructor_args
super
end

def all
result.map do |d|
OpenStruct.new(
Expand Down Expand Up @@ -45,6 +55,10 @@ def rows
end
end

def ids
result.map { |d| d[:id] }
end

private

def route
Expand All @@ -55,15 +69,31 @@ def filters
# TODO filtering across all list classes can be refactored to support multiple options in a more flexible way
filter_set = []
filter_set << "(col:dashboard_title,opr:ct,value:'#{title_contains}')" if title_contains.present?
filter_set << "(col:tags,opr:dashboard_tags,value:#{tag_equals})" if tag_equals.present?
filter_set << tag_filters if tags_equal.present?
filter_set << ids_not_in_filters if ids_not_in.present?
unless filter_set.empty?
"filters:!(" + filter_set.join(',') + "),"
end
end

def tag_filters
tags_equal.map {|tag| "(col:tags,opr:dashboard_tags,value:'#{tag}')"}.join(',')
end

def ids_not_in_filters
ids_not_in.map {|id| "(col:id,opr:neq,value:'#{id}')"}.join(',')
end

def list_attributes
[:id, :dashboard_title, :status, :url]
end

def validate_constructor_args
raise InvalidParameterError, "title_contains must be a String type" unless title_contains.is_a?(String)
raise InvalidParameterError, "tags_equal must be an Array type" unless tags_equal.is_a?(Array)
raise InvalidParameterError, "tags_equal array must contain string only values" unless tags_equal.all? { |item| item.is_a?(String) }
raise InvalidParameterError, "ids_not_in must be an Array type" unless ids_not_in.is_a?(Array)
end
end
end
end
end
41 changes: 41 additions & 0 deletions lib/superset/dataset/bulk_delete.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# frozen_string_literal: true

# TODO: the gui delete has a confirmation step, this API call does not.
# Potentially we could add a confirm_delete parameter to the constructor that would ensure that all datasets either
# 1 belong to only an expected charts or filters before deleting
# 2 or do not belong to any charts or filters
# ( not sure if this needed at this point )

module Superset
module Dataset
class BulkDelete < Superset::Request
attr_reader :dataset_ids

def initialize(dataset_ids: [])
@dataset_ids = dataset_ids
end

def perform
raise InvalidParameterError, "dataset_ids array of integers expected" unless dataset_ids.is_a?(Array)
raise InvalidParameterError, "dataset_ids array must contain Integer only values" unless dataset_ids.all? { |item| item.is_a?(Integer) }

logger.info("Attempting to delete datasets with id: #{dataset_ids.join(', ')}")
response
end

def response
@response ||= client.delete(route, params)
end

private

def params
{ q: "!(#{dataset_ids.join(',')})" }
end

def route
"dataset/"
end
end
end
end
30 changes: 30 additions & 0 deletions lib/superset/dataset/delete.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module Superset
module Dataset
class Delete < Superset::Request
attr_reader :dataset_id

def initialize(dataset_id: )
@dataset_id = dataset_id
end

def perform
raise InvalidParameterError, "dataset_id integer is required" unless dataset_id.present? && dataset_id.is_a?(Integer)

logger.info("Attempting to delete dataset with id: #{dataset_id}")
response
end

def response
@response ||= client.delete(route)
end

private

def route
"dataset/#{dataset_id}"
end
end
end
end
Loading

0 comments on commit 3247a47

Please sign in to comment.