| Age | Commit message (Collapse) | Author |
|
|
|
|
|
.admin_layout replaces the #admin_layout. All css rules and
javascript queries were changed along and rules simplified
where the opportunity arose.
|
|
|
|
|
|
|
|
|
|
nodes#new marks the kinds that place under /updates, derived from each kind's
own path_prefix. The three parent pickers mark candidates the current user
cannot publish into; menu_search returns needs_redaktion per result, computed
per user rather than as a bare restricted flag, and the menu-item picker opts
out.
restore_from_trash! checks its destination: the restore is the move, applied
rather than staged, so no later publish would have caught it. The node
returns as a draft either way.
|
|
|
|
a tabler grip and icon-only edit and delete actions. Shows each item's
non-default translations muted below the title, read from the
translation rows rather than the accessor so the fallback chain cannot
disguise a missing label as a translated one.
Adds move up/down buttons via acts_as_list, the single-pointer
alternative WCAG 2.5.7 requires: the jQuery UI sortable binds mouse
events only, so dragging works neither on touch nor from the keyboard.
The grip is hidden below the desktop breakpoint for the same reason.
The sort handler dropped dataType: "json" against a head :ok response,
which sent every success down the error path, and now reloads so the
disabled chevron states match the stored order after a drag.
|
|
|
|
|
|
|
|
Dropped files land in the existing file input and submit through the
unchanged form. An empty name field is prefilled from the basename.
|
|
|
|
|
|
image_interface and meta_data (admin_interface.js), the sort_images
action and route, and their admin.css rules -- the old vertical
image_browser sidebar this all depended on isn't rendered by any
current view. related_assets.js and the star-toggle sidebar fully
supersede what this did.
Confirmed unreachable via full grep across app/, config/routes.rb,
and admin_bundle.js before removal -- route, controller action, and
JS handler were all individually real and functional, just with
nothing left anywhere that could ever trigger them.
|
|
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.
|
|
- 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
|
|
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.
|
|
|
|
Improve the humanizer to also understand weekly patters that
an editor can manually select, on top of the single week
rules.
Extend template and javascript controller to reflect these
changes.
|
|
|
|
Custom TinyMCE toolbar button opens a picker scoped to a page's own
attached images. Selecting one and a placement (full width, left,
right) inserts <a class="glightbox" data-gallery="page-N">
wrapping an <img>, sharing the existing headline-image lightbox
gallery. No native TinyMCE image dialog or resize handles --
placement is fixed to the three options via CSS classes only.
extended_valid_elements defines a and img explicitly and
symmetrically; valid_classes allows the placement classes and
glightbox specifically. content_style renders placement inside the
editing iframe, since ccc.css doesn't load there.
A pre-save pass removes any a.glightbox left without an img,
covering in-editor deletion regardless of how it happened.
Alt text comes from the asset's name, escaped.
A badge marks whichever attached image sits at position 0, since
_headline_image.html.erb always renders that position as the
page's automatic headline. Shown in the sidebar Images list and in
the picker grid.
|
|
Hidden by default, shares horizontal space with the body editor once
opened rather than a separate section, and only requests the iframe's
src on first toggle -- no preview traffic at all until someone
actually wants to see it. Refreshes automatically on every successful
autosave; a separate force-render button re-attempts a save-and-
refresh cycle immediately, for when the normal 7-second cycle has
been interrupted (a lock-lost error, a transient failure) and waiting
for the next tick isn't good enough.
|
|
|
|
Replaces nodes#edit's old Images section -- a hidden panel dumping
every image asset in the system unfiltered (#image_browser) plus a
raw drag-and-drop box (#image_box) -- with a small search-and-click
picker built on the endpoint from the last two commits. Attaching
posts immediately and appends the new thumbnail via a cloned
<template> -- icons only render correctly through the Rails helper
server-side, so the template holds real, pre-rendered markup for JS
to clone rather than duplicating raw SVG in a JS string. Reordering is
jQuery UI sortable on the small attached list only, with a dedicated
drag handle rather than the whole thumbnail.
Two bugs caught while click-testing, fixed here rather than shipped
and patched after: the search panel never closed after attaching an
image, since the success handler re-triggered focus to keep it open
for attaching several in a row -- which meant it just re-populated
itself forever instead of signaling "done." Fixed to close explicitly;
a click-outside-closes handler was added alongside it, matching the
affordance the top-bar search already has.
A real, independent, pre-existing data bug surfaced during the same
testing: Node#autosave!'s first-time-creation branch never carried
related assets forward from whatever page was previously current --
attach an image, let autosave fire once, and it silently landed on a
fresh, assetless Page row. Long-dormant, not introduced by this work,
just finally exercised by something that made it visible. Fixed inside
the `unless self.autosave` guard specifically -- running this on every
call, not just creation, would overwrite anything attached directly to
an existing autosave in between, a worse bug than the one being fixed.
nodes#show gains a read-only Images section, rendered only when a page
actually has attached images, so an attachment can be confirmed
present without entering the edit/lock cycle -- useful on its own, and
specifically useful the next time an asset bug needs investigating.
Its thumbnail CSS is shared with the edit view's picker via a class
(.thumbnail_list) rather than duplicated under a second name.
|
|
initSearchPicker's input handler has always short-circuited on an empty
term -- correct for every existing picker, none of which want results
appearing before anything's typed. The asset picker does want exactly
that (show the last few uploaded images without requiring a search
first), so this adds an opt-in loadOnFocus option instead of changing
the shared default: it fires once when the input gains focus with no
term yet, reusing the same request/render path a real search uses
rather than a separate code path. The AJAX call itself was pulled out
into a named runSearch function so both triggers could share it without
duplicating the success/render logic.
RelatedAssetsController#search now treats a blank term as "show the
most recently created, unattached images" (limit 5) rather than
returning nothing, matching the new client behavior. A real search
term still returns up to 10 name-matched results, unchanged.
|
|
Flips the plain-link underline from an opt-in list (growing every time
a new context needed it) to the default a rule, with opt-outs living
as more specific overrides where something shouldn't look like plain
content -- .action_button, the icon nav, the search dropdown's bold
results. The allowlist's own history made the case for this: three of
its entries were already hand-copied duplicates of the same five
properties, and two of those had already silently drifted.
form.button_to's icon+text buttons (Destroy, currently) get the same
inline-flex/gap treatment .action_button already had -- they were
never included in that fix, so they still baseline-aligned an SVG
against text instead of centering it, plus an explicit icon size
they'd never had either.
Dashboard search results: tags render as a wrapped row of pills
instead of one-per-line, for visual distinction from page results.
The public-preview link and its Revoke button get their own row
rather than loose inline flow, which wrapped unpredictably next to a
long token URL -- aligned by box-top rather than center or baseline,
since a <button> doesn't reliably expose a text baseline the way a
plain link does, with a small compensating offset for the button's
own internal padding.
|
|
AdminController#dashboard_search returns tags and nodes as separate,
labeled groups (via ActsAsTaggableOn::Tag.named_like and
Node.editor_search) rather than the flat per-node list every existing
picker returns. initSearchPicker gains a renderResults callback option
that, when given, replaces the default per-node rendering entirely --
lets the dashboard render its two labeled groups without a second,
parallel picker implementation.
resultsHeaderHtml (the "Press Enter to see all results" hint) is now
threaded through as a third argument to renderResults, so a picker with
custom rendering can still show it -- previously only the default
per-node branch ever did.
Tags link straight to the existing /admin/nodes/tags/:tag view rather
than becoming an in-place filter chip.
|
|
menu_items/parent_search/move_to_search/event_search each duplicated
their own debounce-free AJAX call and result rendering. Replaced with
one shared initSearchPicker, taking each picker's distinctive
behavior (parent_search's live path preview, event_search's title
hint) as a callback rather than a whole reimplementation. Adds a real
debounce with an out-of-order-response guard -- none of the four had
either before. admin_search (the Alt+F top-bar search) now shares the
same function via its own url/isActive/header options, gaining the
same guard and fixing an inconsistency of its own (it previously
always slid its panel open, even on zero results).
Each picker's results container gets its own id instead of sharing
was ever supposed to be on screen at once, an assumption with no
actual enforcement behind it. Styling moved from an id-pair
(#menu_search_results, #search_results) to a shared .search_results
class so a future picker never needs this file touched again.
menu_search and the admin top-bar search now call Node.editor_search
instead of the public, head-only Node.search -- both are admin-only,
authenticated views, and had no reason to inherit the public search's
"can't find a draft" limitation. The always-ignored :per_page => 1000
on the latter is gone too; Node.search's second argument was never
read by the method at all.
Also removed a stale #metadata a { text-transform: lowercase } rule,
found while verifying the above -- written for the pre-subnav-removal
expand-toggle, which no longer exists; it had been silently
lowercasing nodes#edit's own, unrelated #metadata div (including
move_to_search's results) by id coincidence ever since. #main_navigation
and #overview_toggle intentionally left capitalized rather than
special-cased -- both belong to the nav bar already slated to shrink
to three icons, not worth polishing on the way out.
|
|
|
|
Revisions#diff now computes an inline or side-by-side word diff
server-side (Page#diff_against, lib/html_word_diff.rb) instead of
shipping raw/escaped content to the browser for a 2008-era vendored
JS differ to mangle. View mode is picked via a `view` param, settable
either on the diff page itself or directly from the revisions#index
sticky bar next to "Diff revisions".
Also fixes a pre-existing bug in RevisionsController#diff's single-
revision branch, which set params[:start]/params[:end] instead of
params[:start_revision]/params[:end_revision].
|
|
|
|
Previously piggybacked on the main form's action and relied on a
.js.erb response to update #flash; now posts to the dedicated
autosave route with an explicit _method=put override, and reacts to
a 423 by stopping the timer and showing a persistent banner rather
than letting the next Save discover the conflict on its own.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
parent_match Procs on CccConventions::NODE_KINDS, matched against
unique_path, decide which "add child" kinds show on a given node. Fixes
nodes#new not honoring a pre-selected kind (radio group and parent-field
visibility both defaulted to "generic" unconditionally).
|
|
layouts/admin.html.erb's top-bar search results div shared id
"search_results" with nodes#new/nodes#edit's parent-search widget -
since the layout renders on every admin page, whichever widget's JS
ran last silently won the shared ID, putting top-bar results into the
parent-search box on affected pages. Renamed to "menu_search_results"
and updated admin_search.js to match.
Also modernizes admin_search.js's event bindings from keyup/keydown/
keypress/paste/cut + .attr("value") to input + .val() throughout
(menu_items, parent_search, move_to_search) - the multi-event binding
was working around old IE compatibility that .val() + "input" already
handles correctly. parent_search's result rendering now matches
menu_search's convention (real <p>/<a> markup with a .result_path
span) instead of a bare <a> in a throwaway wrapper div, so the same
CSS rule now correctly applies to both.
menu_search's JSON response gains node_path per result, matching what
admin_search's own results already provide - not yet consumed by
parent_search/move_to_search, which still render click-to-select links
rather than navigable ones (correct for their purpose - selecting a
value, not leaving the page).
Known remaining gap, not fixed here: menu_items, parent_search, and
move_to_search still all target the literal id "search_results"
between themselves. No live collision today since none of the three
currently share a page, but it's the same fragility as the bug above -
tracked alongside the existing menu_items/parent_search/move_to_search
consolidation backlog item rather than treated as resolved.
|
|
|
|
Vendors GLightbox 3.3.1 (MIT, dependency-free) as static files in
public/javascripts and public/stylesheets, replacing the Shadowbox
2009 vendor tree and its jQuery adapter. Public site no longer loads
jQuery at all.
- app/views/layouts/application.html.erb: swap Shadowbox script/style
includes and the public_bundle (jQuery) include for GLightbox's
CSS/JS
- app/views/content/_headline_image.html.erb: headline image is now
itself a GLightbox trigger; additional images are direct
a.glightbox links sharing a per-page data-gallery group, replacing
the hidden shadowbox_images div and its click-forwarding trigger
- public/javascripts/public.js: replace Shadowbox.init/setup and the
click-forwarding handler with a single GLightbox() init call;
remove the unused image_handler object
- Remove public/javascripts/shadowbox/ (including vendored Sizzle,
swfobject, and unused video/Flash players) and
public/stylesheets/shadowbox.css
- Remove app/assets/javascripts/public_bundle.js (jquery require)
|
|
Remove vendored jquery-1.3.2.min.js, jquery-ui-1.7.2.custom.min.js,
and the unreferenced duplicate jquery.hotkeys.js from public/javascripts/.
Public layout now loads jQuery via a small public_bundle.js manifest
through the asset pipeline, same mechanism already used for the admin
interface (admin_bundle.js). This brings the public site from jQuery
1.3.2 (2009) to the current jquery-rails-provided version (3.7.x).
Shadowbox's jQuery adapter (shadowbox-jquery.js) only uses stable APIs
(.css, .remove, .bind, .unbind, .append, .extend) unchanged across this
version span. Verified by manual click-test: gallery image opens,
displays, and dismisses correctly.
public.js required no changes — all jQuery APIs used
(.ready, .bind, .trigger, .length) are stable across versions.
|
|
- Widen overlay (300px -> min(520px, 90vw)), centre instead of
hardcoded left:400px, so it scales from mobile to desktop
- Split title and unique_name into separate JSON fields and DOM
elements; two-line result layout (bold title, small grey
monospace path) instead of "Title (path)" wrapping awkwardly
- Add small margin between title and path line
- Fix event handler stacking: keyup/escape/outside-click handlers
were being rebound on every display_toggle call. Moved all
bindings to initialize(), display_toggle() now only shows/hides
- Switch search input from keyup to input event, catching paste
and cut via mouse which keyup misses
- Add Escape key and outside-click to dismiss the overlay
- Stop clearing search box and results on close; reopening now
preserves prior search, matching standard search UI behaviour
- Link search results to node_path instead of edit_node_path,
since opening edit auto-locks the node
- Add "press Enter to see all results" hint in dropdown
- Disable browser autocomplete on search input
|