module Eco module API class Session class Config class TagTree < BaseConfig class MissingTagtree < StandardError end attr_key :file, :structure_id # @note it retrieves the tree this way: # 1. If there's a file tagtree.json file, it uses it # 2. If no file, retrieves `structure_id` (config) # @param include_archived [Boolean] whether or not it should include archived nodes. # @return [Eco::API::Organization::TagTree] def scope_tree(enviro: nil, include_archived: true, raise_on_missing: true) return @tagtree if instance_variable_defined?(:@tagtree) && @tagtree.enviro == enviro kargs = { enviro: enviro, includeArchivedNodes: include_archived } if tree_file = self.file if (tree = file_manager.load_json(tree_file)) && !tree.empty? @tagtree = Eco::API::Organization::TagTree.new(tree) end elsif self.structure_id kargs.merge(id: self.structure_id) end @tagtree ||= live_tree(**kargs).tap do |tree| unless tree && !tree.empty? msg = "Could not find a local or live locations structure." raise MissingTagtree, msg end end end # Among all the locations structures it selects the one with more location nodes # If `id` is provided, it only retrieves this locations structure. # @param [enviro] used for re-caching def live_tree(id: nil, enviro: nil, include_archived: false, **kargs, &block) existing_cache = !!@live_tree first_load = !existing_cache target_change = existing_cache && id && @live_tree.id != id enviro_change = existing_cache && enviro && @live_tree.enviro != enviro switching_target = existing_cache && (target_change || enviro_change) refresh_cache = existing_cache && !switching_target kargs = { includeArchivedNodes: include_archived }.merge(kargs) if id args = { id: id }.merge(kargs) @live_tree = live_tree_get(**args, &block) else trees = live_trees(**kargs, &block) @live_tree = trees.reject do |tree| tree.empty? end.max do |a,b| a.count <=> b.count end end.tap do |tree| if tree msg = "LIVE LOCATIONS Structure (#{tree.id}): '#{tree.name}' (#{tree.count} nodes)" if first_load session_logger.info("Using #{msg}") elsif switching_target session_logger.info("Switched to #{msg}") else # refresh_cache session_logger.debug("Reloading #{msg}") end else session_logger.info "Could not retrive live tree (#{id})" end end end # Gets a single locations structure # @note it does not memoize # @param include_archived [Boolean] whether or not to include archived **nodes** # @return [Eco::API::Organization::TagTree, NilClass] def live_tree_get(id: nil, include_archived: false, **kargs, &block) return nil unless apis.active_api.version_available?(:graphql) return nil unless graphql = apis.api(version: :graphql) kargs = { id: id, includeArchivedNodes: include_archived }.merge(kargs) return nil unless tree = graphql.currentOrganization.locationStructure(**kargs, &block) Eco::API::Organization::TagTree.new(tree.treeify, id: tree.id, name: tree.name) end # Retrieves all the location structures of the organisation # @param include_archived [Boolean] whether or not to include archived **nodes** # @return [Array] def live_trees(include_archived: false, **kargs, &block) [].tap do |eco_trees| next unless apis.active_api.version_available?(:graphql) next unless graphql = apis.api(version: :graphql) kargs = { includeArchivedNodes: include_archived }.merge(kargs) next unless trees = graphql.currentOrganization.locationStructures(**kargs, &block) trees.each do |tree| eco_tree = Eco::API::Organization::TagTree.new(tree.treeify, id: tree.id, name: tree.name) eco_trees.push(eco_tree) end end end private def session ASSETS.session end def session_logger session.logger end end end end end end