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: 0 additions & 2 deletions app/javascript/alchemy_admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { LinkDialog } from "alchemy_admin/link_dialog"
import pleaseWaitOverlay from "alchemy_admin/please_wait_overlay"
import Sitemap from "alchemy_admin/sitemap"
import Spinner from "alchemy_admin/spinner"
import PagePublicationFields from "alchemy_admin/page_publication_fields"
import { reloadPreview } from "alchemy_admin/components/preview_window"
import { openConfirmDialog } from "alchemy_admin/confirm_dialog"

Expand Down Expand Up @@ -47,7 +46,6 @@ Object.assign(Alchemy, {
pleaseWaitOverlay,
Sitemap,
Spinner,
PagePublicationFields,
reloadPreview
})

Expand Down
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 @@ -23,6 +23,7 @@ import "alchemy_admin/components/link_buttons"
import "alchemy_admin/components/node_select"
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_thumbnail"
import "alchemy_admin/components/preview_window"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
// Handles the page publication date fields
export default function () {
document.addEventListener("DialogReady.Alchemy", function (evt) {
const dialog = evt.detail.body
const public_on_field = dialog.querySelector("#page_public_on")
const public_until_field = dialog.querySelector("#page_public_until")
const publication_date_fields = dialog.querySelector(
export class PagePublicationFields extends HTMLElement {
connectedCallback() {
const public_on_field = this.querySelector("#page_public_on")
const public_until_field = this.querySelector("#page_public_until")
const publication_date_fields = this.querySelector(
".page-publication-date-fields"
)
const public_field = dialog.querySelector("#page_public")
const public_field = this.querySelector("#page_public")

if (!public_field) return

Expand All @@ -24,5 +23,7 @@ export default function () {
}
public_until_field.value = ""
})
})
}
}

customElements.define("alchemy-page-publication-fields", PagePublicationFields)
54 changes: 28 additions & 26 deletions app/views/alchemy/admin/pages/_publication_fields.html.erb
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
<% checkbox = check_box_tag :page_public, nil, @page.public?, name: nil, disabled: @page.attribute_fixed?(:public_on) %>
<alchemy-page-publication-fields>
<% checkbox = check_box_tag :page_public, nil, @page.public?, name: nil, disabled: @page.attribute_fixed?(:public_on) %>

<label class="checkbox">
<% if @page.attribute_fixed?(:public_on) || @page.attribute_fixed?(:public_until) %>
<sl-tooltip class="like-hint-tooltip" content="<%= Alchemy.t(:attribute_fixed) %>" placement="bottom-start">
<label class="checkbox">
<% if @page.attribute_fixed?(:public_on) || @page.attribute_fixed?(:public_until) %>
<sl-tooltip class="like-hint-tooltip" content="<%= Alchemy.t(:attribute_fixed) %>" placement="bottom-start">
<%= checkbox %>
<%= Alchemy::Page.human_attribute_name :public %>
</sl-tooltip>
<% else %>
<%= checkbox %>
<%= Alchemy::Page.human_attribute_name :public %>
</sl-tooltip>
<% else %>
<%= checkbox %>
<%= Alchemy::Page.human_attribute_name :public %>
<% end %>
</label>
<% end %>
</label>

<%= content_tag :div, class: [
@page.public_on.present? || @page.public_until.present? ? nil : 'hidden',
'page-publication-date-fields',
'input-row'
] do %>
<div class="input-column">
<label><%= Alchemy.t(:from) %></label>
<%= alchemy_datepicker @page, :public_on, type: :datetime,
disabled: @page.attribute_fixed?(:public_on) %>
</div>
<div class="input-column">
<label><%= Alchemy.t(:until) %></label>
<%= alchemy_datepicker @page, :public_until, type: :datetime,
disabled: @page.attribute_fixed?(:public_until) %>
</div>
<% end %>
<%= content_tag :div, class: [
@page.public_on.present? || @page.public_until.present? ? nil : 'hidden',
'page-publication-date-fields',
'input-row'
] do %>
<div class="input-column">
<label><%= Alchemy.t(:from) %></label>
<%= alchemy_datepicker @page, :public_on, type: :datetime,
disabled: @page.attribute_fixed?(:public_on) %>
</div>
<div class="input-column">
<label><%= Alchemy.t(:until) %></label>
<%= alchemy_datepicker @page, :public_until, type: :datetime,
disabled: @page.attribute_fixed?(:public_until) %>
</div>
<% end %>
</alchemy-page-publication-fields>
7 changes: 0 additions & 7 deletions app/views/alchemy/admin/pages/_table.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,3 @@
<% end %>
<% table.delete_button tooltip: Alchemy.t(:delete_page), confirm_message: Alchemy.t(:confirm_to_delete_page) %>
<% end %>


