agave-client 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +14 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/CONTRIBUTORS.md +34 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +29 -0
- data/README.md +41 -0
- data/Rakefile +7 -0
- data/agave-client.gemspec +63 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/exe/agave +10 -0
- data/lib/agave.rb +11 -0
- data/lib/agave/api_client.rb +97 -0
- data/lib/agave/api_error.rb +23 -0
- data/lib/agave/cli.rb +93 -0
- data/lib/agave/dump/dsl/add_to_data_file.rb +14 -0
- data/lib/agave/dump/dsl/create_data_file.rb +14 -0
- data/lib/agave/dump/dsl/create_post.rb +33 -0
- data/lib/agave/dump/dsl/directory.rb +30 -0
- data/lib/agave/dump/dsl/root.rb +37 -0
- data/lib/agave/dump/format.rb +28 -0
- data/lib/agave/dump/format/json.rb +18 -0
- data/lib/agave/dump/format/toml.rb +31 -0
- data/lib/agave/dump/format/yaml.rb +55 -0
- data/lib/agave/dump/operation/add_to_data_file.rb +41 -0
- data/lib/agave/dump/operation/create_data_file.rb +28 -0
- data/lib/agave/dump/operation/create_post.rb +34 -0
- data/lib/agave/dump/operation/directory.rb +34 -0
- data/lib/agave/dump/operation/root.rb +27 -0
- data/lib/agave/dump/runner.rb +47 -0
- data/lib/agave/dump/ssg_detector.rb +36 -0
- data/lib/agave/json_api_deserializer.rb +38 -0
- data/lib/agave/json_api_serializer.rb +145 -0
- data/lib/agave/local/entities_repo.rb +46 -0
- data/lib/agave/local/field_type/boolean.rb +12 -0
- data/lib/agave/local/field_type/color.rb +63 -0
- data/lib/agave/local/field_type/date.rb +12 -0
- data/lib/agave/local/field_type/date_time.rb +12 -0
- data/lib/agave/local/field_type/file.rb +65 -0
- data/lib/agave/local/field_type/float.rb +12 -0
- data/lib/agave/local/field_type/gallery.rb +23 -0
- data/lib/agave/local/field_type/global_seo.rb +56 -0
- data/lib/agave/local/field_type/image.rb +82 -0
- data/lib/agave/local/field_type/integer.rb +12 -0
- data/lib/agave/local/field_type/json.rb +13 -0
- data/lib/agave/local/field_type/lat_lon.rb +30 -0
- data/lib/agave/local/field_type/link.rb +12 -0
- data/lib/agave/local/field_type/links.rb +21 -0
- data/lib/agave/local/field_type/rich_text.rb +21 -0
- data/lib/agave/local/field_type/seo.rb +33 -0
- data/lib/agave/local/field_type/slug.rb +12 -0
- data/lib/agave/local/field_type/string.rb +12 -0
- data/lib/agave/local/field_type/text.rb +12 -0
- data/lib/agave/local/field_type/theme.rb +43 -0
- data/lib/agave/local/field_type/video.rb +77 -0
- data/lib/agave/local/item.rb +179 -0
- data/lib/agave/local/items_repo.rb +210 -0
- data/lib/agave/local/json_api_entity.rb +78 -0
- data/lib/agave/local/loader.rb +60 -0
- data/lib/agave/local/site.rb +73 -0
- data/lib/agave/paginator.rb +33 -0
- data/lib/agave/repo.rb +93 -0
- data/lib/agave/site/client.rb +24 -0
- data/lib/agave/upload/file.rb +92 -0
- data/lib/agave/upload/image.rb +8 -0
- data/lib/agave/utils/favicon_tags_builder.rb +85 -0
- data/lib/agave/utils/locale_value.rb +15 -0
- data/lib/agave/utils/meta_tags/article_modified_time.rb +15 -0
- data/lib/agave/utils/meta_tags/article_publisher.rb +18 -0
- data/lib/agave/utils/meta_tags/base.rb +55 -0
- data/lib/agave/utils/meta_tags/description.rb +24 -0
- data/lib/agave/utils/meta_tags/image.rb +35 -0
- data/lib/agave/utils/meta_tags/og_locale.rb +15 -0
- data/lib/agave/utils/meta_tags/og_site_name.rb +18 -0
- data/lib/agave/utils/meta_tags/og_type.rb +18 -0
- data/lib/agave/utils/meta_tags/robots.rb +14 -0
- data/lib/agave/utils/meta_tags/title.rb +46 -0
- data/lib/agave/utils/meta_tags/twitter_card.rb +14 -0
- data/lib/agave/utils/meta_tags/twitter_site.rb +18 -0
- data/lib/agave/utils/seo_tags_builder.rb +45 -0
- data/lib/agave/version.rb +4 -0
- data/lib/agave/watch/site_change_watcher.rb +37 -0
- metadata +504 -0
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            require 'fileutils'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module Agave
         | 
