<feed xmlns='http://www.w3.org/2005/Atom'>
<title>cccms/config, branch erdgeist-modernize-auth</title>
<subtitle>[no description]</subtitle>
<id>https://erdgeist.org/gitweb/cccms/atom?h=erdgeist-modernize-auth</id>
<link rel='self' href='https://erdgeist.org/gitweb/cccms/atom?h=erdgeist-modernize-auth'/>
<link rel='alternate' type='text/html' href='https://erdgeist.org/gitweb/cccms/'/>
<updated>2026-07-16T11:50:15Z</updated>
<entry>
<title>Condense the action log into a scannable table</title>
<updated>2026-07-16T11:50:15Z</updated>
<author>
<name>erdgeist</name>
<email>erdgeist@erdgeist.org</email>
</author>
<published>2026-07-16T11:50:15Z</published>
<link rel='alternate' type='text/html' href='https://erdgeist.org/gitweb/cccms/commit/?id=603ccfbd5fe96f0b83aaf3d5118aded2a39992fb'/>
<id>urn:sha1:603ccfbd5fe96f0b83aaf3d5118aded2a39992fb</id>
<content type='text'>
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
</content>
</entry>
<entry>
<title>Don't reference your own user as 'du' in action log. It breaks grammar.</title>
<updated>2026-07-16T03:39:27Z</updated>
<author>
<name>erdgeist</name>
<email>erdgeist@erdgeist.org</email>
</author>
<published>2026-07-16T03:39:27Z</published>
<link rel='alternate' type='text/html' href='https://erdgeist.org/gitweb/cccms/commit/?id=bb7ef80d084f474bb4c3be0ae0d033aff3de0272'/>
<id>urn:sha1:bb7ef80d084f474bb4c3be0ae0d033aff3de0272</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Add a reader for the action log at admin/log</title>
<updated>2026-07-16T01:30:01Z</updated>
<author>
<name>erdgeist</name>
<email>erdgeist@erdgeist.org</email>
</author>
<published>2026-07-16T01:30:01Z</published>
<link rel='alternate' type='text/html' href='https://erdgeist.org/gitweb/cccms/commit/?id=190daaa8a0bb79e750894b83e31b9d99f7d900a4'/>
<id>urn:sha1:190daaa8a0bb79e750894b83e31b9d99f7d900a4</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>Make the recent-changes page match the widget it links from</title>
<updated>2026-07-14T23:10:17Z</updated>
<author>
<name>erdgeist</name>
<email>erdgeist@erdgeist.org</email>
</author>
<published>2026-07-14T23:10:17Z</published>
<link rel='alternate' type='text/html' href='https://erdgeist.org/gitweb/cccms/commit/?id=28a6999b55cbec555696df848d6e924aae3166ee'/>
<id>urn:sha1:28a6999b55cbec555696df848d6e924aae3166ee</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>Make revisions locale aware</title>
<updated>2026-07-14T00:17:04Z</updated>
<author>
<name>erdgeist</name>
<email>erdgeist@erdgeist.org</email>
</author>
<published>2026-07-14T00:17:04Z</published>
<link rel='alternate' type='text/html' href='https://erdgeist.org/gitweb/cccms/commit/?id=88ebeaac7fcf140cbab489e841bf9c197f84c4ea'/>
<id>urn:sha1:88ebeaac7fcf140cbab489e841bf9c197f84c4ea</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Wire real autosave into translation editing</title>
<updated>2026-07-13T15:09:31Z</updated>
<author>
<name>erdgeist</name>
<email>erdgeist@erdgeist.org</email>
</author>
<published>2026-07-13T15:09:31Z</published>
<link rel='alternate' type='text/html' href='https://erdgeist.org/gitweb/cccms/commit/?id=aa14587b052a0aa7884aaf27183981975168ab14'/>
<id>urn:sha1:aa14587b052a0aa7884aaf27183981975168ab14</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>Add per-node translation management: list, edit, destroy, compare</title>
<updated>2026-07-13T14:36:38Z</updated>
<author>
<name>erdgeist</name>
<email>erdgeist@erdgeist.org</email>
</author>
<published>2026-07-13T14:36:38Z</published>
<link rel='alternate' type='text/html' href='https://erdgeist.org/gitweb/cccms/commit/?id=0b6ae26f3b4c3c8278e569fa6644a544e996c25d'/>
<id>urn:sha1:0b6ae26f3b4c3c8278e569fa6644a544e996c25d</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>Set config.i18n.available_locales explicitly</title>
<updated>2026-07-13T14:33:45Z</updated>
<author>
<name>erdgeist</name>
<email>erdgeist@erdgeist.org</email>
</author>
<published>2026-07-13T14:33:45Z</published>
<link rel='alternate' type='text/html' href='https://erdgeist.org/gitweb/cccms/commit/?id=8d4aa4da56e2ddb5f53ba142c2b6a5ad49e791d0'/>
<id>urn:sha1:8d4aa4da56e2ddb5f53ba142c2b6a5ad49e791d0</id>
<content type='text'>
Rails-i18n's bundled locale data means an unset available_locales
defaults to every locale it ships pluralization/date rules for --
several hundred, not the two this app actually supports. Harmless
everywhere the outer route scope's own /de|en/ regex already
narrowed whatever reached I18n.available_locales.include?(...), but
the first code to read the list directly (Page.non_default_locales)
took it at face value. Also closes a related, independently-silent
gap in Page#rewrite_links_in_body, which used the same unconstrained
list to decide whether a link was already locale-prefixed.
</content>
</entry>
<entry>
<title>Add RelatedAssetsController: search, attach, detach, reorder</title>
<updated>2026-07-13T01:22:37Z</updated>
<author>
<name>erdgeist</name>
<email>erdgeist@erdgeist.org</email>
</author>
<published>2026-07-13T01:22:37Z</published>
<link rel='alternate' type='text/html' href='https://erdgeist.org/gitweb/cccms/commit/?id=70653b681d10917b77dced08f577446ced7568f1'/>
<id>urn:sha1:70653b681d10917b77dced08f577446ced7568f1</id>
<content type='text'>
Backend for the asset-picker rebuild -- replaces the plan to dump
every image asset in the system into a hidden, unfiltered browse
panel on every node edit (the actual current behavior, confirmed by
reading nodes/edit.html.erb directly) with a small, name-scoped search
endpoint plus create/destroy/update for attach, detach, and reorder.

