Skip to content

Commit a715b27

Browse files
authored
Merge pull request #3530 from AlchemyCMS/picture-description-select
fix(PictureDescriptionSelect): Add site name to identify language
2 parents 89ae8ab + 9547ddd commit a715b27

File tree

10 files changed

+199
-36
lines changed

10 files changed

+199
-36
lines changed

app/assets/builds/alchemy/admin.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
module Alchemy
2+
module Admin
3+
class PictureDescriptionSelect < ViewComponent::Base
4+
erb_template <<-ERB
5+
<alchemy-picture-description-select url="<%= url %>">
6+
<label class="inline-label">
7+
<%= label %>
8+
<%= select name_prefix, :language_id,
9+
options_for_select(language_options, selected:) %>
10+
</label>
11+
</alchemy-picture-description-select>
12+
ERB
13+
14+
def initialize(url:, selected:, name_prefix:)
15+
@url = url
16+
@selected = selected
17+
@name_prefix = name_prefix
18+
end
19+
20+
def render?
21+
Alchemy::Language.published.many?
22+
end
23+
24+
private
25+
26+
delegate :multi_site?, to: :helpers
27+
28+
attr_reader :name_prefix, :selected, :url
29+
30+
def label
31+
Alchemy::Language.model_name.human
32+
end
33+
34+
def language_options
35+
Alchemy::Language.published.map do |language|
36+
[language_label(language), language.id]
37+
end
38+
end
39+
40+
def language_label(language)
41+
language_name = language.name
42+
multi_site? ? "#{language_name} (#{language.site.name})" : language_name
43+
end
44+
end
45+
end
46+
end

app/javascript/alchemy_admin/components/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import "alchemy_admin/components/uploader"
2525
import "alchemy_admin/components/overlay"
2626
import "alchemy_admin/components/page_publication_fields"
2727
import "alchemy_admin/components/page_select"
28+
import "alchemy_admin/components/picture_description_select"
2829
import "alchemy_admin/components/picture_thumbnail"
2930
import "alchemy_admin/components/preview_window"
3031
import "alchemy_admin/components/select"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class PictureDescriptionSelect extends HTMLElement {
2+
constructor() {
3+
super()
4+
this.addEventListener("change", this)
5+
}
6+
7+
handleEvent(event) {
8+
switch (event.type) {
9+
case "change":
10+
this.onChange()
11+
break
12+
}
13+
}
14+
15+
onChange() {
16+
const url = new URL(this.getAttribute("url"))
17+
const select = this.querySelector("select")
18+
url.searchParams.set("language_id", select.value)
19+
Turbo.visit(url, { frame: "picture_descriptions" })
20+
}
21+
}
22+
23+
customElements.define(
24+
"alchemy-picture-description-select",
25+
PictureDescriptionSelect
26+
)

app/stylesheets/alchemy/admin/archive.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,3 +349,15 @@ div#library_sidebar {
349349
#all_files td.name a {
350350
@include mixins.zoom-in;
351351
}
352+
353+
.picture-form {
354+
.inline-label {
355+
float: right;
356+
justify-content: end;
357+
width: 200px;
358+
359+
select {
360+
max-width: 160px;
361+
}
362+
}
363+
}

