Skip to content

Commit

Permalink
Add ResourceLink as a page part (#1372)
Browse files Browse the repository at this point in the history
  • Loading branch information
simmerz authored May 24, 2024
1 parent f4c631a commit 22b0929
Show file tree
Hide file tree
Showing 14 changed files with 164 additions and 59 deletions.
39 changes: 2 additions & 37 deletions app/assets/javascripts/spina/controllers/page_select_controller.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,3 @@
import { Controller } from "@hotwired/stimulus"
import SelectController from 'controllers/select_controller'

export default class extends Controller {

static get targets() {
return ['input', 'label', 'search']
}

connect() {
// Show placeholder if there is no page selected yet
if (this.labelTarget.querySelector("turbo-frame") == undefined) {
this.clear()
}
}

select(event) {
let button = event.currentTarget

this.inputTarget.value = button.dataset.id
this.labelTarget.innerText = button.dataset.title
}

clear() {
this.inputTarget.value = ""
this.labelTarget.innerHTML = `
<span class="text-gray-400">
${this.element.dataset.placeholder}
</span>
`
}

autofocus() {
setTimeout(function() {
this.searchTarget.focus()
}.bind(this), 100)
}

}
export default class extends SelectController { }
38 changes: 38 additions & 0 deletions app/assets/javascripts/spina/controllers/select_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {

static get targets() {
return ['input', 'label', 'search']
}

connect() {
// Show placeholder if there is no page selected yet
if (this.labelTarget.querySelector("turbo-frame") == undefined) {
this.clear()
}
}

select(event) {
let button = event.currentTarget

this.inputTarget.value = button.dataset.id
this.labelTarget.innerText = button.dataset.title
}

clear() {
this.inputTarget.value = ""
this.labelTarget.innerHTML = `
<span class="text-gray-400">
${this.element.dataset.placeholder}
</span>
`
}

autofocus() {
setTimeout(function () {
this.searchTarget.focus()
}.bind(this), 100)
}

}
20 changes: 20 additions & 0 deletions app/controllers/spina/admin/resource_select_options_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module Spina
module Admin
class ResourceSelectOptionsController < AdminController

def show
@resource = Resource.find(params[:id])
end

def index
end

def search
@resources ||= Resource.all
@resources = @resources.where("name ILIKE :query OR label ILIKE :query", query: "%#{params[:search]}%").order(created_at: :desc).distinct.page(params[:page]).per(20)
render :index
end

end
end
end
13 changes: 13 additions & 0 deletions app/models/spina/parts/resource_link.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module Spina
module Parts
class ResourceLink < Base
attr_json :resource_id, :integer, default: nil

attr_accessor :options

def content
::Spina::Resource.find_by(id: resource_id)
end
end
end
end
8 changes: 4 additions & 4 deletions app/views/spina/admin/page_select_options/index.html.erb
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<%= turbo_frame_tag "page_select_options_#{params[:object_id]}" do %>
<% if params[:search].blank? %>
<button type="button" data-action="page-select#clear reveal#hide" class="block hover:bg-gray-100 w-full text-left px-5 py-2 font-medium leading-5 text-gray-700 hover:text-gray-900 text-sm border-t border-gray-150">
<button type="button" data-action="select#clear reveal#hide" class="block hover:bg-gray-100 w-full text-left px-5 py-2 font-medium leading-5 text-gray-700 hover:text-gray-900 text-sm border-t border-gray-150">
</button>
<% end %>
<% @pages.each do |page| %>
<button type="button" data-action="page-select#select reveal#hide" data-title="<%= page.title %>" data-id="<%= page.id %>" class="block hover:bg-gray-100 w-full text-left px-5 py-2 font-medium leading-5 text-gray-700 hover:text-gray-900 text-sm border-t border-gray-150">
<button type="button" data-action="select#select reveal#hide" data-title="<%= page.title %>" data-id="<%= page.id %>" class="block hover:bg-gray-100 w-full text-left px-5 py-2 font-medium leading-5 text-gray-700 hover:text-gray-900 text-sm border-t border-gray-150">
<%= page.title %>
<% if page.draft? %>
<span class="font-normal text-gray-400">
Expand All @@ -18,4 +18,4 @@
</div>
</button>
<% end %>
<% end %>
<% end %>
14 changes: 5 additions & 9 deletions app/views/spina/admin/parts/page_links/_form.html.erb
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
<div class="mt-6">
<label class="block text-sm leading-5 font-medium text-gray-700"><%= f.object.title %></label>
<div class="text-gray-400 text-sm"><%= f.object.hint %></div>

<div data-controller="page-select reveal" data-placeholder="<%=t "spina.pages.select_page" %>" class="relative mt-1" data-reveal-away-value>
<%= f.hidden_field :page_id, data: {page_select_target: "input"} %>

<button type="button" class="btn btn-default px-3 inline-flex items-center text-sm font-medium" data-action="reveal#toggle page-select#autofocus">
<div data-controller="select reveal" data-placeholder="<%=t "spina.pages.select_page" %>" class="relative mt-1" data-reveal-away-value>
<%= f.hidden_field :page_id, data: {select_target: "input"} %>
<button type="button" class="btn btn-default px-3 inline-flex items-center text-sm font-medium" data-action="reveal#toggle select#autofocus">
<%= heroicon("link", style: :mini, class: "w-4 h-4 mr-1 text-gray-600") %>
<div data-page-select-target="label">
<div data-select-target="label">
<% if f.object.page_id.present? %>
<%= turbo_frame_tag :page_title, src: spina.admin_page_select_option_path(f.object.page_id) %>
<% end %>
</div>
</button>

<div class="relative mt-1">
<div data-reveal data-transition hidden class="absolute shadow-lg border border-gray-200 origin-top-right rounded-md z-10 top-0">
<div class="rounded-md bg-white shadow-xs">
<%= form_with url: spina.search_admin_page_select_options_path, data: {turbo_frame: "page_select_options_#{f.object.object_id}", controller: "form", debounce_time: 100} do |ff| %>
<%= ff.hidden_field :object_id, value: f.object.object_id %>
<%= ff.hidden_field :resource, value: f.object.options&.dig(:resource) %>
<div class="p-2">
<%= ff.search_field :search, placeholder: t("spina.search"), class: "form-input sticky top-0 text-sm w-80", data: {action: "input->form#submit focus->form#submit", page_select_target: "search"} %>
<%= ff.search_field :search, placeholder: t("spina.search"), class: "form-input sticky top-0 text-sm w-80", data: {action: "input->form#submit focus->form#submit", select_target: "search"} %>
</div>
<% end %>

<div class="overflow-scroll max-h-80">
<%= turbo_frame_tag "page_select_options_#{f.object.object_id}" do %>
<% end %>
Expand Down
32 changes: 32 additions & 0 deletions app/views/spina/admin/parts/resource_links/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<div class="mt-6">
<label class="block text-sm leading-5 font-medium text-gray-700"><%= f.object.title %></label>
<div class="text-gray-400 text-sm"><%= f.object.hint %></div>
<div data-controller="select reveal" data-placeholder="<%=t "spina.resources.select_resource" %>" class="relative mt-1" data-reveal-away-value>
<%= f.hidden_field :resource_id, data: {select_target: "input"} %>
<button type="button" class="btn btn-default px-3 inline-flex items-center text-sm font-medium" data-action="reveal#toggle select#autofocus">
<%= heroicon("link", style: :mini, class: "w-4 h-4 mr-1 text-gray-600") %>
<div data-select-target="label">
<% if f.object.resource_id.present? %>
<%= turbo_frame_tag :resource_title, src: spina.admin_resource_select_option_path(f.object.resource_id) %>
<% end %>
</div>
</button>
<div class="relative mt-1">
<div data-reveal data-transition hidden class="absolute shadow-lg border border-gray-200 origin-top-right rounded-md z-10 top-0">
<div class="rounded-md bg-white shadow-xs">
<%= form_with url: spina.search_admin_resource_select_options_path, data: {turbo_frame: "resource_select_options_#{f.object.object_id}", controller: "form", debounce_time: 100} do |ff| %>
<%= ff.hidden_field :object_id, value: f.object.object_id %>
<%= ff.hidden_field :resource, value: f.object.options&.dig(:resource) %>
<div class="p-2">
<%= ff.search_field :search, placeholder: t("spina.search"), class: "form-input sticky top-0 text-sm w-80", data: {action: "input->form#submit focus->form#submit", select_target: "search"} %>
</div>
<% end %>
<div class="overflow-scroll max-h-80">
<%= turbo_frame_tag "resource_select_options_#{f.object.object_id}" do %>
<% end %>
</div>
</div>
</div>
</div>
</div>
</div>
13 changes: 13 additions & 0 deletions app/views/spina/admin/resource_select_options/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<%= turbo_frame_tag "resource_select_options_#{params[:object_id]}" do %>
<% if params[:search].blank? %>
<button type="button" data-action="select#clear reveal#hide" class="block hover:bg-gray-100 w-full text-left px-5 py-2 font-medium leading-5 text-gray-700 hover:text-gray-900 text-sm border-t border-gray-150">
</button>
<% end %>
<% @resources.each do |resource| %>
<button type="button" data-action="select#select reveal#hide" data-title="<%= resource.label %>" data-id="<%= resource.id %>" class="block hover:bg-gray-100 w-full text-left px-5 py-2 font-medium leading-5 text-gray-700 hover:text-gray-900 text-sm border-t border-gray-150">
<%= resource.label %>
</button>
<% end %>
<% end %>
3 changes: 3 additions & 0 deletions app/views/spina/admin/resource_select_options/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<%= turbo_frame_tag :resource_title do %>
<%= @resource.label %>
<% end %>
11 changes: 6 additions & 5 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ en:
options:
choose_option: Choose option
pages:
add_page_to: 'Add page to:'
add_page_to: "Add page to:"
add_translation: Add %{language} translation
advanced: Advanced
cannot_be_deleted: Page can't be deleted
Expand Down Expand Up @@ -270,7 +270,7 @@ en:
page_content: Content
page_part: Page section
page_seo: Search engines
path: 'Path:'
path: "Path:"
photo_picker: Choose image
photos_picker: Choose images
preview: Preview
Expand All @@ -295,15 +295,15 @@ en:
deleted: Translation deleted
permanently_delete: Permanently delete
photos:
cannot_be_created: 'Image could not be processed:'
cannot_be_created: "Image could not be processed:"
choose_images: Choose images
delete: Delete
delete_confirmation: Are you sure you want to delete this <strong>image</strong>?
delete_folder: Delete folder
done_organizing: Done organizing
insert_photo: Insert image
insert_photos: Choose images
link: 'URL of your image:'
link: "URL of your image:"
new_folder: New folder
organize: Organize images
rename_folder: Rename folder
Expand Down Expand Up @@ -335,6 +335,7 @@ en:
manual_sorting: Manual sorting
no_default_template: No default template
saved: Page collection saved
select_resource: Select resource
settings: "%{label} settings"
settings_description: All pages inside this collection will be prepended with this slug.
save: Save
Expand Down Expand Up @@ -379,7 +380,7 @@ en:
delete: Delete user
delete_confirmation_html: Are you sure you want to delete the user <strong>%{user}</strong>?
deleted: User deleted
last_login: 'Last login:'
last_login: "Last login:"
never_logged_in: Never logged in
new: New user
profile: Profile
Expand Down
5 changes: 4 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
get :children
post :sort_one
end

collection do
post :sort
end
Expand All @@ -58,6 +58,9 @@
resources :page_select_options, only: [:show, :index] do
post :search, on: :collection
end
resources :resource_select_options, only: [:show, :index] do
post :search, on: :collection
end
resources :page_translations, only: [:destroy]
resources :parent_pages
resource :layout, controller: :layout, only: [:edit, :update]
Expand Down
16 changes: 16 additions & 0 deletions docs/v2/rendering_content/10_resource_link.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# ResourceLink

An ResourceLink is a part where you can link to or reference a resource. This is useful for displaying a list of pages contained within a resource.

## Theme configuration

```
config.parts = [
# ...
{
name: "content_group",
title: "Content Group",
part_type: "Spina::Parts::ResourceLink"
}
]
```
3 changes: 2 additions & 1 deletion lib/spina/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ class Engine < ::Rails::Engine
Spina::Parts::Repeater,
Spina::Parts::Option,
Spina::Parts::Attachment,
Spina::Parts::PageLink
Spina::Parts::PageLink,
Spina::Parts::ResourceLink
)
end
end
Expand Down
8 changes: 6 additions & 2 deletions test/dummy/config/initializers/themes/demo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@
options: {
resource: "blog"
}
}, {
name: "page_group",
title: "Pagegroup",
part_type: "Spina::Parts::ResourceLink",
}]

theme.view_templates = [{
Expand All @@ -80,12 +84,12 @@
title: "Simple page",
description: "Default layout",
usage: "Use for your content",
parts: ["body", "blogpost", "page", "testrepeater"]
parts: ["body", "blogpost", "page", "testrepeater", "page_group"]
}, {
name: "demo",
title: "Demo",
description: "Example including all parts",
parts: ["repeater", "repeater2", "attachment", "option", "body", "image_collection", "image", "portrait", "landscape", "wide"],
parts: ["repeater", "repeater2", "attachment", "option", "body", "image_collection", "image", "portrait", "landscape", "wide", "page_group"],
exclude_from: %w[guides]
}, {
name: "blogpost",
Expand Down

0 comments on commit 22b0929

Please sign in to comment.