| 5 | 
            +
              module Dump
         | 
| 6 | 
            +
                module Operation
         | 
| 7 | 
            +
                  class Directory
         | 
| 8 | 
            +
                    attr_reader :context, :path
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    def initialize(context, path)
         | 
| 11 | 
            +
                      @context = context
         | 
| 12 | 
            +
                      @path = File.join(context.path, path)
         | 
| 13 | 
            +
                      @operations = []
         | 
| 14 | 
            +
                    end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                    def add(operation)
         | 
| 17 | 
            +
                      @operations << operation
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    def perform
         | 
| 21 | 
            +
                      FileUtils.remove_dir(path) if Dir.exist?(path)
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                      FileUtils.mkdir_p(path)
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                      operations.each(&:perform)
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    private
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    attr_reader :operations
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            module Agave
         | 
| 3 | 
            +
              module Dump
         | 
| 4 | 
            +
                module Operation
         | 
| 5 | 
            +
                  class Root
         | 
| 6 | 
            +
                    attr_reader :path
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                    def initialize(path)
         | 
| 9 | 
            +
                      @operations = []
         | 
| 10 | 
            +
                      @path = path
         | 
| 11 | 
            +
                    end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    def add(operation)
         | 
| 14 | 
            +
                      @operations << operation
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    def perform
         | 
| 18 | 
            +
                      operations.each(&:perform)
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    private
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    attr_reader :operations
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,47 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            require 'agave/dump/dsl/root'
         | 
| 3 | 
            +
            require 'agave/dump/operation/root'
         | 
| 4 | 
            +
            require 'agave/dump/ssg_detector'
         | 
| 5 | 
            +
            require 'agave/local/loader'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module Agave
         | 
| 8 | 
            +
              module Dump
         | 
| 9 | 
            +
                class Runner
         | 
| 10 | 
            +
                  attr_reader :config_path, :client, :destination_path, :preview_mode
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def initialize(config_path, client, preview_mode, destination_path = Dir.pwd)
         | 
| 13 | 
            +
                    @config_path = config_path
         | 
| 14 | 
            +
                    @preview_mode = preview_mode
         | 
| 15 | 
            +
                    @client = client
         | 
| 16 | 
            +
                    @destination_path = destination_path
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  def run
         | 
| 20 | 
            +
                    print 'Fetching content from AgaveCMS... '
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    loader.load
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    I18n.available_locales = loader.items_repo.available_locales
         | 
| 25 | 
            +
                    I18n.locale = I18n.available_locales.first
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    Dsl::Root.new(
         | 
| 28 | 
            +
                      File.read(config_path),
         | 
| 29 | 
            +
                      loader.items_repo,
         | 
| 30 | 
            +
                      operation
         | 
| 31 | 
            +
                    )
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    operation.perform
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    puts "\e[32m✓\e[0m Done!"
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  def operation
         | 
| 39 | 
            +
                    @operation ||= Operation::Root.new(destination_path)
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  def loader
         | 
| 43 | 
            +
                    @loader ||= Agave::Local::Loader.new(client, preview_mode)
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
            end
         | 
