jekyll-open-sdg-plugins 1.1.0 → 1.2.0.pre.beta1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e6f79d3292ae608202621743899fe24604ee67fc7bcc9ca90d26e91bf18e8d6
4
- data.tar.gz: e09f66ec6f34a74e8b29d07f9dc75dcd2c3a4484daa3d02db45eb5140f2fd637
3
+ metadata.gz: 714570ee0a7ab38905c524b6fad9c1590340e09052778c82adc543574d11e7ac
4
+ data.tar.gz: ed6ee32ba2cb547dd8f46159fb133197b044fc101c0d00af12662cf78a245872
5
5
  SHA512:
6
- metadata.gz: d217ea0ac1fecaaf2e4d83f7d39d094be1f6d34277a52b5c34c0aa369effefb7589ec44e76d41d87ce437c84f0d1a6bcb47c657c04db751dac93fdbcb586bc19
7
- data.tar.gz: 94d80452821f6793932b5be5342d6d99814caf52dd27cd5b27e000fe67b1893364d6da9c47bc1327743125e5b01c2a49431d4405f0c075a62dd77ff182a25819
6
+ metadata.gz: 2c5862fc0ffd6241ef72f92d15e72f5a0dc4fe682a8b0a9cfe80e418968b1eadfa0aa5fa7c5ea83e82b2ebe441535d3c8e77283b7925d9ce83f491b7bcf7f99d
7
+ data.tar.gz: 789bb89817ceb676ab5eaac06411435030a6fcdf24dd4ad5c0529fa7cfadac27d5dcd91670f5894fdc983220e9cd6a04324309fee46bb747c93996e561a79821
@@ -14,4 +14,5 @@ Gem::Specification.new do |spec|
14
14
  spec.require_paths = ["lib"]
15
15
  spec.add_dependency "jekyll", "~> 3.0"
16
16
  spec.add_dependency "deep_merge", "~> 1.2"
17
+ spec.add_dependency "json_schemer", "~> 0.2"
17
18
  end
@@ -1,5 +1,6 @@
1
1
  require_relative "jekyll-open-sdg-plugins/version"
2
2
  require_relative "jekyll-open-sdg-plugins/site_configuration"
3
+ require_relative "jekyll-open-sdg-plugins/validate_site_config"
3
4
  require_relative "jekyll-open-sdg-plugins/fetch_remote_data"
4
5
  require_relative "jekyll-open-sdg-plugins/translate_key"
5
6
  require_relative "jekyll-open-sdg-plugins/translate_date"
@@ -9,6 +10,7 @@ require_relative "jekyll-open-sdg-plugins/create_goals"
9
10
  require_relative "jekyll-open-sdg-plugins/create_pages"
10
11
  require_relative "jekyll-open-sdg-plugins/sdg_variables"
11
12
  require_relative "jekyll-open-sdg-plugins/search_index"
13
+ require_relative "jekyll-open-sdg-plugins/validate_indicator_config"
12
14
 
13
15
  module JekyllOpenSdgPlugins
14
16
  end
@@ -43,6 +43,37 @@ module JekyllOpenSdgPlugins
43
43
  site.collections['indicators'].docs << IndicatorPage.new(site, site.source, dir, inid, language, layout)
44
44
  end
45
45
  end
46
+ # Create the indicator configuration pages.
47
+ metadata = {}
48
+ if opensdg_translated_builds(site)
49
+ if site.data.has_key?('untranslated')
50
+ metadata = site.data['untranslated']['meta']
51
+ else
52
+ default_language = site.config['languages'][0]
53
+ metadata = site.data[default_language]['meta']
54
+ end
55
+ else
56
+ metadata = site.data['meta']
57
+ end
58
+ # Loop through the indicators (using metadata as a list).
59
+ if !metadata.empty?
60
+ site.config['show_indicator_config_forms'] = true
61
+ # Loop through the languages.
62
+ site.config['languages'].each_with_index do |language, index|
63
+ # Get the "public language" (for URLs) which may be different.
64
+ language_public = language
65
+ if languages_public[language]
66
+ language_public = languages_public[language]
67
+ end
68
+ metadata.each do |inid, meta|
69
+ dir = File.join('config', inid)
70
+ if index != 0
71
+ dir = File.join(language_public, 'config', inid)
72
+ end
73
+ site.collections['pages'].docs << IndicatorConfigPage.new(site, site.source, dir, inid, language, meta)
74
+ end
75
+ end
76
+ end
46
77
  end