app/stylesheets/alchemy/admin/forms.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ form {
2525
.inline-label {
2626
display: inline-flex;
2727
align-items: center;
28-
gap: var(--spacing-1);
28+
gap: var(--spacing-2);
2929
}
3030

3131
.input {
Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,16 @@
11
<div class="input">
2-
<% if Alchemy::Language.published.many? %>
3-
<label class="inline-label" style="float: right">
4-
<%= Alchemy::Language.model_name.human %>
5-
<%= select description_field_name_prefix, :language_id, options_from_collection_for_select(
6-
Alchemy::Language.published, :id, ->(l) { l.code.upcase },
7-
selected: @picture_description.language_id,
8-
),
9-
{},
10-
id: "picture_description_select",
11-
data: {
12-
url: alchemy.edit_admin_picture_description_url(
13-
id: @picture_description.id || "__ID__",
14-
picture_id: @picture
15-
)
16-
} %>
17-
</label>
18-
<% end %>
2+
<%= render Alchemy::Admin::PictureDescriptionSelect.new(
3+
url: alchemy.edit_admin_picture_description_url(
4+
id: @picture_description.id || "__ID__",
5+
picture_id: @picture
6+
),
7+
selected: @picture_description.language_id,
8+
name_prefix: description_field_name_prefix
9+
) %>
1910

2011
<turbo-frame id="picture_descriptions">
2112
<%= render "alchemy/admin/picture_descriptions/form",
2213
description_field_name_prefix: description_field_name_prefix,
2314
picture_description: @picture_description %>
2415
</turbo-frame>
2516
</div>
26-
27-
<script>
28-
(function ($) {
29-
const select = $.getElementById("picture_description_select")
30-
31-
if (select) {
32-
select.addEventListener("change", () => {
33-
const url = new URL(select.dataset.url)
34-
url.searchParams.set("language_id", select.value)
35-
Turbo.visit(url, { frame: "picture_descriptions" })
36-
})
37-
}
38-
})(document)
39-
</script>
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
require "rails_helper"
2+
3+
RSpec.describe Alchemy::Admin::PictureDescriptionSelect, type: :component do
4+
let(:component) do
5+
described_class.new(
6+
url: "/some/url",
7+
selected: selected,
8+
name_prefix: "some_prefix"
9+
)
10+
end
11+
12+
subject(:render) do
13+
render_inline(component)
14+
end
15+
16+
context "when there are multiple languages" do
17+
let(:selected) { language.id }
18+
19+
context "when there is only one site" do
20+
let!(:language) { create(:alchemy_language, :english, site: site) }
21+
let!(:german) { create(:alchemy_language, :german, site: site) }
22+
let(:site) { create(:alchemy_site) }
23+
24+
before do
25+
allow_any_instance_of(described_class).to receive(:multi_site?).and_return(false)
26+
render
27+
end
28+
29+
it "renders the select box with both languages" do
30+
expect(page).to have_select("Language", options: ["English", "Deutsch"], selected: "English")
31+
expect(page).to have_selector("alchemy-picture-description-select[url='/some/url']")
32+
end
33+
end
34+
35+
context "when there are multiple sites" do
36+
let!(:language) { create(:alchemy_language, :english, site: site1) }
37+
let!(:german) { create(:alchemy_language, :german, site: site2) }
38+
let(:site1) { create(:alchemy_site, host: "demo.example.com", name: "Demo") }
39+
let(:site2) { create(:alchemy_site, host: "www.example.com", name: "Default") }
40+
41+
before do
42+
allow_any_instance_of(described_class).to receive(:multi_site?).and_return(true)
43+
render
44+
end
45+
46+
it "renders select with site names" do
47+
expect(page).to have_select("Language", options: ["English (Demo)", "Deutsch (Default)"], selected: "English (Demo)")
48+
expect(page).to have_selector("alchemy-picture-description-select[url='/some/url']")
49+
end
50+
end
51+
end
52+
53+
context "when there is only one published language" do
54+
let(:selected) { language.id }
55+
let!(:language) { create(:alchemy_language, :english) }
56+
57+
before do
58+
allow_any_instance_of(described_class).to receive(:multi_site?).and_return(false)
59+
render
60+
end
61+
62+
it "does not render the component" do
63+
expect(rendered_content).to be_empty
64+
end
65+
end
66+
end

spec/features/admin/picture_library_integration_spec.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,16 +231,16 @@
231231
expect(page).to have_content("Picture updated successfully")
232232
end
233233

234-
select(german.language_code.upcase, from: "Language")
234+
select(german.name, from: "Language")
235235
fill_in "Description", with: "Tolles Bild."
236236
click_button "Save"
237237
within "#flash_notices" do
238238
expect(page).to have_content("Picture updated successfully")
239239
end
240240

241-
select(language.language_code.upcase, from: "Language")
241+
select(language.name, from: "Language")
242242
expect(page).to have_field("Description", with: "This is an amazing image.")
243-
select(german.language_code.upcase, from: "Language")
243+
select(german.name, from: "Language")
244244
expect(page).to have_field("Description", with: "Tolles Bild.")
245245
end
246246
end
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { vi } from "vitest"
2+
import { renderComponent } from "./component.helper"
3+
import "alchemy_admin/components/picture_description_select"
4+
5+
describe("alchemy-picture-description-select", () => {
6+
/**
7+
*
8+
* @type {HTMLElement | undefined}
9+
*/
10+
let component = undefined
11+
12+
beforeEach(() => {
13+
const html = `
14+
<alchemy-picture-description-select url="http://example.com/some/url">
15+
<select>
16+
<option value="1"></option>
17+
<option value="2" selected></option>
18+
</select>
19+
</alchemy-picture-description-select>
20+
`
21+
component = renderComponent("alchemy-picture-description-select", html)
22+
global.Turbo = { visit: vi.fn() }
23+
})
24+
25+
it("should use Turbo to reload the picture_descriptions frame", () => {
26+
const select = component.querySelector("select")
27+
const event = new Event("change", { bubbles: true })
28+
select.dispatchEvent(event)
29+
30+
expect(Turbo.visit).toHaveBeenCalledWith(
31+
new URL("http://example.com/some/url?language_id=2"),
32+
{ frame: "picture_descriptions" }
33+
)
34+
})
35+
})

0 commit comments

Comments
 (0)