| @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            require 'toml'
         | 
| 3 | 
            +
            require 'json'
         | 
| 4 | 
            +
            require 'yaml'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module Agave
         | 
| 7 | 
            +
              module Dump
         | 
| 8 | 
            +
                class SsgDetector
         | 
| 9 | 
            +
                  attr_reader :path
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  RUBY = %w(jekyll).freeze
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  def initialize(path)
         | 
| 14 | 
            +
                    @path = path
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def detect
         | 
| 18 | 
            +
                    ruby_generator ||
         | 
| 19 | 
            +
                      'unknown'
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  private
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  def ruby_generator
         | 
| 25 | 
            +
                    gemfile_path = File.join(path, 'Gemfile')
         | 
| 26 | 
            +
                    return unless File.exist?(gemfile_path)
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    gemfile = File.read(gemfile_path)
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    RUBY.find do |generator|
         | 
| 31 | 
            +
                      gemfile =~ /('#{generator}'|"#{generator}")/
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            module Agave
         | 
| 3 | 
            +
              class JsonApiDeserializer
         | 
| 4 | 
            +
                def deserialize(data)
         | 
| 5 | 
            +
                  data = data[:data]
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  if data.is_a? Array
         | 
| 8 | 
            +
                    data.map { |resource| deserialize_resource(resource) }
         | 
| 9 | 
            +
                  else
         | 
| 10 | 
            +
                    deserialize_resource(data)
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def deserialize_resource(data)
         | 
| 15 | 
            +
                  result = { id: data[:id] }
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  if data[:attributes]
         | 
| 18 | 
            +
                    result.merge!(data[:attributes])
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  relationships = data.delete(:relationships)
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  if relationships
         | 
| 24 | 
            +
                    relationships.each do |key, handle|
         | 
| 25 | 
            +
                      handle_data = handle['data']
         | 
| 26 | 
            +
                      value = if handle_data.is_a? Array
         | 
| 27 | 
            +
                                handle_data.map { |ref| ref['id'] }
         | 
| 28 | 
            +
                              elsif handle_data.is_a? Hash
         | 
| 29 | 
            +
                                handle_data[:id]
         | 
| 30 | 
            +
                              end
         | 
| 31 | 
            +
                      result[key] = value
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  result.with_indifferent_access
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            end
         | 
| @@ -0,0 +1,145 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            module Agave
         | 
| 3 | 
            +
              class JsonApiSerializer
         | 
| 4 | 
            +
                attr_reader :link, :type
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                def initialize(type, link)
         | 
| 7 | 
            +
                  @link = link
         | 
| 8 | 
            +
                  @type = type
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def serialize(resource, id = nil)
         | 
| 12 | 
            +
                  resource = resource.with_indifferent_access
         | 
| 13 | 
            +
                  data = {}
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  data[:id] = id || resource[:id] if id || resource[:id]
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  data[:type] = type
         | 
| 18 | 
            +
                  data[:attributes] = serialized_attributes(resource)
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  if relationships.any?
         | 
| 21 | 
            +
                    data[:relationships] = serialized_relationships(resource)
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  { data: data }
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def serialized_attributes(resource)
         | 
| 28 | 
            +
                  result = {}
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  attributes(resource).each do |attribute|
         | 
| 31 | 
            +
                    if resource.key? attribute
         | 
| 32 | 
            +
                      result[attribute] = resource[attribute]
         | 
| 33 | 
            +
                    elsif required_attributes.include? attribute
         | 
| 34 | 
            +
                      throw "Required attribute: #{attribute}"
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  result
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                def serialized_relationships(resource)
         | 
| 42 | 
            +
                  result = {}
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  relationships.each do |relationship, meta|
         | 
| 45 | 
            +
                    if resource.key? relationship
         | 
| 46 | 
            +
                      value = resource[relationship]
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                      data = if value
         | 
| 49 | 
            +
                               if meta[:collection]
         | 
| 50 | 
            +
                                 value.map do |id|
         | 