47
78
  end
48
79
  end
@@ -64,4 +95,24 @@ module JekyllOpenSdgPlugins
64
95
  self.data['indicator'] = self.data['indicator_number']
65
96
  end
66
97
  end
98
+
99
+ # A Page subclass used in the `CreateIndicators` class.
100
+ class IndicatorConfigPage < Jekyll::Page
101
+ def initialize(site, base, dir, inid, language, meta)
102
+ @site = site
103
+ @base = base
104
+ @dir = dir
105
+ @name = 'index.html'
106
+
107
+ self.process(@name)
108
+ self.data = {}
109
+ self.data['language'] = language
110
+ self.data['indicator_number'] = inid.gsub('-', '.')
111
+ self.data['config_type'] = 'indicator'
112
+ self.data['layout'] = 'config-builder'
113
+ self.data['meta'] = meta
114
+ self.data['title'] = 'Open SDG indicator configuration: ' + self.data['indicator_number']
115
+ self.data['config_filename'] = inid + '.yml'
116
+ end
117
+ end
67
118
  end
@@ -61,6 +61,21 @@ module JekyllOpenSdgPlugins
61
61
  pages = site.config['create_pages']
62
62
  end
63
63
 
64
+ # Clone pages so that we don't edit the original.
65
+ pages = pages.clone
66
+
67
+ # Hardcode the site configuration page if it's not already there.
68
+ config_page = pages.find { |page| page['layout'] == 'config-builder' }
69
+ if config_page == nil
70
+ pages.push({
71
+ 'folder' => '/config',
72
+ 'layout' => 'config-builder',
73
+ 'title' => 'Open SDG site configuration',
74
+ 'config_type' => 'site',
75
+ 'config_filename' => 'site_config.yml'
76
+ })
77
+ end
78
+
64
79
  # See if we need to "map" any language codes.
65
80
  languages_public = Hash.new
66
81
  if site.config['languages_public']
@@ -22,20 +22,17 @@ module JekyllOpenSdgPlugins
22
22
  'headlines' => 'headline/all.json',
23
23
  'schema' => 'meta/schema.json',
24
24
  'reporting' => 'stats/reporting.json',
25
+ 'disaggregation' => 'stats/disaggregation.json',
25
26
  'translations' => 'translations/translations.json',
26
- 'zip' => 'zip/all_indicators.json'
27
+ 'zip' => 'zip/all_indicators.json',
28
+ 'indicator_downloads' => 'downloads/indicator-downloads.json'
27
29
  }
28
30
  end
29
31
 
30
- # Is this path a remote path?
31
- def is_path_remote(path)
32
- return path.start_with?('http')
33
- end
34
-
35
32
  # Get a build from a local folder on disk or a remote URL on the Internet.
36
33
  def fetch_build(path)
37
34
 
38
- is_remote = is_path_remote(path)
35
+ is_remote = opensdg_is_path_remote(path)
39
36
  build = {}
40
37
  get_endpoints().each do |key, value|
41
38
  endpoint = is_remote ? path + '/' + value : File.join(path, fix_path(value))
@@ -44,8 +41,14 @@ module JekyllOpenSdgPlugins
44
41
  json_file = is_remote ? open(endpoint) : File.open(endpoint)
45
42
  build[key] = JSON.load(json_file)
46
43
  rescue StandardError => e
47
- # For backwards compatibility, we allow 'translations' to be missing.
48
- if key != 'translations'
44
+ # For backwards compatibility, forego the exception in some cases.
45
+ abort_build = true
46
+ if ['translations', 'indicator_downloads', 'disaggregation'].include? key
47
+ abort_build = false
48
+ elsif endpoint.include? '/untranslated/'
49
+ abort_build = false
50
+ end
51
+ if abort_build
49
52
  puts e.message
50
53
  abort 'Unable to read data from: ' + endpoint
51
54
  end
@@ -59,7 +62,7 @@ module JekyllOpenSdgPlugins
59
62
  # translated builds or not.
