dato 0.1.5 → 0.1.6
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 +4 -4
- data/.rubocop.yml +24 -0
- data/Gemfile +1 -0
- data/Rakefile +25 -9
- data/bin/console +4 -3
- data/dato.gemspec +28 -23
- data/lib/dato.rb +5 -3
- data/lib/dato/account/client.rb +6 -5
- data/lib/dato/account/repo/account.rb +9 -10
- data/lib/dato/account/repo/base.rb +3 -3
- data/lib/dato/account/repo/site.rb +7 -8
- data/lib/dato/api_error.rb +3 -2
- data/lib/dato/json_api_deserializer.rb +7 -9
- data/lib/dato/json_api_serializer.rb +4 -5
- data/lib/dato/local/entities_repo.rb +46 -0
- data/lib/dato/local/field_type/boolean.rb +12 -0
- data/lib/dato/local/field_type/date.rb +12 -0
- data/lib/dato/local/field_type/date_time.rb +12 -0
- data/lib/dato/local/field_type/file.rb +33 -0
- data/lib/dato/local/field_type/float.rb +12 -0
- data/lib/dato/local/field_type/image.rb +32 -0
- data/lib/dato/local/field_type/integer.rb +12 -0
- data/lib/dato/local/field_type/lat_lon.rb +23 -0
- data/lib/dato/local/field_type/link.rb +12 -0
- data/lib/dato/local/field_type/links.rb +12 -0
- data/lib/dato/local/field_type/seo.rb +24 -0
- data/lib/dato/local/field_type/string.rb +12 -0
- data/lib/dato/local/field_type/text.rb +12 -0
- data/lib/dato/local/field_type/video.rb +55 -0
- data/lib/dato/local/item.rb +121 -0
- data/lib/dato/local/items_repo.rb +110 -0
- data/lib/dato/local/json_api_entity.rb +78 -0
- data/lib/dato/local/site.rb +57 -0
- data/lib/dato/site/client.rb +6 -5
- data/lib/dato/site/repo/base.rb +3 -2
- data/lib/dato/site/repo/field.rb +3 -4
- data/lib/dato/site/repo/item.rb +6 -7
- data/lib/dato/site/repo/item_type.rb +6 -7
- data/lib/dato/site/repo/menu_item.rb +8 -9
- data/lib/dato/site/repo/site.rb +5 -6
- data/lib/dato/site/repo/upload_request.rb +3 -4
- data/lib/dato/site/repo/user.rb +8 -9
- data/lib/dato/upload/file.rb +6 -5
- data/lib/dato/upload/image.rb +3 -3
- data/lib/dato/version.rb +2 -1
- metadata +77 -1
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'imgix'
|
3
|
+
|
4
|
+
module Dato
|
5
|
+
module Local
|
6
|
+
module FieldType
|
7
|
+
class File
|
8
|
+
attr_reader :path, :format, :size
|
9
|
+
|
10
|
+
def self.parse(value, _repo)
|
11
|
+
new(
|
12
|
+
value[:path],
|
13
|
+
value[:format],
|
14
|
+
value[:size]
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(path, format, size)
|
19
|
+
@path = path
|
20
|
+
@format = format
|
21
|
+
@size = size
|
22
|
+
end
|
23
|
+
|
24
|
+
def file
|
25
|
+
Imgix::Client.new(
|
26
|
+
host: 'dato-images.imgix.net',
|
27
|
+
secure: true
|
28
|
+
).path(path)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'dato/local/field_type/file'
|
3
|
+
|
4
|
+
module Dato
|
5
|
+
module Local
|
6
|
+
module FieldType
|
7
|
+
class Image < Dato::Local::FieldType::File
|
8
|
+
attr_reader :width, :height
|
9
|
+
|
10
|
+
def self.parse(value, _repo)
|
11
|
+
new(
|
12
|
+
value[:path],
|
13
|
+
value[:format],
|
14
|
+
value[:size],
|
15
|
+
value[:width],
|
16
|
+
value[:height]
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(path, format, size, width, height)
|
21
|
+
super(path, format, size)
|
22
|
+
@width = width
|
23
|
+
@height = height
|
24
|
+
end
|
25
|
+
|
26
|
+
def file
|
27
|
+
super.ch('DPR', 'Width').auto('compress', 'format')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Dato
|
3
|
+
module Local
|
4
|
+
module FieldType
|
5
|
+
class LatLon
|
6
|
+
attr_reader :latitude, :longitude
|
7
|
+
|
8
|
+
def self.parse(value, _repo)
|
9
|
+
new(value[:latitude], value[:longitude])
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(latitude, longitude)
|
13
|
+
@latitude = latitude
|
14
|
+
@longitude = longitude
|
15
|
+
end
|
16
|
+
|
17
|
+
def values
|
18
|
+
[latitude, longitude]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Dato
|
3
|
+
module Local
|
4
|
+
module FieldType
|
5
|
+
class Seo
|
6
|
+
attr_reader :title, :description
|
7
|
+
|
8
|
+
def self.parse(value, _repo)
|
9
|
+
new(value[:title], value[:description], value[:image])
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(title, description, image)
|
13
|
+
@title = title
|
14
|
+
@description = description
|
15
|
+
@image = image
|
16
|
+
end
|
17
|
+
|
18
|
+
def image
|
19
|
+
@image && Image.parse(@image, nil)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'active_support/core_ext/hash/compact'
|
3
|
+
require 'video_embed'
|
4
|
+
|
5
|
+
module Dato
|
6
|
+
module Local
|
7
|
+
module FieldType
|
8
|
+
class Video
|
9
|
+
def self.parse(value, _repo)
|
10
|
+
new(value)
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(attributes)
|
14
|
+
@attributes = attributes
|
15
|
+
end
|
16
|
+
|
17
|
+
def url
|
18
|
+
@attributes[:url]
|
19
|
+
end
|
20
|
+
|
21
|
+
def thumbnail_url
|
22
|
+
@attributes[:thumbnail_url]
|
23
|
+
end
|
24
|
+
|
25
|
+
def title
|
26
|
+
@attributes[:title]
|
27
|
+
end
|
28
|
+
|
29
|
+
def width
|
30
|
+
@attributes[:width]
|
31
|
+
end
|
32
|
+
|
33
|
+
def height
|
34
|
+
@attributes[:height]
|
35
|
+
end
|
36
|
+
|
37
|
+
def provider
|
38
|
+
@attributes[:provider]
|
39
|
+
end
|
40
|
+
|
41
|
+
def provider_url
|
42
|
+
@attributes[:provider_url]
|
43
|
+
end
|
44
|
+
|
45
|
+
def provider_uid
|
46
|
+
@attributes[:provider_uid]
|
47
|
+
end
|
48
|
+
|
49
|
+
def iframe_embed(width = nil, height = nil)
|
50
|
+
VideoEmbed.embed(url, { width: width, height: height }.compact)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'forwardable'
|
3
|
+
require 'active_support/inflector/transliterate'
|
4
|
+
require 'active_support/hash_with_indifferent_access'
|
5
|
+
|
6
|
+
Dir[File.dirname(__FILE__) + '/field_type/*.rb'].each do |file|
|
7
|
+
require file
|
8
|
+
end
|
9
|
+
|
10
|
+
module Dato
|
11
|
+
module Local
|
12
|
+
class Item
|
13
|
+
extend Forwardable
|
14
|
+
|
15
|
+
attr_reader :entity
|
16
|
+
def_delegators :entity, :id, :type, :item_type
|
17
|
+
|
18
|
+
def initialize(entity, items_repo)
|
19
|
+
@entity = entity
|
20
|
+
@items_repo = items_repo
|
21
|
+
end
|
22
|
+
|
23
|
+
def ==(other)
|
24
|
+
other.is_a?(Item) && other.id == id
|
25
|
+
end
|
26
|
+
|
27
|
+
def slug
|
28
|
+
return item_type.api_key.humanize.parameterize if singleton?
|
29
|
+
return id.to_s unless title_attribute
|
30
|
+
|
31
|
+
title = send(title_attribute)
|
32
|
+
if title
|
33
|
+
"#{id}-#{title.parameterize[0..50]}"
|
34
|
+
else
|
35
|
+
id.to_s
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def singleton?
|
40
|
+
item_type.singleton
|
41
|
+
end
|
42
|
+
|
43
|
+
def item_type
|
44
|
+
@item_type ||= entity.item_type
|
45
|
+
end
|
46
|
+
alias content_type item_type
|
47
|
+
|
48
|
+
def fields
|
49
|
+
@fields ||= item_type.fields.sort_by(&:position)
|
50
|
+
end
|
51
|
+
|
52
|
+
def attributes
|
53
|
+
@attributes ||= fields.each_with_object(
|
54
|
+
ActiveSupport::HashWithIndifferentAccess.new
|
55
|
+
) do |field, acc|
|
56
|
+
acc[field.api_key.to_sym] = send(field.api_key)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def position
|
61
|
+
entity.position
|
62
|
+
end
|
63
|
+
|
64
|
+
def updated_at
|
65
|
+
Time.parse(entity.updated_at)
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_s
|
69
|
+
api_key = item_type.api_key
|
70
|
+
"#<Item id=#{id} item_type=#{api_key} attributes=#{attributes}>"
|
71
|
+
end
|
72
|
+
alias inspect to_s
|
73
|
+
|
74
|
+
def title_attribute
|
75
|
+
title_field = fields.find do |field|
|
76
|
+
field.field_type == 'string' &&
|
77
|
+
field.appeareance[:type] == 'title'
|
78
|
+
end
|
79
|
+
title_field && title_field.api_key
|
80
|
+
end
|
81
|
+
|
82
|
+
def respond_to_missing?(method, include_private = false)
|
83
|
+
field = fields.find { |f| f.api_key.to_sym == method }
|
84
|
+
if field
|
85
|
+
true
|
86
|
+
else
|
87
|
+
super
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def read_attribute(method, field)
|
94
|
+
field_type = field.field_type
|
95
|
+
type_klass_name = "::Dato::Local::FieldType::#{field_type.camelize}"
|
96
|
+
type_klass = type_klass_name.safe_constantize
|
97
|
+
|
98
|
+
if type_klass
|
99
|
+
value = if field.localized
|
100
|
+
(entity.send(method) || {})[I18n.locale]
|
101
|
+
else
|
102
|
+
entity.send(method)
|
103
|
+
end
|
104
|
+
|
105
|
+
value && type_klass.parse(value, @items_repo)
|
106
|
+
else
|
107
|
+
raise "Cannot convert field `#{method}` of type `#{field_type}`"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def method_missing(method, *arguments, &block)
|
112
|
+
field = fields.find { |f| f.api_key.to_sym == method }
|
113
|
+
if field && arguments.empty?
|
114
|
+
read_attribute(method, field)
|
115
|
+
else
|
116
|
+
super
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'active_support/core_ext/string'
|
3
|
+
require 'dato/local/item'
|
4
|
+
|
5
|
+
module Dato
|
6
|
+
module Local
|
7
|
+
class ItemsRepo
|
8
|
+
attr_reader :entities_repo, :collections_by_type
|
9
|
+
|
10
|
+
def initialize(entities_repo)
|
11
|
+
@entities_repo = entities_repo
|
12
|
+
@collections_by_type = {}
|
13
|
+
@items_by_id = {}
|
14
|
+
|
15
|
+
build_cache!
|
16
|
+
end
|
17
|
+
|
18
|
+
def find(id)
|
19
|
+
@items_by_id[id]
|
20
|
+
end
|
21
|
+
|
22
|
+
def respond_to_missing?(method, include_private = false)
|
23
|
+
if collections_by_type.key?(method)
|
24
|
+
true
|
25
|
+
else
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def item_type_key(item_type)
|
33
|
+
api_key = item_type.api_key
|
34
|
+
if item_type.singleton
|
35
|
+
[api_key.to_sym, true]
|
36
|
+
else
|
37
|
+
[api_key.pluralize.to_sym, false]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def build_cache!
|
42
|
+
item_type_entities.each do |item_type|
|
43
|
+
key, singleton = item_type_key(item_type)
|
44
|
+
@collections_by_type[key] = if singleton
|
45
|
+
nil
|
46
|
+
else
|
47
|
+
ItemCollection.new
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
item_entities.each do |item_entity|
|
52
|
+
item = Item.new(item_entity, self)
|
53
|
+
|
54
|
+
key, singleton = item_type_key(item_entity.item_type)
|
55
|
+
if singleton
|
56
|
+
@collections_by_type[key] = item
|
57
|
+
else
|
58
|
+
@collections_by_type[key].push item
|
59
|
+
end
|
60
|
+
|
61
|
+
@items_by_id[item.id] = item
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def item_type_entities
|
66
|
+
entities_repo.find_entities_of_type('item_type')
|
67
|
+
end
|
68
|
+
|
69
|
+
def item_entities
|
70
|
+
entities_repo.find_entities_of_type('item')
|
71
|
+
end
|
72
|
+
|
73
|
+
def method_missing(method, *arguments, &block)
|
74
|
+
if collections_by_type.key?(method) && arguments.empty?
|
75
|
+
collections_by_type[method]
|
76
|
+
else
|
77
|
+
super
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class ItemCollection < Array
|
82
|
+
def each(&block)
|
83
|
+
if block && block.arity == 2
|
84
|
+
each_with_object({}) do |item, acc|
|
85
|
+
acc[item.id] = item
|
86
|
+
end.each(&block)
|
87
|
+
else
|
88
|
+
super(&block)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def [](id)
|
93
|
+
if id.is_a? String
|
94
|
+
find { |item| item.id == id }
|
95
|
+
else
|
96
|
+
super(id)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def keys
|
101
|
+
map(&:id)
|
102
|
+
end
|
103
|
+
|
104
|
+
def values
|
105
|
+
to_a
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|