| 51 | 
            +
                                   { type: meta[:type], id: id.to_s }
         | 
| 52 | 
            +
                                 end
         | 
| 53 | 
            +
                               else
         | 
| 54 | 
            +
                                 { type: meta[:type], id: value.to_s }
         | 
| 55 | 
            +
                               end
         | 
| 56 | 
            +
                             end
         | 
| 57 | 
            +
                      result[relationship] = { data: data }
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                    elsif required_relationships.include?(relationship)
         | 
| 60 | 
            +
                      throw "Required attribute: #{relationship}"
         | 
| 61 | 
            +
                    end
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                  result
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                def attributes(resource)
         | 
| 68 | 
            +
                  if type == "item"
         | 
| 69 | 
            +
                    return resource.keys.map(&:to_sym) - [
         | 
| 70 | 
            +
                      :item_type,
         | 
| 71 | 
            +
                      :id,
         | 
| 72 | 
            +
                      :created_at,
         | 
| 73 | 
            +
                      :updated_at,
         | 
| 74 | 
            +
                      :is_valid,
         | 
| 75 | 
            +
                      :published_version,
         | 
| 76 | 
            +
                      :current_version
         | 
| 77 | 
            +
                    ]
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  link_attributes["properties"].keys.map(&:to_sym)
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                def required_attributes
         | 
| 84 | 
            +
                  if type == "item"
         | 
| 85 | 
            +
                    return []
         | 
| 86 | 
            +
                  end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                  (link_attributes.required || []).map(&:to_sym)
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                def relationships
         | 
| 92 | 
            +
                  if type == "item"
         | 
| 93 | 
            +
                    if link.rel == :create
         | 
| 94 | 
            +
                      return { item_type: { collection: false, type: 'item_type' } }
         | 
| 95 | 
            +
                    else
         | 
| 96 | 
            +
                      {}
         | 
| 97 | 
            +
                    end
         | 
| 98 | 
            +
                  end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                  if !link_relationships
         | 
| 101 | 
            +
                    return {}
         | 
| 102 | 
            +
                  end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                  link_relationships.properties.reduce({}) do |acc, (relationship, schema)|
         | 
| 105 | 
            +
                    is_collection = schema.properties["data"].type.first == 'array'
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                    definition = if is_collection
         | 
| 108 | 
            +
                                   schema.properties['data'].items
         | 
| 109 | 
            +
                                 elsif schema.properties['data'].type.first == 'object'
         | 
| 110 | 
            +
                                   schema.properties['data']
         | 
| 111 | 
            +
                                 else
         | 
| 112 | 
            +
                                   schema.properties['data'].any_of.find do |option|
         | 
| 113 | 
            +
                                     option.type.first == 'object'
         | 
| 114 | 
            +
                                   end
         | 
| 115 | 
            +
                                 end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                    type = definition.properties['type']
         | 
| 118 | 
            +
                                     .pattern.source.gsub(/(^\^|\$$)/, '')
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                    acc[relationship.to_sym] = {
         | 
| 121 | 
            +
                      collection: is_collection,
         | 
| 122 | 
            +
                      type: type,
         | 
| 123 | 
            +
                    }
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                    acc
         | 
| 126 | 
            +
                  end
         | 
| 127 | 
            +
                end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                def required_relationships
         | 
| 130 | 
            +
                  if type == "item"
         | 
| 131 | 
            +
                    return %i(item_type)
         | 
| 132 | 
            +
                  end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                  (link_relationships.required || []).map(&:to_sym)
         | 
| 135 | 
            +
                end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                def link_attributes
         | 
| 138 | 
            +
                  link.schema.properties["data"].properties["attributes"]
         | 
| 139 | 
            +
                end
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                def link_relationships
         | 
| 142 | 
            +
                  link.schema.properties["data"].properties["relationships"]
         | 
| 143 | 
            +
                end
         | 
| 144 | 
            +
              end
         | 
| 145 | 
            +
            end
         | 
| @@ -0,0 +1,46 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            require 'agave/local/json_api_entity'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module Agave
         | 
