robin_cms 0.2.0 → 0.3.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 +4 -4
- data/lib/robin_cms/cms.rb +5 -0
- data/lib/robin_cms/configuration.rb +45 -8
- data/lib/robin_cms/configuration_schema.rb +109 -0
- data/lib/robin_cms/library.rb +18 -0
- data/lib/robin_cms/singular_library.rb +68 -0
- data/lib/robin_cms/version.rb +1 -1
- data/lib/robin_cms/views/layout.erb +9 -0
- data/lib/robin_cms/views/library.erb +2 -3
- data/lib/robin_cms/views/library_actions.erb +3 -1
- data/lib/robin_cms/views/library_item.erb +1 -0
- data/lib/robin_cms.rb +5 -0
- metadata +4 -3
- data/lib/robin_cms/configuration-schema.json +0 -120
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 26f13be1b3e97bce69e705daf56e969916467591b7c30b2877c2ce29e07e62d3
|
|
4
|
+
data.tar.gz: 7f34fbee635184285025e757e3c52ef8e25467255ed4a90647203bbfcd656756
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a420e205f0f06d34817b5cb1424f513051cddb7a665dcddb9d707c091088969e7031bef154542347691fe109a612f58741c229f622380281e4289a2bcfa1a268
|
|
7
|
+
data.tar.gz: 7d1e1bbd2b23d02c02a7dcca004c35015663bb2ece865f7d4ebfabbcd96e2897bc95bd758bd64145cb70d5ef2f7819717d195417f7121254080773b1f70a9f43
|
data/lib/robin_cms/cms.rb
CHANGED
|
@@ -31,6 +31,17 @@ module RobinCMS
|
|
|
31
31
|
fields: []
|
|
32
32
|
}.freeze
|
|
33
33
|
|
|
34
|
+
SINGULAR_DEFAULTS = {
|
|
35
|
+
type: "singular",
|
|
36
|
+
location: "_data",
|
|
37
|
+
static_location: "uploads",
|
|
38
|
+
filetype: "yml",
|
|
39
|
+
description: "",
|
|
40
|
+
can_create: false,
|
|
41
|
+
can_delete: false,
|
|
42
|
+
fields: []
|
|
43
|
+
}.freeze
|
|
44
|
+
|
|
34
45
|
FIELD_DEFAULTS = {
|
|
35
46
|
type: "text",
|
|
36
47
|
default: nil,
|
|
@@ -55,7 +66,7 @@ module RobinCMS
|
|
|
55
66
|
type: "hidden"
|
|
56
67
|
}].freeze
|
|
57
68
|
|
|
58
|
-
|
|
69
|
+
AUTOMATIC_COLLECTION_FIELDS = [{
|
|
59
70
|
label: "Published",
|
|
60
71
|
id: "published",
|
|
61
72
|
type: "select",
|
|
@@ -72,6 +83,14 @@ module RobinCMS
|
|
|
72
83
|
order: 2
|
|
73
84
|
}].freeze
|
|
74
85
|
|
|
86
|
+
AUTOMATIC_SINGULAR_FIELDS = [{
|
|
87
|
+
label: "Title",
|
|
88
|
+
id: "title",
|
|
89
|
+
type: "hidden",
|
|
90
|
+
required: true,
|
|
91
|
+
order: 1
|
|
92
|
+
}]
|
|
93
|
+
|
|
75
94
|
AUTOMATIC_IMAGE_FIELDS = [{
|
|
76
95
|
id: "image_src",
|
|
77
96
|
type: "hidden"
|
|
@@ -94,10 +113,7 @@ module RobinCMS
|
|
|
94
113
|
YAML.load_file(config_file, symbolize_names: true)
|
|
95
114
|
end
|
|
96
115
|
|
|
97
|
-
|
|
98
|
-
# reuse elements and what not.
|
|
99
|
-
schema_file = File.join(__dir__, "configuration-schema.json")
|
|
100
|
-
schema = JSON.parse(File.read(schema_file))
|
|
116
|
+
schema = ConfigurationSchema.schema
|
|
101
117
|
errors = JSON::Validator.fully_validate(schema, data)
|
|
102
118
|
|
|
103
119
|
unless errors.empty?
|
|
@@ -122,11 +138,24 @@ module RobinCMS
|
|
|
122
138
|
library[:type].nil? || library[:type] == "collection"
|
|
123
139
|
end
|
|
124
140
|
|
|
141
|
+
def data?(library)
|
|
142
|
+
library[:type] == "data"
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def singular?(library)
|
|
146
|
+
library[:type] == "singular"
|
|
147
|
+
end
|
|
148
|
+
|
|
125
149
|
def merge_config(config)
|
|
126
150
|
merge(config, {
|
|
127
151
|
libraries: config[:libraries].map do |library|
|
|
128
|
-
library_defaults =
|
|
129
|
-
|
|
152
|
+
library_defaults = if collection?(library)
|
|
153
|
+
COLLECTION_DEFAULTS
|
|
154
|
+
elsif data?(library)
|
|
155
|
+
DATA_DEFAULTS
|
|
156
|
+
elsif singular?(library)
|
|
157
|
+
SINGULAR_DEFAULTS
|
|
158
|
+
end
|
|
130
159
|
|
|
131
160
|
library_defaults.merge(library, {
|
|
132
161
|
fields: library[:fields].map do |field|
|
|
@@ -144,7 +173,15 @@ module RobinCMS
|
|
|
144
173
|
library[:fields].append(*AUTOMATIC_FIELDS)
|
|
145
174
|
|
|
146
175
|
if collection?(library)
|
|
147
|
-
library[:fields].append(*
|
|
176
|
+
library[:fields].append(*AUTOMATIC_COLLECTION_FIELDS)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Replace the automatic title field with a hidden one. The title is not
|
|
180
|
+
# used for singular fields, but every item is required to have one, so
|
|
181
|
+
# hide it in the UI.
|
|
182
|
+
if singular?(library)
|
|
183
|
+
# Using prepend ensures this one stays when we call uniq! below.
|
|
184
|
+
library[:fields].prepend(*AUTOMATIC_SINGULAR_FIELDS)
|
|
148
185
|
end
|
|
149
186
|
|
|
150
187
|
# Ensure the automatic image fields are inserted directly after the
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# frozen_string_literal => true
|
|
2
|
+
|
|
3
|
+
module RobinCMS
|
|
4
|
+
module ConfigurationSchema
|
|
5
|
+
def self.field_schema(kind)
|
|
6
|
+
field_types = [
|
|
7
|
+
"text",
|
|
8
|
+
"date",
|
|
9
|
+
"hidden",
|
|
10
|
+
"number",
|
|
11
|
+
"color",
|
|
12
|
+
"email",
|
|
13
|
+
"url",
|
|
14
|
+
"select",
|
|
15
|
+
"image"
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
if kind == "collection"
|
|
19
|
+
field_types << "richtext"
|
|
20
|
+
field_types << "array"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
{
|
|
24
|
+
"type" => "object",
|
|
25
|
+
"required" => ["id", "label"],
|
|
26
|
+
"properties" => {
|
|
27
|
+
"id" => { "type" => "string" },
|
|
28
|
+
"label" => { "type" => "string" },
|
|
29
|
+
"type" => { "type" => "string", "enum" => field_types },
|
|
30
|
+
"default" => { "type" => "string" },
|
|
31
|
+
"required" => { "type" => "boolean" },
|
|
32
|
+
"readonly" => { "type" => "boolean" },
|
|
33
|
+
"option" => {
|
|
34
|
+
"type" => "array",
|
|
35
|
+
"items" => {
|
|
36
|
+
"type" => "object",
|
|
37
|
+
"required" => ["label", "value"],
|
|
38
|
+
"properties" => {
|
|
39
|
+
"label" => { "type" => "string" },
|
|
40
|
+
"value" => { "type" => "string" }
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"dimensions" => { "type" => "string", "pattern" => "^[0-9]+x[0-9]+$" },
|
|
45
|
+
"filetype" => { "type" => "string", "enum" => ["png", "jpg"] },
|
|
46
|
+
"description" => { "type" => "string" },
|
|
47
|
+
"order" => { "type" => "number" }
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.library_schema(kind)
|
|
53
|
+
filetypes = case kind
|
|
54
|
+
when "collection"
|
|
55
|
+
["html"]
|
|
56
|
+
when "data", "singular"
|
|
57
|
+
["yml"]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
{
|
|
61
|
+
"type" => "object",
|
|
62
|
+
"required" => ["id", "label", "label_singular"],
|
|
63
|
+
"properties" => {
|
|
64
|
+
"id" => { "type" => "string" },
|
|
65
|
+
"type" => { "type" => "string", "const" => kind },
|
|
66
|
+
"filetype" => { "type" => "string", "enum" => filetypes },
|
|
67
|
+
"label" => { "type" => "string" },
|
|
68
|
+
"label_singular" => { "type" => "string" },
|
|
69
|
+
"location" => { "type" => "string" },
|
|
70
|
+
"static_location" => { "type" => "string" },
|
|
71
|
+
"description" => { "type" => "string" },
|
|
72
|
+
"can_create" => { "type" => "boolean" },
|
|
73
|
+
"can_delete" => { "type" => "boolean" },
|
|
74
|
+
"pattern" => { "type" => "string" },
|
|
75
|
+
"display_name_pattern" => { "type" => "string" },
|
|
76
|
+
"fields" => { "type" => "array", "items" => field_schema(kind) }
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def self.schema
|
|
82
|
+
{
|
|
83
|
+
"$schema" => "http://json-schema.org/draft-06/schema#",
|
|
84
|
+
"title" => "RobinCMS configuration schema",
|
|
85
|
+
"type" => "object",
|
|
86
|
+
"required" => ["url", "libraries"],
|
|
87
|
+
"properties" => {
|
|
88
|
+
"title" => { "type" => "string" },
|
|
89
|
+
"url" => { "type" => "string" },
|
|
90
|
+
"build_command" => { "type" => "string" },
|
|
91
|
+
"accent_color" => {
|
|
92
|
+
"type" => "string",
|
|
93
|
+
"pattern" => '^\\#{1}[a-fA-F0-9]{6}'
|
|
94
|
+
},
|
|
95
|
+
"libraries" => {
|
|
96
|
+
"type" => "array",
|
|
97
|
+
"items" => {
|
|
98
|
+
"anyOf" => [
|
|
99
|
+
library_schema("collection"),
|
|
100
|
+
library_schema("data"),
|
|
101
|
+
library_schema("singular")
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
data/lib/robin_cms/library.rb
CHANGED
|
@@ -29,6 +29,8 @@ module RobinCMS
|
|
|
29
29
|
extend CollectionLibrary
|
|
30
30
|
when "data"
|
|
31
31
|
extend DataLibrary
|
|
32
|
+
when "singular"
|
|
33
|
+
extend SingularLibrary
|
|
32
34
|
end
|
|
33
35
|
end
|
|
34
36
|
|
|
@@ -86,5 +88,21 @@ module RobinCMS
|
|
|
86
88
|
def kind
|
|
87
89
|
@schema[:id]
|
|
88
90
|
end
|
|
91
|
+
|
|
92
|
+
def type
|
|
93
|
+
@schema[:type]
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def collection?
|
|
97
|
+
type == "collection"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def data?
|
|
101
|
+
type == "data"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def singular?
|
|
105
|
+
type == "singular"
|
|
106
|
+
end
|
|
89
107
|
end
|
|
90
108
|
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RobinCMS
|
|
4
|
+
module SingularLibrary
|
|
5
|
+
# Since there is only one of these, give it the special id 0.
|
|
6
|
+
ID = 0
|
|
7
|
+
|
|
8
|
+
def self.extended(target)
|
|
9
|
+
# Since singular files can't be created or delete by users, create an
|
|
10
|
+
# empty one automatically if it doesn't already exist.
|
|
11
|
+
|
|
12
|
+
filename = target.schema[:id]
|
|
13
|
+
filetype = target.schema[:filetype]
|
|
14
|
+
filepath = File.join(target.schema[:location], "#{filename}.#{filetype}")
|
|
15
|
+
|
|
16
|
+
return if File.exist?(filepath)
|
|
17
|
+
|
|
18
|
+
FileUtils.mkdir_p(File.dirname(filepath))
|
|
19
|
+
item = Item.new(nil, {title: target.schema[:label]}, **target.schema)
|
|
20
|
+
item.update_timestamps!
|
|
21
|
+
serialized = YAML.dump(item.frontmatter, stringify_names: true)
|
|
22
|
+
File.write(filepath, serialized)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def create(_attributes = nil)
|
|
26
|
+
raise InvalidOperationError, "Invalid operation for Singular item"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def find_one(_id = nil)
|
|
30
|
+
# Ignore the id parameter. For singular libraries, there is only a single
|
|
31
|
+
# item. The id parameter is left for API compatibility with the other
|
|
32
|
+
# library types.
|
|
33
|
+
|
|
34
|
+
item = YAML.load_file(filepath, symbolize_names: true, permitted_classes: [Date])
|
|
35
|
+
|
|
36
|
+
return nil unless item
|
|
37
|
+
|
|
38
|
+
Item.new(ID, item, **@schema)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def all
|
|
42
|
+
# Returns an array of the only item. For API compatibility with the other
|
|
43
|
+
# library types.
|
|
44
|
+
[find_one].compact
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def write(item)
|
|
48
|
+
FileUtils.mkdir_p(File.dirname(filepath))
|
|
49
|
+
FileUtils.touch(filepath)
|
|
50
|
+
|
|
51
|
+
item.update_timestamps!
|
|
52
|
+
serialized = YAML.dump(item.frontmatter, stringify_names: true)
|
|
53
|
+
File.write(filepath, serialized)
|
|
54
|
+
|
|
55
|
+
filepath
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def delete(_id = nil)
|
|
59
|
+
raise InvalidOperationError, "Invalid operation for Singular item"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def filepath
|
|
65
|
+
File.join(@schema[:location], "#{@schema[:id]}.#{@schema[:filetype]}")
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
data/lib/robin_cms/version.rb
CHANGED
|
@@ -35,7 +35,13 @@
|
|
|
35
35
|
</span>
|
|
36
36
|
</header>
|
|
37
37
|
<% end %>
|
|
38
|
+
|
|
38
39
|
<main id="site-content">
|
|
40
|
+
<% if session[:auth_user] %>
|
|
41
|
+
<header class="card --clear">
|
|
42
|
+
<%= erb :nav %>
|
|
43
|
+
</header>
|
|
44
|
+
<% end %>
|
|
39
45
|
<%= yield %>
|
|
40
46
|
<footer id="site-footer" class="card --clear">
|
|
41
47
|
<%= erb :"logo.svg" %>
|
|
@@ -46,6 +52,7 @@
|
|
|
46
52
|
</p>
|
|
47
53
|
</footer>
|
|
48
54
|
</main>
|
|
55
|
+
|
|
49
56
|
<dialog id="successdialog" class="card">
|
|
50
57
|
<h2>Success!</h2>
|
|
51
58
|
<p><%= flash[:success_dialog] %></p>
|
|
@@ -55,6 +62,7 @@
|
|
|
55
62
|
</form>
|
|
56
63
|
</div>
|
|
57
64
|
</dialog>
|
|
65
|
+
|
|
58
66
|
<dialog id="errordialog" class="card">
|
|
59
67
|
<h2>Oops, something went wrong.</h2>
|
|
60
68
|
<p><%= flash[:error_dialog] %></p>
|
|
@@ -65,6 +73,7 @@
|
|
|
65
73
|
</div>
|
|
66
74
|
</dialog>
|
|
67
75
|
</body>
|
|
76
|
+
|
|
68
77
|
<script>
|
|
69
78
|
const image = document.getElementById("__field_image")
|
|
70
79
|
if (image) {
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
<header class="card --clear">
|
|
2
|
-
<%= erb :nav %>
|
|
3
|
-
</header>
|
|
4
1
|
<div class="card">
|
|
5
2
|
<% if @library[:description] %>
|
|
6
3
|
<p><%= @library[:description] %></p>
|
|
@@ -13,7 +10,9 @@
|
|
|
13
10
|
</form>
|
|
14
11
|
<% end %>
|
|
15
12
|
</div>
|
|
13
|
+
|
|
16
14
|
<%= erb :filter_form %>
|
|
15
|
+
|
|
17
16
|
<% if @items.empty? %>
|
|
18
17
|
<div class="no-items">
|
|
19
18
|
Nothing to show.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<span class="controls">
|
|
2
|
-
|
|
2
|
+
<% unless @library.singular? %>
|
|
3
|
+
<a href="<%= library_url(@library) %>">Back</a>
|
|
4
|
+
<% end %>
|
|
3
5
|
<button form="<%= safe_id(@item.id, 'edit_item') %>" type="submit">Save</button>
|
|
4
6
|
<%= erb :delete_dialog if has_delete %>
|
|
5
7
|
</span>
|
data/lib/robin_cms.rb
CHANGED
|
@@ -23,10 +23,14 @@ module RobinCMS
|
|
|
23
23
|
|
|
24
24
|
class ConversionError < StandardError
|
|
25
25
|
end
|
|
26
|
+
|
|
27
|
+
class InvalidOperationError < StandardError
|
|
28
|
+
end
|
|
26
29
|
end
|
|
27
30
|
|
|
28
31
|
require_relative "robin_cms/version"
|
|
29
32
|
require_relative "robin_cms/configuration"
|
|
33
|
+
require_relative "robin_cms/configuration_schema"
|
|
30
34
|
require_relative "robin_cms/editable"
|
|
31
35
|
require_relative "robin_cms/sluggable"
|
|
32
36
|
require_relative "robin_cms/queryable"
|
|
@@ -34,6 +38,7 @@ require_relative "robin_cms/item"
|
|
|
34
38
|
require_relative "robin_cms/library"
|
|
35
39
|
require_relative "robin_cms/collection_library"
|
|
36
40
|
require_relative "robin_cms/data_library"
|
|
41
|
+
require_relative "robin_cms/singular_library"
|
|
37
42
|
require_relative "robin_cms/item"
|
|
38
43
|
require_relative "robin_cms/auth"
|
|
39
44
|
require_relative "robin_cms/flash"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: robin_cms
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Aron Lebani
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-09-
|
|
11
|
+
date: 2026-09-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bcrypt
|
|
@@ -80,8 +80,8 @@ files:
|
|
|
80
80
|
- lib/robin_cms/auth.rb
|
|
81
81
|
- lib/robin_cms/cms.rb
|
|
82
82
|
- lib/robin_cms/collection_library.rb
|
|
83
|
-
- lib/robin_cms/configuration-schema.json
|
|
84
83
|
- lib/robin_cms/configuration.rb
|
|
84
|
+
- lib/robin_cms/configuration_schema.rb
|
|
85
85
|
- lib/robin_cms/data_library.rb
|
|
86
86
|
- lib/robin_cms/editable.rb
|
|
87
87
|
- lib/robin_cms/flash.rb
|
|
@@ -89,6 +89,7 @@ files:
|
|
|
89
89
|
- lib/robin_cms/item.rb
|
|
90
90
|
- lib/robin_cms/library.rb
|
|
91
91
|
- lib/robin_cms/queryable.rb
|
|
92
|
+
- lib/robin_cms/singular_library.rb
|
|
92
93
|
- lib/robin_cms/sluggable.rb
|
|
93
94
|
- lib/robin_cms/version.rb
|
|
94
95
|
- lib/robin_cms/views/change_password.erb
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "http://json-schema.org/draft-06/schema#",
|
|
3
|
-
"title": "RobinCMS configuration schema",
|
|
4
|
-
"type": "object",
|
|
5
|
-
"required": ["url", "libraries"],
|
|
6
|
-
"properties": {
|
|
7
|
-
"title": { "type": "string" },
|
|
8
|
-
"url": { "type": "string" },
|
|
9
|
-
"build_command": { "type": "string" },
|
|
10
|
-
"accent_color": {
|
|
11
|
-
"type": "string",
|
|
12
|
-
"pattern": "^\\#{1}[a-fA-F0-9]{6}"
|
|
13
|
-
},
|
|
14
|
-
"libraries": {
|
|
15
|
-
"type": "array",
|
|
16
|
-
"items": {
|
|
17
|
-
"anyOf": [
|
|
18
|
-
{ "$ref": "#/$defs/library_schema" },
|
|
19
|
-
{ "$ref": "#/$defs/data_schema" }
|
|
20
|
-
]
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
"$defs": {
|
|
25
|
-
"options_schema": {
|
|
26
|
-
"type": "array",
|
|
27
|
-
"items": {
|
|
28
|
-
"type": "object",
|
|
29
|
-
"required": ["label", "value"],
|
|
30
|
-
"properties": {
|
|
31
|
-
"label": { "type": "string" },
|
|
32
|
-
"value": { "type": "string" }
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
"image_dimensions_schema": { "type": "string", "pattern": "^[0-9]+x[0-9]+$" },
|
|
37
|
-
"image_filetype_schema": { "type": "string", "enum": ["png", "jpg"] },
|
|
38
|
-
"library_schema": {
|
|
39
|
-
"type": "object",
|
|
40
|
-
"required": ["id", "label", "label_singular"],
|
|
41
|
-
"properties": {
|
|
42
|
-
"id": { "type": "string" },
|
|
43
|
-
"type": { "type": "string", "const": "collection" },
|
|
44
|
-
"filetype": { "type": "string", "enum": ["html"] },
|
|
45
|
-
"label": { "type": "string" },
|
|
46
|
-
"label_singular": { "type": "string" },
|
|
47
|
-
"location": { "type": "string" },
|
|
48
|
-
"static_location": { "type": "string" },
|
|
49
|
-
"description": { "type": "string" },
|
|
50
|
-
"can_create": { "type": "boolean" },
|
|
51
|
-
"can_delete": { "type": "boolean" },
|
|
52
|
-
"pattern": { "type": "string" },
|
|
53
|
-
"display_name_pattern": { "type": "string" },
|
|
54
|
-
"fields": {
|
|
55
|
-
"type": "array",
|
|
56
|
-
"items": {
|
|
57
|
-
"type": "object",
|
|
58
|
-
"required": ["id", "label"],
|
|
59
|
-
"properties": {
|
|
60
|
-
"id": { "type": "string" },
|
|
61
|
-
"label": { "type": "string" },
|
|
62
|
-
"type": {
|
|
63
|
-
"type": "string",
|
|
64
|
-
"enum": ["text", "richtext", "date", "hidden", "number", "color", "email", "url", "select", "image", "array"]
|
|
65
|
-
},
|
|
66
|
-
"default": { "type": "string" },
|
|
67
|
-
"required": { "type": "boolean" },
|
|
68
|
-
"readonly": { "type": "boolean" },
|
|
69
|
-
"options": { "$ref": "#/$defs/options_schema" },
|
|
70
|
-
"dimensions": { "$ref": "#/$defs/image_dimensions_schema" },
|
|
71
|
-
"filetype": { "$ref": "#/$defs/image_filetype_schema" },
|
|
72
|
-
"description": { "type": "string" },
|
|
73
|
-
"order": { "type": "number" }
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
},
|
|
79
|
-
"data_schema": {
|
|
80
|
-
"type": "object",
|
|
81
|
-
"required": ["id", "label", "label_singular"],
|
|
82
|
-
"properties": {
|
|
83
|
-
"id": { "type": "string" },
|
|
84
|
-
"type": { "type": "string", "const": "data" },
|
|
85
|
-
"filetype": { "type": "string", "enum": ["yml"] },
|
|
86
|
-
"label": { "type": "string" },
|
|
87
|
-
"label_singular": { "type": "string" },
|
|
88
|
-
"location": { "type": "string" },
|
|
89
|
-
"static_location": { "type": "string" },
|
|
90
|
-
"description": { "type": "string" },
|
|
91
|
-
"can_create": { "type": "boolean" },
|
|
92
|
-
"can_delete": { "type": "boolean" },
|
|
93
|
-
"pattern": { "type": "string" },
|
|
94
|
-
"display_name_pattern": { "type": "string" },
|
|
95
|
-
"fields": {
|
|
96
|
-
"type": "array",
|
|
97
|
-
"items": {
|
|
98
|
-
"type": "object",
|
|
99
|
-
"required": ["id", "label"],
|
|
100
|
-
"properties": {
|
|
101
|
-
"id": { "type": "string" },
|
|
102
|
-
"label": { "type": "string" },
|
|
103
|
-
"type": {
|
|
104
|
-
"type": "string",
|
|
105
|
-
"enum": ["text", "date", "hidden", "number", "color", "email", "url", "select", "image"]
|
|
106
|
-
},
|
|
107
|
-
"default": { "type": "string" },
|
|
108
|
-
"required": { "type": "boolean" },
|
|
109
|
-
"readonly": { "type": "boolean" },
|
|
110
|
-
"options": { "$ref": "#/$defs/options_schema" },
|
|
111
|
-
"dimensions": { "$ref": "#/$defs/image_dimensions_schema" },
|
|
112
|
-
"filetype": { "$ref": "#/$defs/image_filetype_schema" },
|
|
113
|
-
"description": { "type": "string" }
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|