| Age | Commit message (Collapse) | Author |
|
The editable sidebar has had a star toggle since headline
designation shipped; the read-only view never gained any equivalent
indicator. Same visual language -- gold filled star, same
.is_headline card highlight already defined in admin.css.
|
|
GLightbox's own selector-based description feature never actually
resolved a selector in three different attempts -- literal text,
then a resolved-but-empty div, then apparently not firing at all
against the installed (unversioned) build. Replaced with a small
afterSlideLoad handler that reads a plain data-credit-selector
attribute and copies the real element's HTML into the slide's
description area directly, depending only on GLightbox handing back
a real DOM node per slide -- a much smaller contract than trusting
its own caption-resolution feature.
Renamed the credit div's class from glightbox-desc, since that name
is reserved by the library's own bundled CSS (display: none
!important) and can't be reliably overridden from here.
Also: distinguishes the credit line and the "N Bilder" caption from
ordinary body text (italic, muted, matching .author_and_date's
existing convention), and makes the lightbox's caption card follow
the site's light/dark toggle via Canvas/CanvasText, since the
library's bundled theme never adapts to it on its own.
|
|
self.assets = page.assets implicitly cleared the collection before
recreating it. Replacing it with an explicit loop, to preserve the
headline flag across clones, dropped that clearing -- every
clone_attributes_from call since has been appending related_assets
rather than replacing them. Restored with an explicit delete_all
before the copy.
update_assets (the sort_images reorder action) had the same gap for
headline specifically; it now carries the previous headline forward
when that asset is still present in the new list.
|
|
|
|
|
|
|
|
- related_assets gains a `headline` boolean (DB-enforced: at most one
per page), replacing "first image by position" as the headline
rule. A rake task backfills the current first image on every live
head/draft, so nothing changes visually until an editor changes it.
- The image picker sidebar gets a star toggle reflecting the flag;
the TinyMCE inline-image picker's badge now reads it too, instead
of assuming position 0.
- No headline chosen (or none attached) now falls back to the
gallery-count caption itself becoming the lightbox trigger, instead
of the gallery being unreachable.
- Assets gain creator, source_url, and license_key (against a new
config/asset_licenses.yml dictionary). asset_credit renders a
degrading attribution line, reused as a hidden per-image glightbox
caption so credit is one click away for every image, not only the
headline's always-visible one.
- Fixed: asset thumbnails rendered unconditionally regardless of
whether a real variant exists on disk. Asset#has_variant? checks
file existence, not content type -- some legacy PDFs have real
pre-rewrite thumbnails a content-type check would have hidden.
- assets#new/edit rebuilt onto the same node_description/node_content
layout as assets#show, picking up the three new fields in the
process.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- dark-mode restore now travels nonced, the admin constants likewise
- AUTH_TOKEN deleted in favour of the csrf meta tag
- new report collector at /csp_reports
|
|
A muted glyph before each sentence makes both log surfaces
scannable by verb: create, publish, move, trash, restore,
destroy, and the discard pair. Rollback publishes get their own
icon (history) distinct from ordinary promotion. Unknown verbs
fall back to a dashed circle.
|
|
Each row in nodes#show's History section now carries terse badges
from the action log: created, published, and restored (rollback
re-promotion), with date and actor, rendered from entry metadata
alone. Backfilled entries wear the inferred marker, so
reconstructed provenance stays distinguishable from witnessed
history. A revision that was published and later restored shows
both badges chronologically -- its true biography.
Only create and publish entries carry page_id; trash, restore, and
destroy annotate the node's own log zoom instead of any single
revision, by design.
|
|
|
|
|
|
Sentences for trash (with the pre-trash path), restore_from_trash
(with the destination), and destroy (with the final path, read
from its flat create-symmetric key).
|
|
nodes#show gains a Trash section on trashed nodes: provenance from
the trash entry, a restore form whose parent picker pre-fills the
old parent while it still lives, and permanent deletion. A
Move-to-Trash button joins the status actions on living nodes.
nodes#trashed lists trashed subtree roots with weight, provenance,
and deletion; the dashboard housekeeping row links to it, and
trash/destroy redirect there.
Deletion from Trash now removes the whole subtree, deepest first,
each node through a real destroy! so every per-node cascade runs --
amending the never-recursive rule for this one sanctioned path
(both confirms state the count; the root entry carries
destroyed_descendants). Bare Node#destroy still refuses children.
|
|
|
|
Also update the node action contract to include the trash related verbs.
|
|
|
|
related_assets rows outlived their pages; head and draft carried a
dependent destroy that double-destroyed rows has_many :pages
already owns. Autosave keeps its own -- autosave pages carry no
node_id, so pages does not reach them.
|
|
NestedTree's before_destroy silently delete_all'd the whole
subtree, bypassing every per-node cleanup. Nodes are never
destroyed recursively; descendants must be removed individually.
|
|
|
|
Page.aggregate interpolated order_by into SQL unchecked while
already allowlisting order_direction; the column is now normalized
and checked against the sortable columns, falling back to pages.id.
Its values arrive from editor-authored aggregate shortcodes, so
this was editor-gated, but the asymmetry was wrong regardless.
template_name and default_template_name now validate inclusion in
Page.custom_templates -- names render as filesystem paths, so only
names actually present in the template directory are acceptable.
Validated only on change: legacy rows whose template file has since
vanished stay saveable, and valid_template's render-time fallback
to standard_template continues to cover them. Two tests that wrote
fabricated template names through the front door now arrange their
state correctly (update_column for the stale-name fallback test, a
real template for the update-persists test).
|
|
password_required? treated a blank crypted_password as "needs a
password", but after bcrypt migration crypted_password is nil by
design -- every subsequent save of a migrated or new user failed
validation. The predicate now requires a password only when both
the legacy and the bcrypt credential are absent, or when one is
actually being set.
|
|
|
|
Add has_secure_password and bcrypt while retaining compatibility with
legacy SHA-1 password hashes. Existing users are upgraded to
password_digest on their next successful login.
Add regression tests covering both legacy and modern authentication
paths.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|