No schema change needed -- RelatedAsset already had everything this
requires (asset_id, page_id, an acts_as_list position). search excludes
assets already attached to the page, keeping results meaningfully small
given hundreds of assets total but only a handful per node in practice.
create is find_or_create_by! rather than a bare create!, guarding
against the same asset being attached twice from two separate search
results. update leans on acts_as_list's own insert_at rather than
custom position-shifting logic.

Node#editable_page (autosave || draft || head) is extracted since this
is now its third call site with identical logic -- deliberately not
touching nodes#show, which resolves draft || head without autosave on
purpose, a different and correct semantic for "current committed
state" versus "what's actively being edited."
</content>
</entry>
<entry>
<title>Add a locale-aware relative-time helper; drop stale locale overrides</title>
<updated>2026-07-12T21:42:23Z</updated>
<author>
<name>erdgeist</name>
<email>erdgeist@erdgeist.org</email>
</author>
<published>2026-07-12T21:42:23Z</published>
<link rel='alternate' type='text/html' href='https://erdgeist.org/gitweb/cccms/commit/?id=cf93acb8ad44ba9cd486e8f6457d9fd9fbc041cc'/>
<id>urn:sha1:cf93acb8ad44ba9cd486e8f6457d9fd9fbc041cc</id>
<content type='text'>
Node.recently_changed and the new dashboard need "X ago" rendered
correctly in both locales. Rails' own distance_of_time_in_words/
time_ago_in_words can't do this on their own -- the scope option
changes which translation key is looked up, not the underlying
grammar, and German's "vor" requires dative case, which is a
different word form than the nominative plural Rails computes by
default. relative_time_phrase/relative_distance is a small, from-
scratch bucketing helper instead, with an explicit, hand-checked
translation table per unit per locale.

Also removes de.yml's datetime.distance_in_words and activerecord.
errors blocks. Both used the old {{count}}/{{model}} interpolation
syntax the current i18n gem no longer recognizes -- it silently
leaves the literal placeholder text in the rendered output rather
than erroring, which is why this went unnoticed until now. Both were
shadowing rails-i18n's own current, correct translations for exactly
these keys; deleting the local override lets the gem's version take
over instead of maintaining a second, broken copy.
</content>
</entry>
</feed>
