solidus_content 0.1.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 +7 -0
- data/.circleci/config.yml +72 -0
- data/.gem_release.yml +5 -0
- data/.github/stale.yml +17 -0
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/.rubocop.yml +38 -0
- data/Gemfile +38 -0
- data/LICENSE +26 -0
- data/README.md +439 -0
- data/Rakefile +6 -0
- data/app/assets/javascripts/spree/backend/solidus_content.js +2 -0
- data/app/assets/javascripts/spree/frontend/solidus_content.js +2 -0
- data/app/assets/stylesheets/spree/backend/solidus_content.css +4 -0
- data/app/assets/stylesheets/spree/frontend/solidus_content.css +4 -0
- data/app/controllers/solidus_content/resource_controller.rb +35 -0
- data/app/controllers/spree/admin/entries_controller.rb +25 -0
- data/app/controllers/spree/admin/entry_types_controller.rb +25 -0
- data/app/controllers/spree/solidus_content_controller.rb +13 -0
- data/app/models/solidus_content/application_record.rb +5 -0
- data/app/models/solidus_content/entry.rb +44 -0
- data/app/models/solidus_content/entry_type.rb +55 -0
- data/app/models/solidus_content/provider/fields.rb +20 -0
- data/app/views/spree/admin/entries/_form.html.erb +31 -0
- data/app/views/spree/admin/entries/_options_form.html.erb +18 -0
- data/app/views/spree/admin/entries/edit.html.erb +16 -0
- data/app/views/spree/admin/entries/index.html.erb +54 -0
- data/app/views/spree/admin/entries/new.html.erb +21 -0
- data/app/views/spree/admin/entry_types/_form.html.erb +30 -0
- data/app/views/spree/admin/entry_types/_options_form.html.erb +16 -0
- data/app/views/spree/admin/entry_types/edit.html.erb +16 -0
- data/app/views/spree/admin/entry_types/index.html.erb +54 -0
- data/app/views/spree/admin/entry_types/new.html.erb +21 -0
- data/app/views/spree/admin/shared/_solidus_content_sub_menu.html.erb +9 -0
- data/bin/console +17 -0
- data/bin/rails +7 -0
- data/bin/rails-engine +13 -0
- data/bin/rails-sandbox +16 -0
- data/bin/rake +7 -0
- data/bin/rspec +7 -0
- data/bin/sandbox +84 -0
- data/bin/setup +8 -0
- data/config/initializers/spree.rb +12 -0
- data/config/locales/en.yml +51 -0
- data/config/routes.rb +14 -0
- data/db/migrate/20200207135842_create_solidus_content_entries.rb +11 -0
- data/db/migrate/20200306110114_create_solidus_content_entry_types.rb +12 -0
- data/lib/generators/solidus_content/install/install_generator.rb +36 -0
- data/lib/generators/solidus_content/install/templates/initializer.rb +20 -0
- data/lib/solidus_content.rb +10 -0
- data/lib/solidus_content/active_record.rb +7 -0
- data/lib/solidus_content/configuration.rb +38 -0
- data/lib/solidus_content/engine.rb +19 -0
- data/lib/solidus_content/factories.rb +13 -0
- data/lib/solidus_content/providers.rb +23 -0
- data/lib/solidus_content/providers/contentful.rb +36 -0
- data/lib/solidus_content/providers/json.rb +27 -0
- data/lib/solidus_content/providers/prismic.rb +36 -0
- data/lib/solidus_content/providers/raw.rb +22 -0
- data/lib/solidus_content/providers/solidus_static_content.rb +23 -0
- data/lib/solidus_content/providers/yaml.rb +33 -0
- data/lib/solidus_content/version.rb +5 -0
- data/solidus_content.gemspec +36 -0
- data/spec/features/admin/content/create_entry_spec.rb +36 -0
- data/spec/features/admin/content/create_entry_type_spec.rb +36 -0
- data/spec/features/admin/content/delete_entry_spec.rb +20 -0
- data/spec/features/admin/content/delete_entry_type_spec.rb +20 -0
- data/spec/features/admin/content/edit_entry_spec.rb +45 -0
- data/spec/features/admin/content/edit_entry_type_spec.rb +44 -0
- data/spec/features/admin/content/list_entries_spec.rb +33 -0
- data/spec/features/admin/content/list_entry_types_spec.rb +33 -0
- data/spec/features/admin/sidebar_spec.rb +19 -0
- data/spec/features/render_content_with_views_spec.rb +41 -0
- data/spec/fixtures/content/example.json +1 -0
- data/spec/fixtures/content/example.yaml +1 -0
- data/spec/fixtures/content/example.yml +1 -0
- data/spec/fixtures/content/example_2.yaml +1 -0
- data/spec/models/solidus_content/entry_spec.rb +100 -0
- data/spec/models/solidus_content/entry_type_spec.rb +106 -0
- data/spec/solidus_content/configuration_spec.rb +37 -0
- data/spec/solidus_content/providers/contentful_spec.rb +56 -0
- data/spec/solidus_content/providers/json_spec.rb +33 -0
- data/spec/solidus_content/providers/prismic_spec.rb +82 -0
- data/spec/solidus_content/providers/solidus_static_content_spec.rb +34 -0
- data/spec/solidus_content/providers/yaml_spec.rb +51 -0
- data/spec/solidus_content_spec.rb +23 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/warden.rb +5 -0
- metadata +206 -0
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusContent
|
4
|
+
class ResourceController < Spree::Admin::ResourceController
|
5
|
+
private
|
6
|
+
|
7
|
+
def location_after_save
|
8
|
+
edit_object_url(@object)
|
9
|
+
end
|
10
|
+
|
11
|
+
def collection
|
12
|
+
super.page(params[:page] || 0)
|
13
|
+
end
|
14
|
+
|
15
|
+
def model_class
|
16
|
+
"SolidusContent::#{controller_name.classify}".constantize
|
17
|
+
end
|
18
|
+
|
19
|
+
def new_object_url(options = {})
|
20
|
+
send(:"new_admin_#{controller_name.singularize}_path", options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def edit_object_url(object, options = {})
|
24
|
+
send(:"edit_admin_#{controller_name.singularize}_path", object, options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def object_url(object = nil, options = {})
|
28
|
+
send(:"admin_#{controller_name.singularize}_path", object, options)
|
29
|
+
end
|
30
|
+
|
31
|
+
def collection_url(options = {})
|
32
|
+
send(:"admin_#{controller_name}_path", options)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
module Admin
|
5
|
+
class EntriesController < SolidusContent::ResourceController
|
6
|
+
helper_method :model_class
|
7
|
+
|
8
|
+
def show
|
9
|
+
redirect_to action: :edit
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def permitted_resource_params
|
15
|
+
params
|
16
|
+
.require(:solidus_content_entry)
|
17
|
+
.permit(:slug, :entry_type_id, *provider_params)
|
18
|
+
end
|
19
|
+
|
20
|
+
def provider_params
|
21
|
+
@object.entry_fields || []
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
module Admin
|
5
|
+
class EntryTypesController < SolidusContent::ResourceController
|
6
|
+
helper_method :model_class
|
7
|
+
|
8
|
+
def show
|
9
|
+
redirect_to action: :edit
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def permitted_resource_params
|
15
|
+
params
|
16
|
+
.require(:solidus_content_entry_type)
|
17
|
+
.permit(:name, :provider_name, *provider_params)
|
18
|
+
end
|
19
|
+
|
20
|
+
def provider_params
|
21
|
+
@object.entry_type_fields || []
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_dependency 'solidus_content/entry_type'
|
4
|
+
|
5
|
+
class Spree::SolidusContentController < Spree::StoreController
|
6
|
+
def show
|
7
|
+
slug = params[:id] || :default
|
8
|
+
type = params[:type]
|
9
|
+
|
10
|
+
@entry = ::SolidusContent::Entry.by_type(type).by_slug(slug)
|
11
|
+
render action: type
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class SolidusContent::Entry < SolidusContent::ApplicationRecord
|
4
|
+
include SolidusContent::Provider::Fields
|
5
|
+
|
6
|
+
belongs_to :entry_type
|
7
|
+
|
8
|
+
after_initialize { self.options ||= {} }
|
9
|
+
after_initialize :inject_entry_fields, if: :entry_type_id?
|
10
|
+
|
11
|
+
validates :slug, presence: true, uniqueness: { scope: :entry_type_id }
|
12
|
+
|
13
|
+
scope :by_slug, ->(slug) { find_by!(slug: slug) }
|
14
|
+
scope :by_type, ->(type) {
|
15
|
+
unless type.is_a? SolidusContent::EntryType
|
16
|
+
type = SolidusContent::EntryType.by_name(type)
|
17
|
+
end
|
18
|
+
where(entry_type: type)
|
19
|
+
}
|
20
|
+
|
21
|
+
def self.data_for(type, slug)
|
22
|
+
by_type(type).by_slug(slug).data
|
23
|
+
end
|
24
|
+
|
25
|
+
def data
|
26
|
+
content[:data]
|
27
|
+
end
|
28
|
+
|
29
|
+
def content
|
30
|
+
@content ||= entry_type.content_for(self)
|
31
|
+
end
|
32
|
+
|
33
|
+
def entry_fields
|
34
|
+
return unless entry_type_id?
|
35
|
+
|
36
|
+
entry_type.provider_class.entry_fields
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def inject_entry_fields
|
42
|
+
provider_based_attr_reader(entry_fields)
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class SolidusContent::EntryType < SolidusContent::ApplicationRecord
|
4
|
+
include SolidusContent::Provider::Fields
|
5
|
+
|
6
|
+
has_many :entries, dependent: :destroy
|
7
|
+
|
8
|
+
scope :by_name, ->(name) { find_by!(name: name) }
|
9
|
+
|
10
|
+
validates :name, presence: true
|
11
|
+
validates :provider_name, presence: true
|
12
|
+
validates :name, :provider_name, presence: true
|
13
|
+
validate :ensure_provider_name_is_not_changed
|
14
|
+
|
15
|
+
after_initialize { self.options ||= {} }
|
16
|
+
after_initialize :inject_provider_fields, if: :provider_name?
|
17
|
+
|
18
|
+
scope :by_name, ->(name) { find_by!(name: name) }
|
19
|
+
|
20
|
+
def content_for(entry)
|
21
|
+
provider_class.call(
|
22
|
+
slug: entry.slug,
|
23
|
+
type: name,
|
24
|
+
provider: provider_name,
|
25
|
+
options: entry.options.symbolize_keys,
|
26
|
+
type_options: options.symbolize_keys,
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def provider_class
|
31
|
+
SolidusContent.config.providers[provider_name.to_sym]
|
32
|
+
end
|
33
|
+
|
34
|
+
def provider_name_readonly?
|
35
|
+
persisted?
|
36
|
+
end
|
37
|
+
|
38
|
+
def entry_type_fields
|
39
|
+
return unless provider_name
|
40
|
+
|
41
|
+
provider_class.entry_type_fields
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def inject_provider_fields
|
47
|
+
provider_based_attr_reader(entry_type_fields)
|
48
|
+
end
|
49
|
+
|
50
|
+
def ensure_provider_name_is_not_changed
|
51
|
+
return unless provider_name_changed? && persisted?
|
52
|
+
|
53
|
+
errors.add :provider_name, :readonly
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusContent
|
4
|
+
module Provider
|
5
|
+
module Fields
|
6
|
+
def provider_based_attr_reader(attrs)
|
7
|
+
attrs.each do |attr|
|
8
|
+
define_singleton_method(attr) do
|
9
|
+
options[attr.to_s] || ''
|
10
|
+
end
|
11
|
+
|
12
|
+
define_singleton_method("#{attr}=") do |value|
|
13
|
+
attribute_will_change!(:options)
|
14
|
+
options[attr.to_s] = value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<% entry_type_options = SolidusContent::EntryType.pluck(:name, :id) %>
|
2
|
+
|
3
|
+
<div data-hook="admin_entry_form_fields">
|
4
|
+
<div class="row">
|
5
|
+
<div class="left col-12" data-hook="admin_entry_form">
|
6
|
+
<div class="row">
|
7
|
+
<div class="col-6" data-hook="admin_entry_form_name">
|
8
|
+
<%= form.field_container :slug do %>
|
9
|
+
<%= form.field_hint :slug %>
|
10
|
+
<%= form.label :slug, class: 'required' %><br />
|
11
|
+
<%= form.text_field :slug, class: 'fullwidth' %>
|
12
|
+
<% end %>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<div class="col-6" data-hook="admin_entry_form_provider">
|
16
|
+
<%= form.field_container :entry_type_id do %>
|
17
|
+
<%= form.field_hint :entry_type_id %>
|
18
|
+
<%= form.label :entry_type_id, class: 'required' %><br />
|
19
|
+
<%= form.select :entry_type_id, entry_type_options, { include_blank: false }, { disabled: form.object.persisted?, class: 'custom-select fullwidth' } %>
|
20
|
+
<% end %>
|
21
|
+
</div>
|
22
|
+
|
23
|
+
<%= form.hidden_field :options, value: '{}' %>
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
</div>
|
27
|
+
|
28
|
+
<% if form.object.persisted? && @object.entry_fields.count > 0 %>
|
29
|
+
<%= render "options_form", form: form %>
|
30
|
+
<% end %>
|
31
|
+
</div>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<fieldset class="no-border-bottom">
|
2
|
+
<legend>
|
3
|
+
<%= @entry.entry_type.name %>
|
4
|
+
<%= model_class.human_attribute_name(:options) %>
|
5
|
+
(<%= SolidusContent.human_provider_name(@entry.entry_type.provider_name) %>)
|
6
|
+
</legend>
|
7
|
+
|
8
|
+
<div class="row">
|
9
|
+
<% @entry.entry_fields.each do |field| %>
|
10
|
+
<div class="col-12" data-hook="admin_entry_<%= field %>">
|
11
|
+
<div class="field" id="solidus_content_entry_<%= field %>_field">
|
12
|
+
<%= form.label field %>
|
13
|
+
<%= form.text_field field, class: 'fullwidth' %>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
<% end %>
|
17
|
+
</div>
|
18
|
+
</fieldset>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<% admin_breadcrumb link_to(plural_resource_name(model_class), spree.admin_entries_path) %>
|
2
|
+
<% admin_breadcrumb @object.slug %>
|
3
|
+
|
4
|
+
<%= render 'spree/shared/error_messages', target: @object %>
|
5
|
+
|
6
|
+
<%= form_for @entry, url: spree.admin_entry_path(@entry) do |form| %>
|
7
|
+
<fieldset data-hook="edit_entry">
|
8
|
+
<%= content_tag :legend, model_class.model_name.human %>
|
9
|
+
<%= render 'form', form: form %>
|
10
|
+
|
11
|
+
<div class="form-buttons filter-actions actions" data-hook="buttons">
|
12
|
+
<%= submit_tag t('spree.actions.update'), class: 'btn btn-primary' %>
|
13
|
+
<%= link_to t('spree.actions.cancel'), collection_url, class: 'button' %>
|
14
|
+
</div>
|
15
|
+
</fieldset>
|
16
|
+
<% end %>
|
@@ -0,0 +1,54 @@
|
|
1
|
+
<% admin_layout "full-width" %>
|
2
|
+
|
3
|
+
<% admin_breadcrumb plural_resource_name(model_class) %>
|
4
|
+
|
5
|
+
<% content_for :page_actions do %>
|
6
|
+
<li>
|
7
|
+
<%= link_to t('spree.admin.entry.new'), new_object_url, class: 'btn btn-primary' %>
|
8
|
+
</li>
|
9
|
+
<% end if can?(:create, model_class) %>
|
10
|
+
|
11
|
+
<%= paginate @collection, theme: "solidus_admin" %>
|
12
|
+
|
13
|
+
<% if @collection.any? %>
|
14
|
+
<table class="index" id="listing_entries">
|
15
|
+
<colgroup>
|
16
|
+
<col style="width: 40%;">
|
17
|
+
<col style="width: 40%;">
|
18
|
+
<col style="width: 20%;">
|
19
|
+
</colgroup>
|
20
|
+
<thead>
|
21
|
+
<tr data-hook="admin_products_index_headers">
|
22
|
+
<th><%= model_class.human_attribute_name(:slug) %></th>
|
23
|
+
<th><%= model_class.human_attribute_name(:entry_type) %></th>
|
24
|
+
<th></th>
|
25
|
+
</tr>
|
26
|
+
</thead>
|
27
|
+
<tbody>
|
28
|
+
<% @collection.each do |entry| %>
|
29
|
+
<tr id="<%= spree_dom_id entry %>" data-hook="admin_entries_index_rows">
|
30
|
+
<td>
|
31
|
+
<%= link_to entry.slug, object_url(entry) %>
|
32
|
+
</td>
|
33
|
+
<td>
|
34
|
+
<%= link_to entry.entry_type.name, admin_entry_type_path(entry.entry_type) %>
|
35
|
+
</td>
|
36
|
+
<td class="actions" data-hook="admin_entries_index_row_actions">
|
37
|
+
<%= link_to_edit entry, url: edit_object_url(entry),
|
38
|
+
class: 'edit edit-entry' if can?(:update, entry) %>
|
39
|
+
<%= link_to_delete entry, url: object_url(entry),
|
40
|
+
class: 'trash delete-entry' if can?(:destroy, entry) %>
|
41
|
+
</td>
|
42
|
+
</tr>
|
43
|
+
<% end %>
|
44
|
+
</tbody>
|
45
|
+
</table>
|
46
|
+
<% else %>
|
47
|
+
<div class="no-objects-found">
|
48
|
+
<%= render 'spree/admin/shared/no_objects_found',
|
49
|
+
resource: model_class,
|
50
|
+
new_resource_url: new_object_url %>
|
51
|
+
</div>
|
52
|
+
<% end %>
|
53
|
+
|
54
|
+
<%= paginate @collection, theme: "solidus_admin" %>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<% admin_breadcrumb link_to(plural_resource_name(model_class), collection_url) %>
|
2
|
+
<% admin_breadcrumb "#{t('spree.actions.new')} #{model_class.model_name.human}" %>
|
3
|
+
|
4
|
+
|
5
|
+
<%= render 'spree/shared/error_messages', target: @object %>
|
6
|
+
|
7
|
+
<%= form_for @object, url: collection_url do |form| %>
|
8
|
+
<fieldset data-hook="new_entry">
|
9
|
+
<legend align="center">
|
10
|
+
<%= admin_hint nil, t('solidus_content.hints.new_entry') %>
|
11
|
+
<%= t('new', scope: %w[spree admin entry]) %>
|
12
|
+
</legend>
|
13
|
+
|
14
|
+
<%= render 'form', form: form %>
|
15
|
+
|
16
|
+
<div class="form-buttons filter-actions actions" data-hook="buttons">
|
17
|
+
<%= submit_tag t('spree.actions.create'), class: 'btn btn-primary' %>
|
18
|
+
<%= link_to t('spree.actions.cancel'), collection_url, class: 'button' %>
|
19
|
+
</div>
|
20
|
+
</fieldset>
|
21
|
+
<% end %>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<% provider_options = SolidusContent.provider_names.map do |name|
|
2
|
+
[SolidusContent.human_provider_name(name), name]
|
3
|
+
end %>
|
4
|
+
|
5
|
+
<div data-hook="admin_entry_type_form_fields">
|
6
|
+
<div class="row">
|
7
|
+
<div class="left col-12" data-hook="admin_entry_type_form">
|
8
|
+
<div class="row">
|
9
|
+
<div class="col-6" data-hook="admin_entry_type_form_name">
|
10
|
+
<%= form.field_container :user do %>
|
11
|
+
<%= form.label :name, class: 'required' %><br />
|
12
|
+
<%= form.text_field :name, class: 'fullwidth' %>
|
13
|
+
<% end %>
|
14
|
+
</div>
|
15
|
+
|
16
|
+
<div class="col-6" data-hook="admin_entry_type_form_provider">
|
17
|
+
<%= form.field_container :provider_name do %>
|
18
|
+
<%= form.field_hint :provider_name %>
|
19
|
+
<%= form.label :provider_name, class: 'required' %><br />
|
20
|
+
<%= form.select :provider_name, provider_options, { include_blank: false }, { disabled: form.object.provider_name_readonly?, class: 'custom-select fullwidth' } %>
|
21
|
+
<% end %>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
|
27
|
+
<% if form.object.provider_name_readonly? && @object.entry_type_fields.count > 0 %>
|
28
|
+
<%= render "options_form", form: form %>
|
29
|
+
<% end %>
|
30
|
+
</div>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<fieldset class="options-form no-border-bottom">
|
2
|
+
<legend>
|
3
|
+
<%= SolidusContent.human_provider_name(@entry_type.provider_name) %>
|
4
|
+
<%= model_class.human_attribute_name(:options) %>
|
5
|
+
</legend>
|
6
|
+
<div class="row">
|
7
|
+
<% @entry_type.entry_type_fields.each do |field| %>
|
8
|
+
<div class="col-12" data-hook="admin_entry_type_<%= field %>">
|
9
|
+
<div class="field" id="solidus_content_entry_type_<%= field %>_field">
|
10
|
+
<%= form.label field %>
|
11
|
+
<%= form.text_field field, class: 'fullwidth' %>
|
12
|
+
</div>
|
13
|
+
</div>
|
14
|
+
<% end %>
|
15
|
+
</div>
|
16
|
+
</fieldset>
|