60
63
  def site_uses_translated_builds(path)
61
64
 
62
- is_remote = is_path_remote(path)
65
+ is_remote = opensdg_is_path_remote(path)
63
66
  endpoints = get_endpoints()
64
67
  # For a quick test, we just use 'meta'.
65
68
  meta = endpoints['meta']
@@ -88,23 +91,30 @@ module JekyllOpenSdgPlugins
88
91
  local = site.config['local_data_folder']
89
92
 
90
93
  if !remote && !local
91
- abort 'Site config must include either "remote_data_prefix" or "local_data_folder".'
94
+ abort 'Site config must include "remote_data_prefix".'
92
95
  end
93
96
 
94
- build_location = remote ? remote : File.join(Dir.pwd, local)
97
+ build_location = remote ? remote : local
98
+ is_remote = opensdg_is_path_remote(build_location)
99
+
100
+ build_location = is_remote ? build_location : File.join(Dir.pwd, build_location)
95
101
  translated_builds = site_uses_translated_builds(build_location)
96
102
 
97
103
  if translated_builds
98
104
  # For translated builds, we get a build for each language, and
99
105
  # place them in "subfolders" (so to speak) of site.data.
100
- site.config['languages'].each do |language|
106
+ subfolders = site.config['languages'].clone
107
+ subfolders.append('untranslated')
108
+ subfolders.each do |language|
101
109
  data_target = site.data[language]
102
- translated_build = remote ? build_location + '/' + language : File.join(build_location, language)
110
+ translated_build = is_remote ? build_location + '/' + language : File.join(build_location, language)
103
111
  data_source = fetch_build(translated_build)
104
- if data_target
105
- data_target.deep_merge(data_source)
106
- else
107
- site.data[language] = data_source
112
+ if !data_source.empty?
113
+ if data_target
114
+ data_target.deep_merge(data_source)
115
+ else
116
+ site.data[language] = data_source
117
+ end
108
118
  end
109
119
  end
110
120
  # We move the language-specific translations to the
@@ -129,7 +139,9 @@ module JekyllOpenSdgPlugins
129
139
  # in the "root" (so to speak) of site.data. Nothing else is needed.
130
140
  target = site.data
131
141
  source = fetch_build(build_location)
132
- target.deep_merge(source)
142
+ if !source.empty?
143
+ target.deep_merge(source)
144
+ end
133
145
  end
134
146
 
135
147
  # Finally support the deprecated 'remote_translations' option.
@@ -162,6 +174,14 @@ module JekyllOpenSdgPlugins
162
174
  source = File.join(Dir.pwd, site.config['local_data_folder'], '.')
163
175
  destination = site.config['destination']
164
176
  FileUtils.cp_r(source, destination)
177
+ # Do the same in the case that "remote_data_prefix" is being used for a local
178
+ # data folder (since "local_data_folder" is deprecated and undocumented).
179
+ elsif site.config['remote_data_prefix']
180
+ if !opensdg_is_path_remote(site.config['remote_data_prefix'])
181
+ source = File.join(Dir.pwd, site.config['remote_data_prefix'], '.')
182
+ destination = site.config['destination']
183
+ FileUtils.cp_r(source, destination)
184
+ end
165
185
  end
166
186
  end
167
187
  end
@@ -92,3 +92,41 @@ def opensdg_languages_public(site)
92
92
  # since the deprecated structure is exactly what this function wants.
93
93
  return languages_public
94
94
  end
