Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/assets/builds/alchemy/admin.css

Large diffs are not rendered by default.

46 changes: 46 additions & 0 deletions app/components/alchemy/admin/picture_description_select.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module Alchemy
module Admin
class PictureDescriptionSelect < ViewComponent::Base
erb_template <<-ERB
<alchemy-picture-description-select url="<%= url %>">
<label class="inline-label">
<%= label %>
<%= select name_prefix, :language_id,
options_for_select(language_options, selected:) %>
</label>
</alchemy-picture-description-select>
ERB

def initialize(url:, selected:, name_prefix:)
@url = url
@selected = selected
@name_prefix = name_prefix
end

def render?
Alchemy::Language.published.many?
end

private

delegate :multi_site?, to: :helpers

attr_reader :name_prefix, :selected, :url

def label
Alchemy::Language.model_name.human
end

def language_options
Alchemy::Language.published.map do |language|
[language_label(language), language.id]
end
end

def language_label(language)
language_name = language.name
multi_site? ? "#{language_name} (#{language.site.name})" : language_name
end
end
end
end
1 change: 1 addition & 0 deletions app/javascript/alchemy_admin/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import "alchemy_admin/components/uploader"
import "alchemy_admin/components/overlay"
import "alchemy_admin/components/page_publication_fields"
import "alchemy_admin/components/page_select"
import "alchemy_admin/components/picture_description_select"
import "alchemy_admin/components/picture_thumbnail"
import "alchemy_admin/components/preview_window"
import "alchemy_admin/components/select"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class PictureDescriptionSelect extends HTMLElement {
constructor() {
super()
this.addEventListener("change", this)
}

handleEvent(event) {
switch (event.type) {
case "change":
this.onChange()
break
}
}

onChange() {
const url = new URL(this.getAttribute("url"))
const select = this.querySelector("select")
url.searchParams.set("language_id", select.value)
Turbo.visit(url, { frame: "picture_descriptions" })
}
}

customElements.define(
"alchemy-picture-description-select",
PictureDescriptionSelect
)
12 changes: 12 additions & 0 deletions app/stylesheets/alchemy/admin/archive.scss
Original file line number Diff line number Diff line change
Expand Up @@ -349,3 +349,15 @@ div#library_sidebar {
#all_files td.name a {
@include mixins.zoom-in;
}

.picture-form {
.inline-label {
float: right;
justify-content: end;
width: 200px;

select {
max-width: 160px;
}
}
}
2 changes: 1 addition & 1 deletion app/stylesheets/alchemy/admin/forms.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ form {
.inline-label {
display: inline-flex;
align-items: center;
gap: var(--spacing-1);
gap: var(--spacing-2);
}

.input {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,16 @@
<div class="input">
<% if Alchemy::Language.published.many? %>
<label class="inline-label" style="float: right">
<%= Alchemy::Language.model_name.human %>
<%= select description_field_name_prefix, :language_id, options_from_collection_for_select(
Alchemy::Language.published, :id, ->(l) { l.code.upcase },
selected: @picture_description.language_id,
),
{},
id: "picture_description_select",
data: {
url: alchemy.edit_admin_picture_description_url(
id: @picture_description.id || "__ID__",
picture_id: @picture
)
} %>
</label>
<% end %>
<%= render Alchemy::Admin::PictureDescriptionSelect.new(
url: alchemy.edit_admin_picture_description_url(
id: @picture_description.id || "__ID__",
picture_id: @picture
),
selected: @picture_description.language_id,
name_prefix: description_field_name_prefix
) %>

<turbo-frame id="picture_descriptions">
<%= render "alchemy/admin/picture_descriptions/form",
description_field_name_prefix: description_field_name_prefix,
picture_description: @picture_description %>
</turbo-frame>
</div>

<script>
(function ($) {
const select = $.getElementById("picture_description_select")

if (select) {
select.addEventListener("change", () => {
const url = new URL(select.dataset.url)
url.searchParams.set("language_id", select.value)
Turbo.visit(url, { frame: "picture_descriptions" })
})
}
})(document)
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
require "rails_helper"

RSpec.describe Alchemy::Admin::PictureDescriptionSelect, type: :component do
let(:component) do
described_class.new(
url: "/some/url",
selected: selected,
name_prefix: "some_prefix"
)
end

subject(:render) do
render_inline(component)
end

context "when there are multiple languages" do
let(:selected) { language.id }

context "when there is only one site" do
let!(:language) { create(:alchemy_language, :english, site: site) }
let!(:german) { create(:alchemy_language, :german, site: site) }
let(:site) { create(:alchemy_site) }

before do
allow_any_instance_of(described_class).to receive(:multi_site?).and_return(false)
render
end

it "renders the select box with both languages" do
expect(page).to have_select("Language", options: ["English", "Deutsch"], selected: "English")
expect(page).to have_selector("alchemy-picture-description-select[url='/some/url']")
end
end

context "when there are multiple sites" do
let!(:language) { create(:alchemy_language, :english, site: site1) }
let!(:german) { create(:alchemy_language, :german, site: site2) }
let(:site1) { create(:alchemy_site, host: "demo.example.com", name: "Demo") }
let(:site2) { create(:alchemy_site, host: "www.example.com", name: "Default") }

before do
allow_any_instance_of(described_class).to receive(:multi_site?).and_return(true)
render
end

it "renders select with site names" do
expect(page).to have_select("Language", options: ["English (Demo)", "Deutsch (Default)"], selected: "English (Demo)")
expect(page).to have_selector("alchemy-picture-description-select[url='/some/url']")
end
end
end

context "when there is only one published language" do
let(:selected) { language.id }
let!(:language) { create(:alchemy_language, :english) }

before do
allow_any_instance_of(described_class).to receive(:multi_site?).and_return(false)
render
end

it "does not render the component" do
expect(rendered_content).to be_empty
end
end
end
6 changes: 3 additions & 3 deletions spec/features/admin/picture_library_integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -231,16 +231,16 @@
expect(page).to have_content("Picture updated successfully")
end

select(german.language_code.upcase, from: "Language")
select(german.name, from: "Language")
fill_in "Description", with: "Tolles Bild."
click_button "Save"
within "#flash_notices" do
expect(page).to have_content("Picture updated successfully")
end

select(language.language_code.upcase, from: "Language")
select(language.name, from: "Language")
expect(page).to have_field("Description", with: "This is an amazing image.")
select(german.language_code.upcase, from: "Language")
select(german.name, from: "Language")
expect(page).to have_field("Description", with: "Tolles Bild.")
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { vi } from "vitest"
import { renderComponent } from "./component.helper"
import "alchemy_admin/components/picture_description_select"

describe("alchemy-picture-description-select", () => {
/**
*
* @type {HTMLElement | undefined}
*/
let component = undefined

beforeEach(() => {
const html = `
<alchemy-picture-description-select url="http://example.com/some/url">
<select>
<option value="1"></option>
<option value="2" selected></option>
</select>
</alchemy-picture-description-select>
`
component = renderComponent("alchemy-picture-description-select", html)
global.Turbo = { visit: vi.fn() }
})

it("should use Turbo to reload the picture_descriptions frame", () => {
const select = component.querySelector("select")
const event = new Event("change", { bubbles: true })
select.dispatchEvent(event)

expect(Turbo.visit).toHaveBeenCalledWith(
new URL("http://example.com/some/url?language_id=2"),
{ frame: "picture_descriptions" }
)
})
})
Loading