linked_rails 0.0.1 → 0.0.4.pre.g1faca9643
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/LICENSE +21 -674
- data/app/controllers/linked_rails/actions/objects_controller.rb +9 -0
- data/app/controllers/linked_rails/bulk_controller.rb +105 -22
- data/app/controllers/linked_rails/enum_values_controller.rb +0 -42
- data/app/models/linked_rails/actions/item.rb +64 -55
- data/app/models/linked_rails/actions/list.rb +6 -31
- data/app/models/linked_rails/actions/object.rb +38 -0
- data/app/models/linked_rails/collection/configuration.rb +55 -0
- data/app/models/linked_rails/collection/filter.rb +1 -1
- data/app/models/linked_rails/collection/filter_field.rb +19 -2
- data/app/models/linked_rails/collection/filter_option.rb +1 -1
- data/app/models/linked_rails/collection/filterable.rb +6 -9
- data/app/models/linked_rails/collection/infinite.rb +113 -0
- data/app/models/linked_rails/collection/infinite_view.rb +1 -90
- data/app/models/linked_rails/collection/iri.rb +47 -43
- data/app/models/linked_rails/collection/iri_mapping.rb +15 -7
- data/app/models/linked_rails/collection/paginated.rb +46 -0
- data/app/models/linked_rails/collection/paginated_view.rb +1 -33
- data/app/models/linked_rails/collection/sortable.rb +1 -9
- data/app/models/linked_rails/collection/sorting.rb +1 -1
- data/app/models/linked_rails/collection/view.rb +51 -14
- data/app/models/linked_rails/collection.rb +53 -85
- data/app/models/linked_rails/creative_work.rb +1 -1
- data/app/models/linked_rails/entry_point.rb +8 -5
- data/app/models/linked_rails/enum_value.rb +40 -2
- data/app/models/linked_rails/form/field/association_input.rb +7 -1
- data/app/models/linked_rails/form/field/file_input.rb +1 -0
- data/app/models/linked_rails/form/field/resource_field.rb +2 -0
- data/{lib/linked_rails/enhancements/indexable/model.rb → app/models/linked_rails/form/field/url_input.rb} +3 -3
- data/app/models/linked_rails/form/field.rb +37 -13
- data/app/models/linked_rails/form/field_factory.rb +48 -18
- data/app/models/linked_rails/form/group.rb +4 -6
- data/app/models/linked_rails/form/page.rb +8 -4
- data/app/models/linked_rails/form.rb +17 -21
- data/app/models/linked_rails/manifest.rb +102 -22
- data/app/models/linked_rails/menus/item.rb +10 -13
- data/app/models/linked_rails/menus/list.rb +16 -7
- data/app/models/linked_rails/ontology/base.rb +3 -1
- data/app/models/linked_rails/ontology/class.rb +3 -3
- data/app/models/linked_rails/ontology.rb +6 -5
- data/app/models/linked_rails/property_query.rb +2 -0
- data/app/models/linked_rails/sequence.rb +4 -13
- data/app/models/linked_rails/shacl/property_shape.rb +1 -1
- data/app/models/linked_rails/web_page.rb +0 -4
- data/app/models/linked_rails/web_site.rb +0 -4
- data/app/models/linked_rails/widget.rb +4 -11
- data/app/policies/linked_rails/actions/object_policy.rb +11 -0
- data/app/policies/linked_rails/collection_policy.rb +2 -2
- data/app/policies/linked_rails/form_policy.rb +13 -0
- data/app/policies/linked_rails/ontology_policy.rb +13 -0
- data/app/serializers/linked_rails/actions/item_serializer.rb +5 -5
- data/app/serializers/linked_rails/actions/object_serializer.rb +9 -0
- data/app/serializers/linked_rails/collection/filter_field_serializer.rb +3 -2
- data/app/serializers/linked_rails/collection/filter_option_serializer.rb +1 -1
- data/app/serializers/linked_rails/collection/filter_serializer.rb +1 -1
- data/app/serializers/linked_rails/collection/sorting_serializer.rb +1 -1
- data/app/serializers/linked_rails/collection/view_serializer.rb +3 -3
- data/app/serializers/linked_rails/collection_serializer.rb +8 -7
- data/app/serializers/linked_rails/condition_serializer.rb +3 -3
- data/app/serializers/linked_rails/entry_point_serializer.rb +3 -3
- data/app/serializers/linked_rails/enum_value_serializer.rb +1 -0
- data/app/serializers/linked_rails/form/field/association_input_serializer.rb +1 -0
- data/app/serializers/linked_rails/form/field/file_input_serializer.rb +11 -0
- data/app/serializers/linked_rails/form/field_serializer.rb +3 -1
- data/app/serializers/linked_rails/form/group_serializer.rb +1 -1
- data/app/serializers/linked_rails/form/page_serializer.rb +1 -1
- data/app/serializers/linked_rails/menus/item_serializer.rb +3 -3
- data/app/serializers/linked_rails/menus/list_serializer.rb +1 -1
- data/app/serializers/linked_rails/ontology_serializer.rb +2 -2
- data/app/serializers/linked_rails/property_query_serializer.rb +7 -0
- data/app/serializers/linked_rails/sequence_serializer.rb +2 -5
- data/app/serializers/linked_rails/shacl/node_shape_serializer.rb +1 -1
- data/app/serializers/linked_rails/shacl/property_shape_serializer.rb +1 -1
- data/app/serializers/linked_rails/shacl/shape_serializer.rb +5 -5
- data/app/serializers/linked_rails/web_page_serializer.rb +3 -3
- data/app/serializers/linked_rails/web_site_serializer.rb +1 -1
- data/app/serializers/linked_rails/widget_serializer.rb +3 -3
- data/app/workers/linked_rails/invalidation_stream_worker.rb +16 -0
- data/lib/generators/linked_rails/install/install_generator.rb +7 -8
- data/lib/generators/linked_rails/install/templates/README +7 -0
- data/lib/generators/linked_rails/install/templates/app_menu_list.rb +36 -7
- data/lib/generators/linked_rails/install/templates/application_menu_list.rb +40 -1
- data/lib/generators/linked_rails/install/templates/initializer.rb +1 -2
- data/lib/generators/linked_rails/install/templates/locales.yml +16 -0
- data/lib/generators/linked_rails/install/templates/rdf_serializers_initializer.rb +1 -1
- data/lib/generators/linked_rails/install/templates/vocab.rb +1 -0
- data/lib/generators/linked_rails/install/templates/vocab.yml +2 -2
- data/lib/generators/linked_rails/model/model_generator.rb +0 -1
- data/lib/generators/linked_rails/model/templates/controller.rb.tt +5 -1
- data/lib/generators/linked_rails/model/templates/form.rb.tt +3 -0
- data/lib/generators/linked_rails/model/templates/menu_list.rb.tt +15 -0
- data/lib/generators/linked_rails/model/templates/policy.rb.tt +13 -0
- data/lib/generators/linked_rails/model/templates/serializer.rb.tt +5 -1
- data/lib/linked_rails/active_response/controller/collections.rb +1 -1
- data/lib/linked_rails/active_response/controller/crud_defaults.rb +4 -4
- data/lib/linked_rails/active_response/controller/params.rb +10 -10
- data/lib/linked_rails/active_response/controller.rb +8 -18
- data/lib/linked_rails/active_response/responders/rdf.rb +19 -10
- data/lib/linked_rails/callable_variable.rb +1 -1
- data/lib/linked_rails/collection_params_parser.rb +93 -0
- data/lib/linked_rails/controller/actionable.rb +121 -0
- data/lib/linked_rails/controller/authorization.rb +6 -0
- data/lib/linked_rails/controller/default_actions/create.rb +52 -0
- data/lib/linked_rails/controller/default_actions/destroy.rb +42 -0
- data/lib/linked_rails/controller/default_actions/update.rb +43 -0
- data/lib/linked_rails/controller/delta.rb +58 -0
- data/lib/linked_rails/controller/error_handling.rb +14 -7
- data/lib/linked_rails/controller/rendering.rb +48 -0
- data/lib/linked_rails/controller.rb +24 -4
- data/lib/linked_rails/enhanceable.rb +1 -1
- data/lib/linked_rails/enhancements/creatable/controller.rb +1 -1
- data/lib/linked_rails/enhancements/destroyable/controller.rb +1 -1
- data/lib/linked_rails/enhancements/updatable/controller.rb +1 -1
- data/lib/linked_rails/enhancements.rb +0 -16
- data/lib/linked_rails/errors/forbidden.rb +37 -0
- data/lib/linked_rails/errors.rb +3 -0
- data/lib/linked_rails/helpers/delta_helper.rb +26 -57
- data/lib/linked_rails/helpers/ontola_actions_helper.rb +2 -2
- data/lib/linked_rails/helpers/resource_helper.rb +11 -2
- data/lib/linked_rails/iri_mapper.rb +17 -39
- data/lib/linked_rails/middleware/error_handling.rb +51 -0
- data/lib/linked_rails/middleware/linked_data_params.rb +30 -151
- data/lib/linked_rails/model/actionable.rb +68 -0
- data/lib/linked_rails/model/cacheable.rb +45 -0
- data/lib/linked_rails/model/collections.rb +201 -39
- data/lib/linked_rails/model/dirty.rb +6 -18
- data/lib/linked_rails/model/enhancements.rb +1 -6
- data/lib/linked_rails/model/filtering.rb +4 -6
- data/lib/linked_rails/model/indexable.rb +6 -16
- data/lib/linked_rails/model/iri.rb +29 -19
- data/lib/linked_rails/model/iri_mapping.rb +37 -8
- data/lib/linked_rails/model/menuable.rb +28 -0
- data/lib/linked_rails/model/serialization.rb +2 -15
- data/lib/linked_rails/model/singularable.rb +57 -0
- data/lib/linked_rails/model/sorting.rb +0 -5
- data/lib/linked_rails/model/tables.rb +26 -0
- data/lib/linked_rails/model.rb +18 -7
- data/lib/linked_rails/params_parser.rb +131 -54
- data/lib/linked_rails/policy/attribute_conditions.rb +2 -2
- data/lib/linked_rails/policy.rb +44 -46
- data/lib/linked_rails/railtie.rb +11 -0
- data/lib/linked_rails/rdf_error.rb +2 -2
- data/lib/linked_rails/renderers.rb +1 -0
- data/lib/linked_rails/routes.rb +38 -22
- data/lib/linked_rails/serializer/actionable.rb +27 -0
- data/lib/linked_rails/serializer/menuable.rb +31 -0
- data/lib/linked_rails/serializer/singularable.rb +26 -0
- data/lib/linked_rails/serializer.rb +28 -11
- data/lib/linked_rails/storage.rb +32 -0
- data/lib/linked_rails/test_methods.rb +114 -0
- data/lib/linked_rails/translate.rb +31 -9
- data/lib/linked_rails/types/iri_type.rb +37 -0
- data/lib/linked_rails/uri_template.rb +30 -0
- data/lib/linked_rails/url.rb +11 -0
- data/lib/linked_rails/version.rb +1 -1
- data/lib/linked_rails/vocab.rb +9 -0
- data/lib/linked_rails.rb +40 -14
- data/lib/rails/welcome_controller.rb +3 -2
- data/lib/rdf/list.rb +9 -0
- data/lib/rdf/query_fix.rb +15 -0
- metadata +80 -33
- data/app/models/linked_rails/actions/default_actions/create.rb +0 -60
- data/app/models/linked_rails/actions/default_actions/destroy.rb +0 -45
- data/app/models/linked_rails/actions/default_actions/update.rb +0 -50
- data/app/models/linked_rails/actions/default_actions.rb +0 -17
- data/lib/generators/linked_rails/install/templates/application_action_list.rb +0 -3
- data/lib/generators/linked_rails/model/templates/action_list.rb.tt +0 -6
- data/lib/linked_rails/enhancements/actionable/model.rb +0 -71
- data/lib/linked_rails/enhancements/actionable/serializer.rb +0 -25
- data/lib/linked_rails/enhancements/creatable/action.rb +0 -15
- data/lib/linked_rails/enhancements/destroyable/action.rb +0 -15
- data/lib/linked_rails/enhancements/destroyable/routing.rb +0 -19
- data/lib/linked_rails/enhancements/menuable/model.rb +0 -36
- data/lib/linked_rails/enhancements/menuable/serializer.rb +0 -33
- data/lib/linked_rails/enhancements/route_concerns.rb +0 -56
- data/lib/linked_rails/enhancements/singularable/controller.rb +0 -43
- data/lib/linked_rails/enhancements/singularable/model.rb +0 -47
- data/lib/linked_rails/enhancements/singularable/serializer.rb +0 -28
- data/lib/linked_rails/enhancements/tableable/model.rb +0 -28
- data/lib/linked_rails/enhancements/updatable/action.rb +0 -15
- data/lib/linked_rails/enhancements/updatable/routing.rb +0 -20
@@ -3,10 +3,17 @@
|
|
3
3
|
module LinkedRails
|
4
4
|
class Form
|
5
5
|
class FieldFactory # rubocop:disable Metrics/ClassLength
|
6
|
+
DATABASE_ERRORS = [
|
7
|
+
'PG::ConnectionBad'.safe_constantize,
|
8
|
+
ActiveRecord::StatementInvalid,
|
9
|
+
ActiveRecord::ConnectionNotEstablished
|
10
|
+
].compact.freeze
|
6
11
|
MAX_STR_LEN = 255
|
7
12
|
VALIDATOR_SELECTORS = [
|
8
13
|
[:min_length, ActiveModel::Validations::LengthValidator, :minimum],
|
14
|
+
[:min_inclusive, ActiveModel::Validations::NumericalityValidator, :greater_than_or_equal_to],
|
9
15
|
[:max_length, ActiveModel::Validations::LengthValidator, :maximum],
|
16
|
+
[:max_inclusive, ActiveModel::Validations::NumericalityValidator, :less_than_or_equal_to],
|
10
17
|
[:pattern, ActiveModel::Validations::FormatValidator, :with],
|
11
18
|
[:presence, ActiveModel::Validations::PresenceValidator, nil],
|
12
19
|
[:sh_in, ActiveModel::Validations::InclusionValidator, :in]
|
@@ -15,7 +22,8 @@ module LinkedRails
|
|
15
22
|
|
16
23
|
attr_accessor :field_options, :form, :key
|
17
24
|
|
18
|
-
delegate :
|
25
|
+
delegate :abstract_form,
|
26
|
+
:form_options_iri,
|
19
27
|
:model_class,
|
20
28
|
:model_policy!,
|
21
29
|
:serializer_attributes,
|
@@ -24,12 +32,21 @@ module LinkedRails
|
|
24
32
|
to: :form
|
25
33
|
|
26
34
|
def condition_or_field
|
27
|
-
@condition_or_field
|
35
|
+
return @condition_or_field if instance_variable_defined?(:@condition_or_field)
|
36
|
+
|
37
|
+
alternatives = node_shapes_for(
|
28
38
|
key,
|
29
|
-
field,
|
30
39
|
property: field_options[:if] || [],
|
31
40
|
sh_not: field_options[:unless] || []
|
32
41
|
)
|
42
|
+
@condition_or_field =
|
43
|
+
if alternatives.count == 1
|
44
|
+
Condition.new(shape: alternatives.first, pass: field)
|
45
|
+
elsif alternatives.count.positive?
|
46
|
+
Condition.new(shape: SHACL::NodeShape.new(or: alternatives), pass: field)
|
47
|
+
else
|
48
|
+
field
|
49
|
+
end
|
33
50
|
end
|
34
51
|
|
35
52
|
private
|
@@ -45,8 +62,7 @@ module LinkedRails
|
|
45
62
|
end
|
46
63
|
|
47
64
|
def attr_to_datatype # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
48
|
-
|
49
|
-
case attribute_type(name)
|
65
|
+
case attribute_type
|
50
66
|
when :string, :text
|
51
67
|
Vocab.xsd.string
|
52
68
|
when :integer
|
@@ -58,22 +74,26 @@ module LinkedRails
|
|
58
74
|
when :boolean
|
59
75
|
Vocab.xsd.boolean
|
60
76
|
when :decimal
|
61
|
-
decimal_data_type(
|
77
|
+
decimal_data_type(attribute_name)
|
62
78
|
when :file
|
63
79
|
Vocab.ll[:blob]
|
64
80
|
else
|
65
|
-
Vocab.xsd.string if model_class.try(:defined_enums)&.key?(
|
81
|
+
Vocab.xsd.string if model_class.try(:defined_enums)&.key?(attribute_name)
|
66
82
|
end
|
67
83
|
end
|
68
84
|
|
69
|
-
def
|
70
|
-
|
71
|
-
|
85
|
+
def attribute_name
|
86
|
+
serializer_attribute&.key&.to_s || key.to_s
|
87
|
+
end
|
88
|
+
|
89
|
+
def attribute_type
|
90
|
+
model_class.try(:attribute_types).try(:[], attribute_name)&.type
|
91
|
+
rescue *DATABASE_ERRORS
|
72
92
|
:string
|
73
93
|
end
|
74
94
|
|
75
95
|
def attribute_validators
|
76
|
-
@attribute_validators ||= model_class
|
96
|
+
@attribute_validators ||= model_class&.validators&.select { |v| v.attributes.include?(model_attribute) }
|
77
97
|
end
|
78
98
|
|
79
99
|
def datatype
|
@@ -143,7 +163,7 @@ module LinkedRails
|
|
143
163
|
when Vocab.ontola['datatype/postalRange']
|
144
164
|
return Form::Field::PostalRangeInput
|
145
165
|
else
|
146
|
-
|
166
|
+
attribute_type == :text ? Form::Field::TextAreaInput : Form::Field::TextInput
|
147
167
|
end
|
148
168
|
end
|
149
169
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
@@ -168,6 +188,15 @@ module LinkedRails
|
|
168
188
|
@model_attribute ||= (model_class.try(:attribute_alias, key) || key).to_sym
|
169
189
|
end
|
170
190
|
|
191
|
+
def node_shapes_for(attr, property: [], sh_not: [])
|
192
|
+
alternatives = abstract_form ? [] : model_policy!.condition_alternatives(attr, field.permission_required?)
|
193
|
+
alternatives = [[]] if alternatives.empty? && (property.any? || sh_not.any?)
|
194
|
+
|
195
|
+
alternatives.map do |props|
|
196
|
+
SHACL::NodeShape.new(property: props + property, sh_not: sh_not)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
171
200
|
def normalized_key(key)
|
172
201
|
return key.to_s[0...-3].to_sym if key.to_s.ends_with?('_id')
|
173
202
|
return key.to_s[0...-4].pluralize.to_sym if key.to_s.ends_with?('_ids')
|
@@ -197,14 +226,15 @@ module LinkedRails
|
|
197
226
|
def validator(klass, option_key)
|
198
227
|
matched_validator = validator_by_class(klass)
|
199
228
|
|
200
|
-
option_key ? matched_validator&.options.try(:[], option_key) : matched_validator.present?
|
229
|
+
value = option_key ? matched_validator&.options.try(:[], option_key) : matched_validator.present?
|
230
|
+
|
231
|
+
value unless value.respond_to?(:call)
|
201
232
|
end
|
202
233
|
|
203
234
|
def validator_by_class(klass)
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
matched_validator if matched_validator.options[:if].blank? && matched_validator.options[:unless].blank?
|
235
|
+
attribute_validators&.detect do |validator|
|
236
|
+
validator.is_a?(klass) && validator.options[:if].blank? && validator.options[:unless].blank?
|
237
|
+
end
|
208
238
|
end
|
209
239
|
|
210
240
|
def validators
|
@@ -212,7 +242,7 @@ module LinkedRails
|
|
212
242
|
VALIDATOR_SELECTORS.map do |key, klass, option_key|
|
213
243
|
[key, validator(klass, option_key)]
|
214
244
|
end
|
215
|
-
]
|
245
|
+
].compact
|
216
246
|
end
|
217
247
|
end
|
218
248
|
end
|
@@ -6,19 +6,17 @@ module LinkedRails
|
|
6
6
|
attr_accessor :fields, :collapsible, :hidden, :footer
|
7
7
|
attr_writer :description, :key, :label
|
8
8
|
|
9
|
-
def initialize(attrs
|
10
|
-
super(attrs)
|
9
|
+
def initialize(**attrs)
|
10
|
+
super(**attrs)
|
11
11
|
self.fields = []
|
12
12
|
end
|
13
13
|
|
14
14
|
def description
|
15
|
-
@description
|
16
|
-
@description
|
15
|
+
@description.respond_to?(:call) ? @description.call : @description
|
17
16
|
end
|
18
17
|
|
19
18
|
def label
|
20
|
-
@label
|
21
|
-
@label
|
19
|
+
@label.respond_to?(:call) ? @label.call : @label
|
22
20
|
end
|
23
21
|
|
24
22
|
def rdf_type
|
@@ -6,13 +6,13 @@ module LinkedRails
|
|
6
6
|
attr_accessor :groups, :label, :description
|
7
7
|
attr_writer :key
|
8
8
|
|
9
|
-
def initialize(attrs
|
10
|
-
super(attrs)
|
9
|
+
def initialize(**attrs)
|
10
|
+
super(**attrs)
|
11
11
|
self.groups = []
|
12
12
|
end
|
13
13
|
|
14
|
-
def add_group(opts)
|
15
|
-
group = Form::Group.new(opts)
|
14
|
+
def add_group(**opts)
|
15
|
+
group = Form::Group.new(**opts)
|
16
16
|
groups << group
|
17
17
|
group
|
18
18
|
end
|
@@ -21,6 +21,10 @@ module LinkedRails
|
|
21
21
|
@footer_group ||= add_group(collapsible: false, footer: true, key: :footer)
|
22
22
|
end
|
23
23
|
|
24
|
+
def footer_group!
|
25
|
+
@footer_group
|
26
|
+
end
|
27
|
+
|
24
28
|
class << self
|
25
29
|
def iri
|
26
30
|
Vocab.form[:Page]
|
@@ -5,10 +5,11 @@ require 'pundit'
|
|
5
5
|
module LinkedRails
|
6
6
|
class Form # rubocop:disable Metrics/ClassLength
|
7
7
|
include LinkedRails::Model
|
8
|
+
include LinkedRails::Model::Cacheable
|
8
9
|
|
9
|
-
class_attribute :pages, :model_class
|
10
|
+
class_attribute :abstract_form, :pages, :model_class
|
10
11
|
|
11
|
-
def root_relative_iri(_opts
|
12
|
+
def root_relative_iri(**_opts)
|
12
13
|
self.class.form_iri_path
|
13
14
|
end
|
14
15
|
|
@@ -63,10 +64,6 @@ module LinkedRails
|
|
63
64
|
@serializer_reflections ||= serializer_class&.relationships_to_serialize || {}
|
64
65
|
end
|
65
66
|
|
66
|
-
def preview_includes
|
67
|
-
[pages: {groups: [fields: [:fail, :pass, shape: [:property, nested_shapes: :property]]]}]
|
68
|
-
end
|
69
|
-
|
70
67
|
private
|
71
68
|
|
72
69
|
def current_group
|
@@ -85,7 +82,7 @@ module LinkedRails
|
|
85
82
|
@default_page ||= page(:default)
|
86
83
|
end
|
87
84
|
|
88
|
-
def field(key, opts
|
85
|
+
def field(key, **opts)
|
89
86
|
current_group.fields << Form::FieldFactory.new(
|
90
87
|
field_options: opts,
|
91
88
|
form: self,
|
@@ -94,9 +91,10 @@ module LinkedRails
|
|
94
91
|
end
|
95
92
|
|
96
93
|
def find_form_class(params)
|
97
|
-
|
94
|
+
form_name = [params[:module], "#{params[:id]&.singularize}_forms"].compact.join('/').classify
|
95
|
+
requested_class = form_name.safe_constantize
|
98
96
|
|
99
|
-
|
97
|
+
requested_class if requested_class && requested_class < LinkedRails::Form
|
100
98
|
end
|
101
99
|
|
102
100
|
def footer
|
@@ -108,10 +106,10 @@ module LinkedRails
|
|
108
106
|
current_page.footer_group
|
109
107
|
end
|
110
108
|
|
111
|
-
def group(key, opts
|
109
|
+
def group(key, **opts)
|
112
110
|
opts[:collapsible] = true unless opts.key?(:collapsible)
|
113
111
|
opts[:key] = key
|
114
|
-
group = current_page.add_group(opts)
|
112
|
+
group = current_page.add_group(**opts)
|
115
113
|
@current_group = group
|
116
114
|
|
117
115
|
yield if block_given?
|
@@ -120,26 +118,24 @@ module LinkedRails
|
|
120
118
|
group
|
121
119
|
end
|
122
120
|
|
123
|
-
|
124
|
-
def has_many(key, opts = {})
|
121
|
+
def has_many(key, **opts)
|
125
122
|
opts[:input_field] = Form::Field::AssociationInput
|
126
123
|
opts[:max_count] = 99
|
127
|
-
field(key, opts)
|
124
|
+
field(key, **opts)
|
128
125
|
end
|
129
126
|
|
130
|
-
def has_one(key, opts
|
127
|
+
def has_one(key, **opts)
|
131
128
|
opts[:input_field] = Form::Field::AssociationInput
|
132
129
|
opts[:max_count] = 1
|
133
|
-
field(key, opts)
|
130
|
+
field(key, **opts)
|
134
131
|
end
|
135
|
-
# rubocop:enable Naming/PredicateName
|
136
132
|
|
137
133
|
def hidden(&block)
|
138
134
|
group(:hidden, collapsible: false, hidden: true, &block)
|
139
135
|
end
|
140
136
|
|
141
|
-
def page(key, opts
|
142
|
-
page = Form::Page.new(opts.merge(key: key))
|
137
|
+
def page(key, **opts)
|
138
|
+
page = Form::Page.new(**opts.merge(key: key))
|
143
139
|
@current_page = page
|
144
140
|
pages << @current_page
|
145
141
|
yield if block_given?
|
@@ -147,9 +143,9 @@ module LinkedRails
|
|
147
143
|
page
|
148
144
|
end
|
149
145
|
|
150
|
-
def resource(key, opts
|
146
|
+
def resource(key, **opts)
|
151
147
|
opts[:input_field] = Form::Field::ResourceField
|
152
|
-
field(key, opts)
|
148
|
+
field(key, **opts)
|
153
149
|
end
|
154
150
|
end
|
155
151
|
end
|
@@ -5,6 +5,27 @@ module LinkedRails
|
|
5
5
|
include ActiveModel::Model
|
6
6
|
include LinkedRails::Model
|
7
7
|
|
8
|
+
def save
|
9
|
+
Storage.hset(
|
10
|
+
:persistent,
|
11
|
+
:manifest,
|
12
|
+
URL.as_href(LinkedRails.iri) => web_manifest.to_json
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
def web_manifest
|
17
|
+
web_manifest_base.merge(
|
18
|
+
ontola: web_manifest_ontola_section,
|
19
|
+
serviceworker: web_manifest_sw_section
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def allowed_external_sources
|
26
|
+
[]
|
27
|
+
end
|
28
|
+
|
8
29
|
def app_name
|
9
30
|
Rails.application.railtie_name.chomp('_application').humanize
|
10
31
|
end
|
@@ -17,8 +38,27 @@ module LinkedRails
|
|
17
38
|
'#eef0f2'
|
18
39
|
end
|
19
40
|
|
41
|
+
def blob_preview_iri
|
42
|
+
return unless ActiveStorage::Blob.service.present?
|
43
|
+
|
44
|
+
"#{LinkedRails.iri(path: 'rails/active_storage/blobs/redirect')}/{signed_id}/preview')"
|
45
|
+
end
|
46
|
+
|
47
|
+
def blob_upload_iri
|
48
|
+
return unless ActiveStorage::Blob.service.present?
|
49
|
+
|
50
|
+
LinkedRails.iri(path: 'rails/active_storage/direct_uploads')
|
51
|
+
end
|
52
|
+
|
20
53
|
def css_class; end
|
21
54
|
|
55
|
+
def csp_entries
|
56
|
+
{
|
57
|
+
connectSrc: [ActiveStorage::Blob.service.try(:bucket)&.url].compact,
|
58
|
+
scriptSrc: [ActiveStorage::Blob.service.try(:bucket)&.url].compact
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
22
62
|
def header_background
|
23
63
|
:primary
|
24
64
|
end
|
@@ -27,17 +67,16 @@ module LinkedRails
|
|
27
67
|
:white
|
28
68
|
end
|
29
69
|
|
30
|
-
def
|
31
|
-
[
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
]
|
70
|
+
def icons
|
71
|
+
[]
|
72
|
+
end
|
73
|
+
|
74
|
+
def lang
|
75
|
+
:nl
|
37
76
|
end
|
38
77
|
|
39
78
|
def scope
|
40
|
-
|
79
|
+
LinkedRails.iri.to_s
|
41
80
|
end
|
42
81
|
|
43
82
|
def site_theme_color
|
@@ -52,51 +91,92 @@ module LinkedRails
|
|
52
91
|
app_name
|
53
92
|
end
|
54
93
|
|
94
|
+
def start_url
|
95
|
+
scope == '/' ? scope : "#{scope}/"
|
96
|
+
end
|
97
|
+
|
55
98
|
def theme; end
|
56
99
|
|
57
100
|
def theme_options
|
58
101
|
{}
|
59
102
|
end
|
60
103
|
|
61
|
-
def web_manifest
|
62
|
-
web_manifest_base.merge(
|
63
|
-
ontola: web_manifest_ontola_section,
|
64
|
-
serviceworker: web_manifest_sw_section
|
65
|
-
)
|
66
|
-
end
|
67
|
-
|
68
104
|
def web_manifest_base # rubocop:disable Metrics/MethodLength
|
69
105
|
{
|
70
106
|
background_color: background_color,
|
71
107
|
dir: :rtl,
|
72
108
|
display: :standalone,
|
73
|
-
|
109
|
+
icons: icons,
|
110
|
+
lang: lang,
|
74
111
|
name: app_name,
|
75
112
|
scope: scope,
|
76
113
|
short_name: app_name,
|
77
|
-
start_url:
|
114
|
+
start_url: start_url,
|
78
115
|
theme_color: site_theme_color
|
79
116
|
}
|
80
117
|
end
|
81
118
|
|
82
|
-
def web_manifest_ontola_section
|
119
|
+
def web_manifest_ontola_section # rubocop:disable Metrics/MethodLength
|
83
120
|
{
|
84
|
-
|
121
|
+
allowed_external_sources: allowed_external_sources,
|
122
|
+
blob_preview_iri: blob_preview_iri,
|
123
|
+
blob_upload_iri: blob_upload_iri,
|
124
|
+
csp: csp_entries,
|
85
125
|
header_background: header_background,
|
86
126
|
header_text: header_text,
|
87
|
-
|
127
|
+
preconnect: preconnect,
|
88
128
|
primary_color: site_theme_color,
|
89
129
|
secondary_color: site_secondary_color,
|
130
|
+
styled_headers: styled_headers,
|
90
131
|
theme: theme,
|
91
|
-
theme_options: theme_options.to_query
|
132
|
+
theme_options: theme_options.to_query,
|
133
|
+
tracking: tracking,
|
134
|
+
website_iri: LinkedRails.iri.to_s,
|
135
|
+
websocket_path: websocket_path
|
92
136
|
}
|
93
137
|
end
|
94
138
|
|
95
139
|
def web_manifest_sw_section
|
96
140
|
{
|
97
|
-
src: "#{scope}/sw.js
|
141
|
+
src: "#{scope.chomp('/')}/sw.js",
|
98
142
|
scope: scope
|
99
143
|
}
|
100
144
|
end
|
145
|
+
|
146
|
+
def websocket_path
|
147
|
+
Rails.application.config.try(:action_cable).try(:mount_path).try(:[], 1..-1)
|
148
|
+
end
|
149
|
+
|
150
|
+
def preconnect
|
151
|
+
[]
|
152
|
+
end
|
153
|
+
|
154
|
+
def styled_headers
|
155
|
+
false
|
156
|
+
end
|
157
|
+
|
158
|
+
def tracking
|
159
|
+
[]
|
160
|
+
end
|
161
|
+
|
162
|
+
class << self
|
163
|
+
def destroy(iri)
|
164
|
+
Storage.hdel(:persistent, :manifest, URL.as_href(iri))
|
165
|
+
end
|
166
|
+
|
167
|
+
def move(from, to)
|
168
|
+
Storage.hset(
|
169
|
+
:persistent,
|
170
|
+
:redirect_prefix,
|
171
|
+
URL.as_href(from) => URL.as_href(to)
|
172
|
+
)
|
173
|
+
|
174
|
+
data = Storage.hget(:persistent, :manifest, URL.as_href(from))
|
175
|
+
|
176
|
+
Storage.hset(:persistent, :manifest, URL.as_href(to), data) if data
|
177
|
+
|
178
|
+
destroy(from)
|
179
|
+
end
|
180
|
+
end
|
101
181
|
end
|
102
182
|
end
|
@@ -12,7 +12,7 @@ module LinkedRails
|
|
12
12
|
delegate :iri_opts, to: :parent
|
13
13
|
|
14
14
|
alias id iri
|
15
|
-
%i[action href image label
|
15
|
+
%i[action href image label iri_base].each do |method|
|
16
16
|
callable_variable(method, instance: :parent)
|
17
17
|
end
|
18
18
|
|
@@ -26,7 +26,7 @@ module LinkedRails
|
|
26
26
|
def iri_template
|
27
27
|
return parent.send(:iri_template) unless parent.is_a?(LinkedRails::Menus::List)
|
28
28
|
|
29
|
-
return URITemplate.new("#{iri_base}{/tag}{#fragment}") if iri_base
|
29
|
+
return LinkedRails::URITemplate.new("#{iri_base}{/tag}{#fragment}") if iri_base
|
30
30
|
|
31
31
|
iri_template_expand_path(parent.send(:iri_template), '{/tag}')
|
32
32
|
end
|
@@ -36,7 +36,7 @@ module LinkedRails
|
|
36
36
|
|
37
37
|
@menu_sequence ||=
|
38
38
|
LinkedRails::Sequence.new(
|
39
|
-
-> { menus
|
39
|
+
-> { menus },
|
40
40
|
id: menu_sequence_iri,
|
41
41
|
parent: self,
|
42
42
|
scope: false
|
@@ -52,6 +52,12 @@ module LinkedRails
|
|
52
52
|
sequence_iri
|
53
53
|
end
|
54
54
|
|
55
|
+
def menus
|
56
|
+
return @menus unless @menus.respond_to?(:call)
|
57
|
+
|
58
|
+
@menus = parent.instance_exec(&@menus).compact.each { |menu| menu.parent = self }
|
59
|
+
end
|
60
|
+
|
55
61
|
def rdf_type
|
56
62
|
type || Vocab.ontola[:MenuItem]
|
57
63
|
end
|
@@ -67,17 +73,8 @@ module LinkedRails
|
|
67
73
|
end
|
68
74
|
|
69
75
|
class << self
|
70
|
-
def base_includes
|
71
|
-
[action: :target]
|
72
|
-
end
|
73
|
-
|
74
76
|
def preview_includes
|
75
|
-
|
76
|
-
menu_sequence: [
|
77
|
-
members: base_includes +
|
78
|
-
[menu_sequence: [members: base_includes]]
|
79
|
-
]
|
80
|
-
]
|
77
|
+
[menu_sequence: [members: [menu_sequence: :members]]]
|
81
78
|
end
|
82
79
|
|
83
80
|
def requested_index_resource(params, user_context)
|
@@ -20,21 +20,28 @@ module LinkedRails
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def iri_opts
|
23
|
-
|
23
|
+
return {} if resource.blank?
|
24
|
+
|
25
|
+
resource.try(:singular_resource?) ? resource.singular_iri_opts : resource.iri_opts
|
24
26
|
end
|
25
27
|
|
26
28
|
def menus
|
27
|
-
@menus ||= available_menus.map(&method(:
|
29
|
+
@menus ||= available_menus.map(&method(:memoized_menu_item))
|
28
30
|
end
|
29
31
|
|
30
32
|
def menu(tag)
|
31
|
-
|
33
|
+
memoized_menu_item(tag, available_menus[tag].dup) if available_menus.key?(tag)
|
32
34
|
end
|
33
35
|
|
34
36
|
private
|
35
37
|
|
36
38
|
def default_label(tag, options)
|
37
|
-
I18n.t("menus.#{resource&.class&.name&.tableize}.#{tag}", options[:label_params])
|
39
|
+
I18n.t("menus.#{resource&.class&.name&.tableize}.#{tag}", **options[:label_params])
|
40
|
+
end
|
41
|
+
|
42
|
+
def memoized_menu_item(tag, options)
|
43
|
+
@memoized_menu_item ||= {}
|
44
|
+
@memoized_menu_item[tag] ||= menu_item(tag, options)
|
38
45
|
end
|
39
46
|
|
40
47
|
def menu_available?(_tag, options)
|
@@ -48,6 +55,7 @@ module LinkedRails
|
|
48
55
|
options[:label_params] ||= {}
|
49
56
|
options[:label_params][:default] ||= ["menus.default.#{tag}".to_sym, tag.to_s.capitalize]
|
50
57
|
options[:label] ||= default_label(tag, options)
|
58
|
+
options[:action] = ontola_dialog_action(options[:href]) if options.delete(:dialog)
|
51
59
|
options.except!(:policy_resource, :policy, :policy_arguments, :label_params)
|
52
60
|
LinkedRails.menus_item_class.new(resource: resource, tag: tag, parent: self, **options)
|
53
61
|
end
|
@@ -62,7 +70,9 @@ module LinkedRails
|
|
62
70
|
end
|
63
71
|
|
64
72
|
def iri_template
|
65
|
-
|
73
|
+
base_template = resource.send(resource.try(:singular_resource?) ? :singular_iri_template : :iri_template)
|
74
|
+
|
75
|
+
@iri_template ||= iri_template_expand_path(base_template, '/menus')
|
66
76
|
end
|
67
77
|
|
68
78
|
class << self
|
@@ -88,7 +98,7 @@ module LinkedRails
|
|
88
98
|
_defined_menus || {}
|
89
99
|
end
|
90
100
|
|
91
|
-
def has_menu(tag, opts
|
101
|
+
def has_menu(tag, **opts)
|
92
102
|
defined_menus[tag] = opts
|
93
103
|
end
|
94
104
|
|
@@ -100,7 +110,6 @@ module LinkedRails
|
|
100
110
|
LinkedRails::Sequence.new(
|
101
111
|
menu_list.menus,
|
102
112
|
id: menu_list.iri,
|
103
|
-
member_includes: Item.preview_includes,
|
104
113
|
scope: false
|
105
114
|
)
|
106
115
|
end
|
@@ -9,7 +9,7 @@ module LinkedRails
|
|
9
9
|
|
10
10
|
def data
|
11
11
|
data = []
|
12
|
-
iri.each_statement do |statement|
|
12
|
+
iri.try(:each_statement) do |statement|
|
13
13
|
next unless include_data_statement?(statement)
|
14
14
|
|
15
15
|
statement.graph_name = ::RDF::Serializers.config.default_graph
|
@@ -41,6 +41,8 @@ module LinkedRails
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def include_data_statement?(statement)
|
44
|
+
return false if statement.subject.node? || statement.object.node?
|
45
|
+
|
44
46
|
statement.predicate != Vocab.rdfs.label &&
|
45
47
|
statement.predicate != Vocab.rdfs.range &&
|
46
48
|
statement.predicate != Vocab.rdfs.domain
|
@@ -12,10 +12,10 @@ module LinkedRails
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def parent_class
|
15
|
-
if klass
|
15
|
+
if klass&.superclass == ApplicationRecord
|
16
16
|
Vocab.schema.Thing
|
17
17
|
else
|
18
|
-
klass
|
18
|
+
klass&.superclass.try(:iri) || Vocab.schema.Thing
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -26,7 +26,7 @@ module LinkedRails
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def properties
|
29
|
-
@properties ||= klass
|
29
|
+
@properties ||= klass&.predicate_mapping&.keys&.map { |key| LinkedRails.ontology_property_class.new(iri: key) }
|
30
30
|
end
|
31
31
|
|
32
32
|
class << self
|
@@ -4,13 +4,14 @@ module LinkedRails
|
|
4
4
|
class Ontology
|
5
5
|
include ActiveModel::Model
|
6
6
|
include LinkedRails::Model
|
7
|
+
include LinkedRails::Model::Cacheable
|
7
8
|
|
8
9
|
def classes
|
9
|
-
@classes ||=
|
10
|
+
@classes ||= LinkedRails.linked_models.map do |klass|
|
10
11
|
iri = klass.iri.is_a?(Array) ? klass.iri.first : klass.iri
|
11
12
|
|
12
|
-
LinkedRails.ontology_class_class.new(klass: klass, iri: iri)
|
13
|
-
end
|
13
|
+
LinkedRails.ontology_class_class.new(klass: klass, iri: iri) if iri
|
14
|
+
end.compact
|
14
15
|
end
|
15
16
|
|
16
17
|
def properties
|
@@ -26,8 +27,8 @@ module LinkedRails
|
|
26
27
|
%i[classes properties]
|
27
28
|
end
|
28
29
|
|
29
|
-
def requested_resource(
|
30
|
-
LinkedRails.ontology_class.new
|
30
|
+
def requested_resource(opts, _user_context)
|
31
|
+
LinkedRails.ontology_class.new if opts[:iri].include?(new.root_relative_iri)
|
31
32
|
end
|
32
33
|
end
|
33
34
|
end
|