95
+
96
+ # Print notices about a validation error.
97
+ def opensdg_validation_error(error)
98
+ if error['type'] == 'required'
99
+ missing = []
100
+ error['schema']['required'].each do |required_property|
101
+ unless error['data'].has_key?(required_property)
102
+ message = 'Missing configuration setting: ' + required_property
103
+ if error['schema'].has_key?('title')
104
+ message += ' (' + error['schema']['title'] + ')'
105
+ end
106
+ opensdg_notice(message)
107
+ end
108
+ end
109
+ else
110
+ message = 'Validation error of type: ' + error['type']
111
+ if error['schema'] && error['schema'].has_key?('title')
112
+ message += ' (' + error['schema']['title'] + ')'
113
+ end
114
+ opensdg_notice(message)
115
+ if error['schema']
116
+ opensdg_notice('Expected schema:')
117
+ puts error['schema'].inspect
118
+ end
119
+ if error['data']
120
+ opensdg_notice('Actual data:')
121
+ puts error['data'].inspect
122
+ end
123
+ end
124
+ end
125
+
126
+ # Is this path a remote path?
127
+ def opensdg_is_path_remote(path)
128
+ if path.nil?
129
+ return false
130
+ end
131
+ return path.start_with?('http')
132
+ end
@@ -0,0 +1,516 @@
1
+ {
2
+ "type": "object",
3
+ "title": "Open SDG indicator configuration",
4
+ "description": "This form will produce an indicator's configuration for your Open SDG implementation.",
5
+ "properties": {
6
+ "computation_units": {
7
+ "type": "string",
8
+ "title": "Unit of measurement",
9
+ "description": "Unit of measurement which displays below the indicator chart.",
10
+ "links": [
11
+ {
12
+ "rel": "More information",
13
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#recommended-special-fields"
14
+ }
15
+ ]
16
+ },
17
+ "copyright": {
18
+ "type": "string",
19
+ "title": "Copyright",
20
+ "description": "Copyright which displays below the indicator chart.",
21
+ "links": [
22
+ {
23
+ "rel": "More information",
24
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#footer"
25
+ }
26
+ ]
27
+ },
28
+ "data_footnote": {
29
+ "type": "string",
30
+ "format": "markdown",
31
+ "title": "Footnote",
32
+ "description": "Footnote which displays below the indicator chart.",
33
+ "links": [
34
+ {
35
+ "rel": "More information",
36
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#footer"
37
+ }
38
+ ]
39
+ },
40
+ "data_non_statistical": {
41
+ "title": "Non-statistical data",
42
+ "type": "boolean",
43
+ "description": "Whether the indicator is statistical (can be charted/graphed) or not.",
44
+ "format": "checkbox",
45
+ "links": [
46
+ {
47
+ "rel": "More information",
48
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#mandatory-fields"
49
+ }
50
+ ]
51
+ },
52
+ "data_notice_class": {
53
+ "title": "Data notice - class",
54
+ "type": "string",
55
+ "description": "A CSS class to apply to the data notice for this indicator.",
56
+ "links": [
57
+ {
58
+ "rel": "More information",
59
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#data-notice"
60
+ }
61
+ ]
62
+ },
63
+ "data_notice_heading": {
64
+ "title": "Data notice - heading",
65
+ "type": "string",
66
+ "description": "A title to display above the data notice for this indicator.",
67
+ "links": [
68
+ {
69
+ "rel": "More information",
70
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#data-notice"
71
+ }
72
+ ]
73
+ },
74
+ "data_notice_text": {
75
+ "title": "Data notice - text",
76
+ "type": "string",
77
+ "format": "markdown",
78
+ "description": "Text to display as a data notice for this indicator, intended to contain very important information which site viewers must keep in mind when using the data provided.",
79
+ "links": [
80
+ {
81
+ "rel": "More information",
82
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#data-notice"
83
+ }
84
+ ]
85
+ },
86
+ "data_show_map": {
87
+ "title": "Show map",
88
+ "type": "boolean",
89
+ "description": "Whether the indicator should display a Map tab.",
90
+ "format": "checkbox",
91
+ "links": [
92
+ {
93
+ "rel": "More information",
94
+ "href": "https://open-sdg.readthedocs.io/en/latest/maps/#metadata-field-data_show_map"
95
+ }
96
+ ]
97
+ },
98
+ "data_start_values": {
99
+ "options": {"collapsed": true},
100
+ "format": "table",
101
+ "type": "array",
102
+ "title": "Starting values",
103
+ "description": "Disaggregation values for a an indicator to start with already selected",
104
+ "items": {
105
+ "type": "object",
106
+ "title": "Starting value",
107
+ "properties": {
108
+ "field": {
109
+ "type": "string",
110
+ "minLength": 1,
111
+ "title": "Field",
112
+ "description": "The field (column) name."
113
+ },
114
+ "value": {
115
+ "type": "string",
116
+ "minLength": 1,
117
+ "title": "Value",
118
+ "description": "The value in that field to pre-select."
119
+ }
120
+ }
121
+ },
122
+ "links": [
123
+ {
124
+ "rel": "More information",
125
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#starting-values"
126
+ }
127
+ ]
128
+ },
129
+ "embedded_feature_footer": {
130
+ "type": "string",
131
+ "format": "markdown",
132
+ "title": "Embedded feature - Footer",
133
+ "description": "A footer that displays below the embedded feature. Only used with either embedded_feature_url or embedded_feature_html.",
134
+ "links": [
135
+ {
136
+ "rel": "More information",
137
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#embedded-feature-metadata"
138
+ }
139
+ ]
140
+ },
141
+ "embedded_feature_html": {
142
+ "type": "string",
143
+ "format": "textarea",
144
+ "title": "Embedded feature - HTML",
145
+ "description": "Any HTML to display in another tab, after Chart/Table/etc.",
146
+ "links": [
147
+ {
148
+ "rel": "More information",
149
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#embedded-feature-metadata"
150
+ }
151
+ ]
152
+ },
153
+ "embedded_feature_tab_title": {
154
+ "type": "string",
155
+ "title": "Embedded feature - Tab Title",
156
+ "description": "A title for the embedded feature tab (ie, Chart/Table/[this]). Only used with either embedded_feature_url or embedded_feature_html.",
157
+ "links": [
158
+ {
159
+ "rel": "More information",
160
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#embedded-feature-metadata"
161
+ }
162
+ ]
163
+ },
164
+ "embedded_feature_title": {
165
+ "type": "string",
166
+ "title": "Embedded feature - Title",
167
+ "description": "A title that displays above the embedded feature. Only used with either embedded_feature_url or embedded_feature_html.",
168
+ "links": [
169
+ {
170
+ "rel": "More information",
171
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#embedded-feature-metadata"
172
+ }
173
+ ]
174
+ },
175
+ "embedded_feature_url": {
176
+ "type": "string",
177
+ "format": "url",
178
+ "title": "Embedded feature - URL",
179
+ "description": "Any URL to display as an iframe in another tab, after Chart/Table/etc.",
180
+ "links": [
181
+ {
182
+ "rel": "More information",
183
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#embedded-feature-metadata"
184
+ }
185
+ ]
186
+ },
187
+ "graph_annotations": {
188
+ "options": {"collapsed": true},
189
+ "type": "array",
190
+ "title": "Graph annotations",
191
+ "description": "This can be used to add line annotations to the graph, such as target lines to show the progress towards the 2030 goal for an indicator.",
192
+ "items": {
193
+ "type": "object",
194
+ "title": "Graph annotation",
195
+ "properties": {
196
+ "preset": {
197
+ "type": "string",
198
+ "format": "choices",
199
+ "title": "Preset",
200
+ "enum": ["target_line"],
201
+ "description": "A preset bundle of configurations."
202
+ },
203
+ "value": {
204
+ "type": "number",
205
+ "minimum": 0,
206
+ "title": "Value",
207
+ "description": "The value at which to draw the line. For horizontal lines, this number corresponds to your actual data. For vertical lines, this number should be between 0 (the left side of the chart) and the number of years minus 1 (the right side of the chart)."
208
+ },
209
+ "endValue": {
210
+ "type": "number",
211
+ "title": "End value",
212
+ "description": "Optionally add a different ending value for the line."
213
+ },
214
+ "description": {
215
+ "type": "string",
216
+ "title": "Description",
217
+ "description": "A description of the annotation to be read by screenreaders."
218
+ },
219
+ "unit": {
220
+ "type": "string",
221
+ "title": "Unit",
222
+ "description": "The unit of measurement the annotation displays on."
223
+ },
224
+ "series": {
225
+ "type": "string",
226
+ "title": "Series",
227
+ "description": "The series the annotation displays on."
228
+ },
229
+ "mode": {
230
+ "type": "string",
231
+ "title": "Mode",
232
+ "description": "Whether the line will be vertical or horizontal.",
233
+ "enum": ["horizontal", "vertical"]
234
+ },
235
+ "borderColor": {
236
+ "type": "string",
237
+ "format": "color",
238
+ "title": "Line color",
239
+ "description": "The color of the line.",
240
+ "links": [
241
+ {
242
+ "rel": "More information",
243
+ "href": "https://github.com/chartjs/chartjs-plugin-annotation/blob/master/README.md"
244
+ }
245
+ ]
246
+ },
247
+ "borderDash": {
248
+ "type": "string",
249
+ "title": "Line dash type",
250
+ "description": "The type of line dash.",
251
+ "links": [
252
+ {
253
+ "rel": "More information",
254
+ "href": "https://github.com/chartjs/chartjs-plugin-annotation/blob/master/README.md"
255
+ }
256
+ ]
257
+ },
258
+ "label": {
259
+ "type": "object",
260
+ "title": "Label",
261
+ "description": "A text label for the annotation.",
262
+ "properties": {
263
+ "position": {
264
+ "type": "string",
265
+ "title": "Position",
266
+ "description": "Placement of the label along the line.",
267
+ "enum": [
268
+ "top",
269
+ "bottom",
270
+ "left",
271
+ "right",
272
+ "center"
273
+ ]
274
+ },
275
+ "content": {
276
+ "type": "string",
277
+ "minLength": 1,
278
+ "title": "Content",
279
+ "description": "Text of the line label."
280
+ },
281
+ "fontColor": {
282
+ "type": "string",
283
+ "format": "color",
284
+ "title": "Label color",
285
+ "description": "Color for the label text."
286
+ },
287
+ "backgroundColor": {
288
+ "type": "string",
289
+ "format": "color",
290
+ "default": "#FFFFFFF",
291
+ "title": "Background color",
292
+ "description": "Background color for the label text."
293
+ }
294
+ }
295
+ },
296
+ "highContrast": {
297
+ "type": "object",
298
+ "title": "High contrast options",
299
+ "description": "High-contrast overrides of certain color.",
300
+ "properties": {
301
+ "borderColor": {
302
+ "type": "string",
303
+ "format": "color",
304
+ "default": "#FFFFFF",
305
+ "title": "High-contrast line color",
306
+ "description": "The color of the line in high-contrast mode."
307
+ },
308
+ "label": {
309
+ "type": "object",
310
+ "title": "High contrast label",
311
+ "description": "High-contrast version of the label.",
312
+ "properties": {
313
+ "fontColor": {
314
+ "type": "string",
315
+ "format": "color",
316
+ "default": "#FFFFFF",
317
+ "title": "High-contrast label color",
318
+ "description": "Color for the label text in high-contrast mode."
319
+ },
320
+ "backgroundColor": {
321
+ "type": "string",
322
+ "format": "color",
323
+ "default": "#000000",
324
+ "title": "High-contrast background color",
325
+ "description": "Background color for the label text in high-contrast mode."
326
+ }
327
+ }
328
+ }
329
+ }
330
+ }
331
+ }
332
+ },
333
+ "links": [
334
+ {
335
+ "rel": "More information",
336
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#graph-metadata"
337
+ }
338
+ ]
339
+ },
340
+ "graph_limits": {
341
+ "options": {"collapsed": true},
342
+ "format": "table",
343
+ "type": "array",
344
+ "title": "Graph limits",
345
+ "description": "A list of min/max limits controlling the lowest/highest values to be shown on the y-axis.",
346
+ "items": {
347
+ "type": "object",
348
+ "title": "Graph limit",
349
+ "properties": {
350
+ "minimum": {
351
+ "type": "number",
352
+ "minimum": 0,
353
+ "title": "Minimum",
354
+ "description": "Minimum value for the y axis."
355
+ },
356
+ "maximum": {
357
+ "type": "number",
358
+ "minimum": 0,
359
+ "title": "Maximum",
360
+ "description": "Maximum value for the y axis."
361
+ },
362
+ "unit": {
363
+ "type": "string",
364
+ "title": "Unit",
365
+ "description": "The unit of measurement the limits apply to."
366
+ },
367
+ "series": {
368
+ "type": "string",
369
+ "title": "Series",
370
+ "description": "The series the limits apply to."
371
+ }
372
+ }
373
+ },
374
+ "links": [
375
+ {
376
+ "rel": "More information",
377
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#graph-metadata"
378
+ }
379
+ ]
380
+ },
381
+ "graph_stacked_disaggregation": {
382
+ "type": "string",
383
+ "title": "Stacked disaggregation",
384
+ "description": "This can be used with the bar graph type to place a certain disaggregation into the same stacked bars.",
385
+ "links": [
386
+ {
387
+ "rel": "More information",
388
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#recommended-special-fields"
389
+ }
390
+ ]
391
+ },
392
+ "graph_title": {
393
+ "type": "string",
394
+ "title": "Graph title",
395
+ "description": "The title that displays above the graph/chart.",
396
+ "links": [
397
+ {
398
+ "rel": "More information",
399
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#mandatory-for-statistical-indicators"
400
+ }
401
+ ]
402
+ },
403
+ "graph_titles": {
404
+ "options": {"collapsed": true},
405
+ "format": "table",
406
+ "type": "array",
407
+ "title": "Graph titles",
408
+ "description": "As an alternative to `graph_title`, this can be used to set specific titles for particular units and/or series.",
409
+ "items": {
410
+ "type": "object",
411
+ "title": "Graph title",
412
+ "properties": {
413
+ "title": {
414
+ "type": "string",
415
+ "minLength": 1,
416
+ "title": "Title",
417
+ "description": "The graph title."
418
+ },
419
+ "unit": {
420
+ "type": "string",
421
+ "title": "Unit",
422
+ "description": "The unit of measurement the title applies to."
423
+ },
424
+ "series": {
425
+ "type": "string",
426
+ "title": "Series",
427
+ "description": "The series the title applies to."
428
+ }
429
+ }
430
+ }
431
+ },
432
+ "graph_type": {
433
+ "type": "string",
434
+ "format": "choices",
435
+ "title": "Graph type",
436
+ "description": "What type of graph to use for the indicator.",
437
+ "enum": ["line", "bar", "binary"],
438
+ "links": [
439
+ {
440
+ "rel": "More information",
441
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#mandatory-for-statistical-indicators"
442
+ }
443
+ ]
444
+ },
445
+ "indicator_name": {
446
+ "type": "string",
447
+ "title": "Indicator name",
448
+ "description": "The name for the indicator, which displays at the top of the indicator page.",
449
+ "links": [
450
+ {
451
+ "rel": "More information",
452
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#mandatory-fields"
453
+ }
454
+ ]
455
+ },
456
+ "indicator_number": {
457
+ "type": "string",
458
+ "title": "Indicator number",
459
+ "description": "The number (or 'id') for the indicator.",
460
+ "links": [
461
+ {
462
+ "rel": "More information",
463
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#mandatory-fields"
464
+ }
465
+ ]
466
+ },
467
+ "national_geographical_coverage": {
468
+ "type": "string",
469
+ "title": "National geographical coverage",
470
+ "description": "A label used in the absence of any disaggregation.",
471
+ "links": [
472
+ {
473
+ "rel": "More information",
474
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#mandatory-for-statistical-indicators"
475
+ }
476
+ ]
477
+ },
478
+ "page_content": {
479
+ "type": "string",
480
+ "format": "markdown",
481
+ "title": "Page content",
482
+ "description": "Content which displays in the main content area of the indicator page."
483
+ },
484
+ "reporting_status": {
485
+ "type": "string",
486
+ "format": "choices",
487
+ "title": "Reporting status",
488
+ "enum": ["complete", "inprogress", "notstarted", "notapplicable"],
489
+ "description": "The status of the indicator.",
490
+ "links": [
491
+ {
492
+ "rel": "More information",
493
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#mandatory-fields"
494
+ }
495
+ ]
496
+ },
497
+ "tags": {
498
+ "options": {"collapsed": true},
499
+ "format": "table",
500
+ "type": "array",
501
+ "title": "Tags",
502
+ "description": "An optional list of 'tags' to display under an indicator when it is listed on its goal page.",
503
+ "items": {
504
+ "type": "string",
505
+ "title": "Tag"
506
+ },
507
+ "links": [
508
+ {
509
+ "rel": "More information",
510
+ "href": "https://open-sdg.readthedocs.io/en/latest/metadata-format/#recommended-special-fields"
511
+ }
512
+ ]
513
+ }
514
+ },
515
+ "additionalProperties": true
516
+ }