<script type="module">
$(function() {
Alchemy.PagePublicationFields();
});
</script>
1 change: 0 additions & 1 deletion app/views/alchemy/admin/pages/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@
if (!not_dirty) Alchemy.pleaseWaitOverlay(false);
return not_dirty;
});
Alchemy.PagePublicationFields();
Alchemy.PageLeaveObserver();
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { vi } from "vitest"
import "alchemy_admin/components/page_publication_fields"
import { renderComponent } from "./component.helper"

describe("alchemy-page-publication-fields", () => {
/**
* @type {HTMLElement | undefined}
*/
let component = undefined
let publicCheckbox = undefined
let publicOnField = undefined
let publicUntilField = undefined
let publicationDateFields = undefined

beforeEach(() => {
const html = `
<alchemy-page-publication-fields>
<input type="checkbox" id="page_public">
<div class="page-publication-date-fields hidden">
<input type="text" id="page_public_on">
<input type="text" id="page_public_until">
</div>
</alchemy-page-publication-fields>
`
component = renderComponent("alchemy-page-publication-fields", html)
publicCheckbox = component.querySelector("#page_public")
publicOnField = component.querySelector("#page_public_on")
publicUntilField = component.querySelector("#page_public_until")
publicationDateFields = component.querySelector(
".page-publication-date-fields"
)

// Mock flatpickr instance on the public_on field
publicOnField._flatpickr = {
setDate: vi.fn()
}
})

describe("when public checkbox is checked", () => {
beforeEach(() => {
publicCheckbox.checked = true
publicCheckbox.dispatchEvent(new Event("click", { bubbles: true }))
})

it("shows the publication date fields", () => {
expect(publicationDateFields.classList.contains("hidden")).toBeFalsy()
})

it("sets the public_on date to now", () => {
expect(publicOnField._flatpickr.setDate).toHaveBeenCalled()
const calledWith = publicOnField._flatpickr.setDate.mock.calls[0][0]
expect(calledWith).toBeInstanceOf(Date)
})

it("clears the public_until field", () => {
publicUntilField.value = "2025-12-31"
publicCheckbox.dispatchEvent(new Event("click", { bubbles: true }))
expect(publicUntilField.value).toEqual("")
})
})

describe("when public checkbox is unchecked", () => {
beforeEach(() => {
publicCheckbox.checked = false
publicationDateFields.classList.remove("hidden")
publicOnField.value = "2025-01-01"
publicUntilField.value = "2025-12-31"
publicCheckbox.dispatchEvent(new Event("click", { bubbles: true }))
})

it("hides the publication date fields", () => {
expect(publicationDateFields.classList.contains("hidden")).toBeTruthy()
})

it("clears the public_on field value", () => {
expect(publicOnField.value).toEqual("")
})

it("clears the public_until field value", () => {
expect(publicUntilField.value).toEqual("")
})

it("does not call flatpickr setDate", () => {
expect(publicOnField._flatpickr.setDate).not.toHaveBeenCalled()
})
})

describe("when public checkbox is missing", () => {
it("does not throw an error", () => {
const html = `
<alchemy-page-publication-fields>
<div class="page-publication-date-fields hidden">
<input type="text" id="page_public_on">
<input type="text" id="page_public_until">
</div>
</alchemy-page-publication-fields>
`
expect(() => {
renderComponent("alchemy-page-publication-fields", html)
}).not.toThrow()
})
})

describe("toggling multiple times", () => {
it("handles repeated toggling correctly", () => {
// First check
publicCheckbox.checked = true
publicCheckbox.dispatchEvent(new Event("click", { bubbles: true }))
expect(publicationDateFields.classList.contains("hidden")).toBeFalsy()
expect(publicOnField._flatpickr.setDate).toHaveBeenCalledTimes(1)

// Uncheck
publicCheckbox.checked = false
publicCheckbox.dispatchEvent(new Event("click", { bubbles: true }))
expect(publicationDateFields.classList.contains("hidden")).toBeTruthy()
expect(publicOnField.value).toEqual("")

// Check again
publicCheckbox.checked = true
publicCheckbox.dispatchEvent(new Event("click", { bubbles: true }))
expect(publicationDateFields.classList.contains("hidden")).toBeFalsy()
expect(publicOnField._flatpickr.setDate).toHaveBeenCalledTimes(2)
})
})
})
Loading