summaryrefslogtreecommitdiff
path: root/app/views
AgeCommit message (Collapse)Author
2026-07-21Render PDF headlines as document cards, not lightbox imageserdgeist
A starred PDF previously ran through the same crop-and-lightbox path a photo does -- exactly the awkward treatment explicit headline designation was meant to avoid. _headline_image.html.erb now branches on @headline_asset.pdf?: a PDF renders as a linked card (a :medium thumbnail, a file icon, its name), no gallery participation at all. The existing image-headline and gallery-fallback logic is otherwise unchanged, now scoped to an image-specific headline only. Other attached PDFs -- headlined or not -- list below as plain links, same reasoning as why non-headline photos still get a gallery trigger: an attached document shouldn't go invisible just because nothing's been starred yet. headline_image's own render guard needed widening to cover a page with PDFs attached but no images and no headline at all -- the one case none of the existing conditions accounted for.
2026-07-21PDFs currently should have no credits attached to them in displayerdgeist
2026-07-21More PDF headline eligibilityerdgeist
2026-07-21Widen nodes#show to all attachmentserdgeist
2026-07-21Extract Page#headline_asseterdgeist
The same related_assets.find_by(headline: true) query was written by hand in three places -- content_helper, nodes#show, and the chapter teaser partial (which was still using assets.first, the old position-based rule, until now). Collapsed to one method, one query.
2026-07-21Show which image is headlined on nodes#showerdgeist
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.
2026-07-21Render asset credit inside the gallery lightbox correctlyerdgeist
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.
2026-07-20Remove a superflous section headererdgeist
2026-07-20Improve discoverability of headline image logic in nodes#editerdgeist
2026-07-20Make headline images explicit, add asset creditserdgeist
- 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.
2026-07-20Link publish actions to revision diffs in recentserdgeist
2026-07-19Remove one dead events viewerdgeist
2026-07-19Add copy-url button to assets; unified the mechanism across viewserdgeist
2026-07-19Point the style sheet to the correct WIP version in treeerdgeist
2026-07-19Start demolition survey of the css for later redesignserdgeist
2026-07-19Refine the action log's time column layouterdgeist
2026-07-18Emit a report-only Content-Security-Policy with nonced inline scriptserdgeist
- 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
2026-07-18Give action log entries per-verb iconserdgeist
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.
2026-07-18Annotate the History list with each revision's lifecycleerdgeist
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.
2026-07-18Add Trash affordances: cockpit, listing, dashboard entryerdgeist
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.
2026-07-17Route and control trash, restore, and permanent deletionerdgeist
2026-07-17Fix computed_unique_name code and consumererdgeist
2026-07-17Retire recent changes widget, replace with action logerdgeist
2026-07-17Retire recent changes widget, replace with action logerdgeist
2026-07-17Cutover to new Recent Changes widgeterdgeist
2026-07-16Move rrule builder to a partial and share between events#new and events#editerdgeist
2026-07-16managed RRULE constructs now include week selectionerdgeist
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.
2026-07-16Split current_unique_name in a setter and an accessorerdgeist
Also clean up some instance variable assignments on the way.
2026-07-16nodes#show's revisions subsection renamed to historyerdgeist
Now there's a separate revisions history and a full action log for a node. To reflect the extended scope, the section has been renamed to history.
2026-07-16Condense the action log into a scannable tableerdgeist
Several minor improvements to the action log presentation: * Now a table with date and human readable presentation as rows is displayed * If no changes in a title were detected, the old version is omitted * The "inferred" flag is demoted to the end of the line * You can zoom in on the node's history directly from a log line * byline for the first publish action is preserved * Revisions are directly linked to when a new one i published
2026-07-16Add a reader for the action log at admin/logerdgeist
NodeActionsController#index lists entries newest-first, filterable by node_id or user_id -- the two zoom shapes the log was designed around. Rendering goes through NodeActionsHelper.action_summary, which builds one sentence per entry from metadata alone, so entries referencing deleted users or nodes render from their snapshots; live associations only upgrade names to links. Unknown verbs degrade to a generic sentence rather than an error, since the log outlives its vocabulary. The helper is the escaping boundary: every metadata value passes through h() before assembly. Actor names link to the log's own user zoom rather than the unused users page -- inspecting a suspicious user's other actions is the intended workflow. Publish entries with a translation_diff expose a collapsed per-locale change table linking out to the revision itself. Sentences live in en.yml/de.yml following the existing widget-string convention. nodes#show links to its node's zoomed log.
2026-07-16Provide parent_unique_name in nodes#new if parent is already pre-seterdgeist
2026-07-15Make the recent-changes page match the widget it links fromerdgeist
nodes/recent rendered the generic node-listing partial (id, actions, current lock owner, revision number) -- nothing resembling what 'See all recent changes' actually promised to show more of. Both surfaces now render the same extracted partial, so they can't tell two different stories again. Also: head.editor correctly identifies who last wrote the content sitting in head, but publish_draft! never touches editor at all -- nobody has ever had the specific act of publishing recorded anywhere. 'Published by X' was a claim the data never supported, only incidentally true when the same person who drafted something also happened to publish it. Relabeled to 'last edited by' -- same data, accurately described. A real publish-actor is separate, future work, once the action log exists. Basic list styling added for the full page, which had never rendered outside the widget's own compact five-line context before.
2026-07-15Remove dead admin/_recent_changes partialerdgeist
2026-07-14Supply related-asset URLs/name and public inline-image CSSerdgeist
RelatedAssetsController#create's JSON includes large_url, original_url, and name alongside thumb_url/url; the related-asset list items in both editors carry them as data-large-url, data-original-url, and data-name. ccc.css gets the public-facing .inline-image--full/--half/--left/ --right rules -- admin.css and TinyMCE's content_style cover the cockpit and in-editor renderings respectively.
2026-07-14Extend static-asset cache-busting to the public layouterdgeist
mtime_busted_path only ever covered the four admin-only static files. The public layout has the identical exposure -- ccc.css, glightbox's vendored CSS/JS, and public.js are all served straight from public/ with no pipeline fingerprinting either -- just never got the same treatment.
2026-07-14Add chapter images: thumbnail on the list, headline image on the detail pageerdgeist
_chapter.html.erb (the aggregator partial used by the erfas/ chaostreffs overview pages) never rendered an image at all -- editors attaching a hackerspace photo via the asset picker would see zero visible effect on exactly the pages they'd check first. chapter_detail.html.erb (the individual page template) had the same gap. Both fixed by reusing existing infrastructure rather than inventing anything: the overview list gets a small, aspect-preserving :thumb image beside the heading; the detail page gets the app's existing headline_image helper, the same one every other full-page template already uses.
2026-07-14Add a toggleable live preview panel to both editorserdgeist
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.
2026-07-14Make revisions locale awareerdgeist
2026-07-14Add tooltips to all navbar itemserdgeist
2026-07-14Make tags a pill list on nodes#showerdgeist
2026-07-13Add cache-buster using mtime of css and js files outside the asset pipelineerdgeist
2026-07-13Remove redundant default translation from the translations subsectionerdgeist
2026-07-13Fix: p elements can't contain buttons. Convert it to a diverdgeist
2026-07-13Make revision diffs locale-aware, defaulting to whichever locale changederdgeist
diff_against compared title/abstract/body under whatever I18n.locale happened to be ambient, with no concept of 'diff this translation specifically' -- so a change confined to one locale was invisible to Diff Head vs. Draft regardless of which locale you were looking at when you clicked it, exactly the 'yields nothing' complaint from earlier this session. Page#diff_against gains a locale: keyword, additive only -- nil preserves the exact original ambient-locale behavior every existing caller and test already depends on; passing a locale switches to reading each side's actual PageTranslation row directly, same fallback-free reasoning as Page#translation_summary. Page#locale_diff_summary reports one entry per locale present on either side, so an added or removed translation counts as a change even where content matches everywhere it exists on both. RevisionsController#diff now resolves a real locale before diffing -- defaulting to whichever locale actually changed, falling back to the default locale only when nothing did -- and the view carries that locale through every existing control (view toggle, layer-pair buttons, the revision-select form) so it and the view/layer-pair axis stay independently selectable rather than resetting each other.
2026-07-13Wire real autosave into translation editingerdgeist
The shared TinyMCE setup initializes cccms.setup_autosave() on any page with a textarea.with_editor, unconditionally starting a 7-second interval that submits to the form's data-autosave-url -- which the translation edit form never set, so the interval PUT the current page URL itself and 404'd on a nonexistent route. Fixed by actually giving it something to talk to, rather than suppressing it: a real autosave endpoint, and update now goes through Node#autosave!/#save_draft! -- the same pipeline the primary editor uses, fixed earlier this session for exactly this kind of cross-locale carryover. This was the autosave-buffer parity already flagged as due after the proof of concept; the shared JS just forced the timing.
2026-07-13Add per-node translation management: list, edit, destroy, compareerdgeist
Replaces the old locale-switch-and-edit-the-same-screen workflow, which conflated presentation locale with content locale and let an editor silently drift into editing the wrong language with no persistent signal that anything had changed. Non-default-locale content now has its own explicit routes and screens, never sharing a route param with the ambient chrome locale. - PageTranslationsController: index/show/edit/update/destroy, scoped to Page.non_default_locales; update handles first-time creation too, so there's no separate new/create step. - Reads go through the actual PageTranslation row (Page#translation_summary), never through the Globalize fallback-bearing accessor -- fallback is correct for public rendering but wrong for editing, where a missing translation needs to look empty, not borrowed from another locale. - Translations ride on the page's own draft/head cycle; no independent publish state. - nodes#show gains a Translations section (per-locale Lock+Edit / Create+Lock, Destroy, a link into the read-only Compare view) and a locale indicator on its own default-locale content; nodes#edit, nodes#update, and nodes#autosave are pinned to the default locale via Globalize.with_locale regardless of the ambient route locale. - nodes#show no longer double-loads the node or calls wipe_draft! on every view (see previous commit for why that's now safe). - .preview_link_row is renamed .aligned_action_row now that it has a second real consumer.
2026-07-13nodes#show: show each revision's editor, not its byline authorerdgeist
page.user is the piece's credited author, carried forward across revisions; page.editor is whoever actually produced this specific revision. The revisions list wants the latter -- found by inspection while testing something unrelated.
2026-07-13Asset picker: attach/detach/reorder UI, read-only view, autosave fixerdgeist
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.
2026-07-13Wavy-underline: allowlist to default; destroy-button and search polisherdgeist
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.