dato 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|