| 5 | 
            +
              module Local
         | 
| 6 | 
            +
                class EntitiesRepo
         | 
| 7 | 
            +
                  attr_reader :entities
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  def initialize(*payloads)
         | 
| 10 | 
            +
                    @entities = {}
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    payloads.each do |payload|
         | 
| 13 | 
            +
                      EntitiesRepo.payload_entities(payload).each do |entity_payload|
         | 
| 14 | 
            +
                        object = JsonApiEntity.new(entity_payload, self)
         | 
| 15 | 
            +
                        @entities[object.type] ||= {}
         | 
| 16 | 
            +
                        @entities[object.type][object.id] = object
         | 
| 17 | 
            +
                      end
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def find_entities_of_type(type)
         | 
| 22 | 
            +
                    entities.fetch(type, {}).values
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  def find_entity(type, id)
         | 
| 26 | 
            +
                    entities.fetch(type, {}).fetch(id, nil)
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  def self.payload_entities(payload)
         | 
| 30 | 
            +
                    acc = []
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                    if payload[:data]
         | 
| 33 | 
            +
                      acc = if payload[:data].is_a? Array
         | 
| 34 | 
            +
                              acc + payload[:data]
         | 
| 35 | 
            +
                            else
         | 
| 36 | 
            +
                              acc + [payload[:data]]
         | 
| 37 | 
            +
                            end
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    acc += payload[:included] if payload[:included]
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    acc
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
            end
         | 
| @@ -0,0 +1,63 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            module Agave
         | 
| 4 | 
            +
              module Local
         | 
| 5 | 
            +
                module FieldType
         | 
| 6 | 
            +
                  class Color
         | 
| 7 | 
            +
                    attr_reader :red, :green, :blue, :alpha
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    def self.parse(value, _repo)
         | 
| 10 | 
            +
                      value && new(
         | 
| 11 | 
            +
                        value[:red],
         | 
| 12 | 
            +
                        value[:green],
         | 
| 13 | 
            +
                        value[:blue],
         | 
| 14 | 
            +
                        value[:alpha]
         | 
| 15 | 
            +
                      )
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    def initialize(red, green, blue, alpha)
         | 
| 19 | 
            +
                      @red = red
         | 
| 20 | 
            +
                      @green = green
         | 
| 21 | 
            +
                      @blue = blue
         | 
| 22 | 
            +
                      @alpha = alpha / 255.0
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    def rgb
         | 
| 26 | 
            +
                      if alpha == 1.0
         | 
| 27 | 
            +
                        "rgb(#{red}, #{green}, #{blue})"
         | 
| 28 | 
            +
                      else #
         | 
| 29 | 
            +
                        "rgba(#{red}, #{green}, #{blue}, #{alpha})"
         | 
| 30 | 
            +
                      end
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    def hex
         | 
| 34 | 
            +
                      r = red.to_s(16)
         | 
| 35 | 
            +
                      g = green.to_s(16)
         | 
| 36 | 
            +
                      b = blue.to_s(16)
         | 
| 37 | 
            +
                      a = (alpha * 255).to_i.to_s(16)
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                      r = "0#{r}" if r.length == 1
         | 
| 40 | 
            +
                      g = "0#{g}" if g.length == 1
         | 
| 41 | 
            +
                      b = "0#{b}" if b.length == 1
         | 
| 42 | 
            +
                      a = "0#{a}" if a.length == 1
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                      hex = '#' + r + g + b
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                      hex += a if a != 'ff'
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                      hex
         | 
| 49 | 
            +
                    end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    def to_hash(*_args)
         | 
| 52 | 
            +
                      {
         | 
| 53 | 
            +
                        red: red,
         | 
| 54 | 
            +
                        green: green,
         | 
| 55 | 
            +
                        blue: blue,
         | 
| 56 | 
            +
                        rgb: rgb,
         | 
| 57 | 
            +
                        hex: hex
         | 
| 58 | 
            +
                      }
         | 
| 59 | 
            +
                    end
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
            end
         |