| Age | Commit message (Collapse) | Author |
|
|
|
Editors' TinyMCE output can contain unclosed void elements like <br>,
which is valid HTML5 but invalid XML -- three different places assumed
the stricter rule and broke or silently misbehaved on the looser one.
The Atom feed's <content type="xhtml"> block required real, well-formed
XML structure but was handed a raw, unescaped body string; switched to
type="html" with CGI.escapeHTML, matching how title/summary already
handle the same content. rewrite_links_in_body used libxml's strict XML
parser to rewrite internal links to be locale-prefixed, which raised on
exactly this class of malformed markup -- silently, since the whole
method was wrapped in rescue; nil, meaning the link rewrite (not the
save) quietly failed with no error anywhere. Replaced with Nokogiri's
lenient HTML parser, which repairs malformed void elements rather than
rejecting them; also drops the bare rescue now that the actual failure
mode it was guarding against shouldn't occur, and fixes two adjacent
bugs found while in this method: a typo'd /sytem/uploads/ regex that
could never match, and a missing https:// exclusion alongside the
existing http:// one.
Also addresses stale flash messaging surfaced while testing the above:
update's save confirmation was being clobbered by edit's own "locked
and ready" notice on the very next request, since nothing distinguished
a fresh lock acquisition from a redirect back after saving. The save
confirmation now names the next step (publish from Status) and flags a
stale translation if one exists, using Page#outdated_translations?,
already present but previously unused by any controller.
|
|
Remove dead pages#index and occurrences resource; fix menu_items#new
menu_items#new called menu_item_params, which requires a submitted
menu_item key that can never be present on a fresh GET -- new only
ever needs a blank record to render against.
pages#index and the entire occurrences resource were unmodified Rails
scaffold generator output, unlinked from any nav and unreachable except
by direct URL. pages#index had no controller action at all (@pages was
never assigned); occurrences#index queried every row with no scoping or
pagination and its layout referenced a scaffold.css asset that no
longer exists in the pipeline. Neither is a real editorial surface --
occurrences are auto-generated from an event's RRULE and were never
meant to be browsed as a flat list. Removed rather than repaired.
pages#preview and pages#sort_images remain, now as explicit routes
rather than under a full resources :pages block.
|
|
Fix button height mismatch, extend table styling to assets/users/events
a.action_button (bordered) and the state_changing/destructive/computation
pills (borderless) rendered at different heights, since each pill variant
set its own padding at higher specificity than the shared rule meant to
equalize them. Padding and border-radius now live only in one shared
rule; also restores the #page_editor prefix on a.action_button, needed
to outrank the #page_editor a wavy-underline rule.
table.assets_table, table.user_table, and table.events_table now share
table.node_table's border-collapse/header/hover treatment. tr
min-height is dropped -- browsers don't honor height on <tr> -- in
favor of cell padding, kept at zero for node_table (spacing already
comes from its h4/p content) and set to 8px for the plain-text tables.
|
|
Adds a fourth button category, .computation -- teal, matching Preview's
existing color -- for actions that compute a view without changing state,
the first case in the app that didn't fit reversible/state-changing/
destructive. Diff revisions now starts disabled and only enables once two
distinct revisions are selected, matching the disabled-state pattern
already used for Unlock + Back.
The header row is wrapped in a real <thead> (previously flat inside the
table alongside data rows) so a sticky diff bar can sit above the fold on
long revision lists -- selecting a comparison pair no longer requires
scrolling back up to find the button, or back down to confirm what's
selected, both surfaced live via one shared JS function.
The two most recent revisions are pre-selected by default, covering the
most common comparison (current against previous) with no extra clicks.
Deliberately scoped to numbered revisions only -- comparing draft/head or
autosave/draft was raised and set aside, since neither exists as a row in
this table by design and extending the comparison to them is a separate
feature, not a default on this one.
Also drops the dead "Edit" subnav link, redundant with nodes#show's
Status section covering the same action with state-aware labeling this
static link could never have.
|
|
Retires content_for :subnavigation on nodes#show entirely -- Preview
was fully redundant with Links' own preview URLs in every state, and
Edit is now a permanent, always-rendered action inside the new Status
section rather than a link floating at the top, consistent with the
"action lives next to the info" pattern People already established
for Unlock. Status surfaces head/draft/autosave plainly and gates
Edit/Publish/Destroy/Discard on lock ownership specifically, not mere
lock presence -- @node.locked? alone would have blocked the lock
owner's own session, caught by the click-test and fixed here rather
than shipped.
nodes#edit's action bar is rebuilt to sit outside form_for (both
button_to calls render their own nested form, invalid HTML the
browser was silently stripping) with Save wired back in via
form="..." rather than needing to live inside the form tag at all.
Also brings the locked-and-ready-to-edit flash message, and the
visual polish from this session's click-test: consistent button
heights across the bordered and pill-shaped variants sharing a row,
spacing between Status's data and its actions, and error_messages
styling reusing the destructive-red vocabulary already established
elsewhere.
|
|
A blank title failed presence and length validation simultaneously,
showing two redundant messages for one problem; length now skips
whenever slug is already blank, matching presence's own skip
condition. Separately, create's failure path never computed
@selected_kind/@parent_id/@parent_name the way new does, so
re-rendering after a validation error silently lost which kind and
parent had been chosen -- for the auto-tagging/auto-templating kinds,
that meant a corrected resubmission could silently produce a plain
generic node instead. required on the title field closes the common
case without a round trip; the server-side fix remains the actual
guarantee, since required is trivially bypassed.
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Sorts rules by hierarchy (base -> layout -> navigation -> buttons ->
tables -> forms -> components), consolidates three duplicated media
query breakpoints into one each, and adds section comments. Bundled
with this reorganization, since the file was rewritten wholesale:
- form.button_to.state_changing: new tinted-pill variant (blue) for
Publish/Restore/Unlock/Revoke, matching .destructive's pattern
- form.button_to.destructive: now a tinted pill at rest instead of
plain colored text, consistent padding at rest and on hover
- Scoped wavy-underline link-visibility fix for #page_editor,
table.node_table, table.assets_table, table.events_table,
table.user_table, .add_child_links, and the dashboard draft list
- #flash decoupled from the page's structural nav-to-content spacing
(.admin_content_spacer), which the flash div was silently providing
as a side effect whenever it rendered
|
|
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).
|
|
nodes#show's flat <table> of label/value pairs grew unreadable once
Admin Preview and Public Preview were added alongside Public Link -
switched to the div.node_description/div.node_content pattern already
used by nodes#edit, grouped into People/Dates/Links/Revisions/Tags/
Events/Children sections rather than one undifferentiated list.
People/Dates/Links use a flex-based item layout, not a second <table> -
multiple independent tables sharing one outer width but different
column counts produced misaligned columns with no shared grid. Flex
items size to their own content with a shared minimum instead.
Revisions and Children are both collapsed via <details>, no JS needed -
previously nodes#show didn't list a node's children at all, blocking
the ability to find/navigate erfa and chaostreff pages without already
knowing they're now standalone nodes. Revision list items link to
node_revision_path(@node, page) - the actual per-revision diff/restore
view, not the plain index.
nodes#new converted to the same pattern for visual consistency, plus a
few things surfaced along the way: submit buttons were unstyled
site-wide (a bare input[type=submit] with no border, fill, or hover
state - Create on this exact page was easy to miss entirely), fixed
with a bordered/bold treatment reusing the existing form.button_to
visual language rather than introducing a fourth button style. Title
regained the bold weight it had before the table rewrite dropped it
silently. Tag list grouping and full link/button semantic taxonomy
(show vs edit/add vs publish/revoke vs destroy, applied consistently
across every link on the page, not just buttons) are known follow-ups,
not attempted here.
|
|
Lets editors share a draft with people outside the admin system, via a
random per-page token rather than an enumerable id - /preview/<token>.
shared_previews#show is intentionally unauthenticated. Redirects to the
real public URL once the page is published. Surfaced on nodes#show
(Admin Preview + Public Preview, next to Public Link) as generate/revoke
buttons.
|
|
events#index still read event.custom_rrule - a live bug the column-drop
migration introduced, not just stale test data. Caught by four test
failures (three fixtures/direct attribute hashes still setting the
removed column, one UnknownAttributeError from a stale fixture loaded
before any test method runs), none of which were actually testing this
view - "should get index" passed throughout with zero Event records
present, meaning it could never have caught a per-row rendering bug.
Strengthened to create one real event first, so a future stray
reference to a dropped or renamed column fails loudly instead of
silently passing on an empty table.
|
|
The following changes were already announced in the last commit, but
the files forgotten. Here's them actually attached.
lib/ccc_conventions.rb: NODE_KINDS registry replaces the kind-specific
branches previously scattered across nodes_controller#create (tags),
unique_path-position check). Each kind declares its parent lookup
(a Proc - Update's "update"/"press_release" continue to genuinely
find-or-create their year-folder via Update.find_or_create_parent;
erfa/chaostreff use a plain find_by_unique_name!, since their parent
nodes are fixed and a missing one should fail loudly, not be silently
created), its tags, and (new) its default template.
New read-only admin/conventions view dumps the NODE_KINDS registry as
a reference table for whoever's confused later about how a given kind
behaves - deliberately just renders the same label/hint text used on
nodes#new rather than re-describing parent/tags/template separately,
since decomposing the parent Proc would mean either invoking it
(Update's has a real side effect - creates the year folder) or
re-stating its logic a second time in a different shape, either of
which risks drifting from the actual behavior.
|
|
nodes#new: each kind's radio button now shows a label plus a smaller,
muted .field_hint explaining what happens automatically (parent,
tags, template) - previously a single undifferentiated string mixing
a short label with a long parenthetical, cluttering the smaller kinds
(erfa/chaostreff) worst. Title field gets the same hint treatment,
telling editors up front that the slug is auto-generated and where to
adjust it later - the previous silence here meant editors only
discovered slug generation after already committing to a title, with
no visible way to fix it.
New "Resulting path" row live-previews the full URL (origin + kind's
path prefix + a debounced call to the new parameterize_preview route,
reusing the exact same slug_for helper "create" now calls, so the
preview can never diverge from what actually gets created) as the
editor types, plus a copy-to-clipboard button. For "generic", the
prefix comes from whichever parent gets chosen via the search widget,
not the registry - parent_search.link_closure now stashes the chosen
node's unique_name as a data attribute for exactly this.
New read-only admin/conventions view dumps the NODE_KINDS registry as
a reference table for whoever's confused later about how a given kind
behaves - deliberately just renders the same label/hint text used on
nodes#new rather than re-describing parent/tags/template separately,
since decomposing the parent Proc would mean either invoking it
(Update's has a real side effect - creates the year folder) or
re-stating its logic a second time in a different shape, either of
which risks drifting from the actual behavior.
nodes#edit's Template field gets a one-line hint noting the value may
already be pre-filled based on how the node was created - the one
place the previous commit's new inheritance mechanism actually
surfaces on this view.
|
|
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.
|
|
The metadata-panel "Event" field on nodes#edit called event_information,
a second, tag-less implementation of "list events + add one" - now
redundant now that nodes#show has the tag-aware version with the
auto-tag flash explanation. Confirmed via grep this was the only call
site before removing both it and the method definition.
|
|
nodes#show's events table now renders unconditionally (previously
hidden entirely for a zero-event node) and gains an "add event" link.
The suggested tag_list is derived from the page's own category tags
via NodesHelper::DEFAULT_EVENT_TAG_BY_PAGE_TAG (erfa-detail/
chaostreff-detail -> open-day) rather than hardcoded, and degrades to
a blank field for any node whose tags don't match - deliberately
universal, not chapter-specific, since Updates have historically
carried event dates the same way.
events#new surfaces *why* the tag was pre-filled via flash.now (not
flash - this is a same-request render, not a redirect), using an
explicit auto_tag_source param passed alongside tag_list rather than
having the controller re-derive the reason from node_id.
No destroy link added to nodes#show's events list - deliberate, per
existing subnav-semantics convention (destructive actions live on the
resource's own views). Covered directly by test.
Adds real coverage for EventsController, previously 100% commented-out
scaffold, plus unit tests for the new tag-mapping helper and the
weekday-abbreviation helpers from the prior commit.
|
|
RruleHumanizer gains WEEKDAY_NAMES_ABBR (Mo/Di/Mi/...) alongside the
existing WEEKDAY_NAMES and WEEKDAY_NAMES_ADVERBIAL hashes, plus a
self.wday_abbr(time, locale) utility mapping a Time's wday to its
RFC5545 code and looking up the abbreviation - keeping RFC5545
vocabulary in one place rather than teaching ContentHelper about day
codes directly.
ContentHelper#weekday_abbr is a thin wrapper passing I18n.locale
through. The partial now renders "Fr 19:00" instead of just "19:00",
joined with a non-breaking space so the pair can't split across a
line wrap.
Takes an explicit Time rather than reading Date.today, matching this
file's existing style of passing state in rather than reading it
ambiently - and staying correct if the currently-unused
calendar/_front_page_calendar partial (spanning six weeks, not just
today) is ever revived and reuses this helper.
|
|
- open_erfas_today helper: samples 3 random open-day-tagged occurrences
of the current day; widget hidden entirely on days without open
chapters; heading shows current weekday
- content/_open_erfas_today partial rendered in right column above
tags and featured articles
- _chapter partial: open-day schedules (event_schedule_text) shown
inline in aggregated chapter lists with 'Offene Tage' label
- ccc.css: open_erfas_today added to existing right-column widget
selector groups (headings, lists, links)
|
|
First application of subnav visual conventions to nodes: actions
column now shows show | edit | revisions as plain informational
links. edit intentionally uses edit_node_path (locking is expected
behaviour for nodes, unlike event views where node_path is used to
avoid inadvertent locking).
|
|
- Split events into open-day tagged events (prominent, via
tagged_with) and other events (secondary listing)
- Use event_schedule_text helper for humanized recurrence +
start time rather than raw rrule string
- Section headings via i18n open_days / upcoming_events keys
|
|
- events_controller: wire return_to through show and new actions;
create respects return_to with fallback to node/event path;
new pre-populates node_id and tag_list from params
- events/edit: remove custom_rrule checkbox; node link removed from
subnav (use show for node navigation); destroy button added
- events/new: remove custom_rrule checkbox; add return_to hidden
field and back link; tag_list field added
- events/show: fix back link via safe_return_to; add node link to
subnav; add destroy button; remove custom_rrule display; show
humanized rrule below raw string
- events/index: destructive class on destroy button; node_id column
replaced with node link; show/edit links carry return_to
- nodes/show: add show/edit links to event entries with return_to
|
|
- app/models/concerns/rrule_humanizer.rb: new concern included into
Event, renders recurring schedule as natural-language German or
English from RRULE string; handles WEEKLY/MONTHLY, biweekly
(INTERVAL=2), ordinal weekday positions (1TU, -1TH, -2WE),
BYMONTH single-month exclusions (December pause convention);
gracefully returns nil for COUNT/UNTIL/unrecognized shapes
- test/models/concerns/rrule_humanizer_test.rb: 15 tests covering
all distinct RRULE shapes found in production data
- app/helpers/nodes_helper.rb: add event_schedule_text helper
combining humanize_rrule with start_time formatting
- app/views/nodes/show.html.erb: add events row, conditionally
rendered when node has associated events
- config/locales/de.yml, en.yml: add event_schedule_time,
event_schedule_unrecognized, event_schedule_none keys
|
|
- event_params now permits title, description, is_primary
- event_information helper lists all node.events, not just the first
- Occurrence.generate handles nil node (standalone events)
- Page.aggregate order_by title uses correlated subquery to avoid
GROUP BY conflict with tag-filter path; order_direction whitelisted
to ASC/DESC to prevent SQL injection
- Events link added to admin menu bar
- events/index shows title, is_primary; drops latitude/longitude columns
|
|
New public page template for erfa and chaostreff nodes. Renders the
node's external_url and lists associated events below the page content.
Seed script updated to set template_name: 'chapter_detail' on all
chapter drafts so the template is applied on publish.
|
|
- _chapter.html.erb: new partial for erfa/chaostreff aggregated lists;
renders title, location, external_url, sanitized body
- content_helper: fix aggregate attr regex to allow hyphens in values
(erfa-detail tag was silently dropped); add debug logging (remove)
- page.rb: suppress libxml stderr noise in rewrite_links_in_body
- db/seeds/chapters.rb: one-shot seed script for erfa and chaostreff
chapter nodes under parent nodes 548/549; creates bilingual pages,
external_url, primary events with RRULEs where known
Note: run Node.rebuild!(false) after execution to fix lft/rgt values
|
|
|
|
|
|
|
|
|
|
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
|
|
- Admin search broke when routing-filter was removed: hardcoded /admin/search
and /admin/menu_search URLs in admin_search.js no longer matched the
locale-scoped routes. Fix by emitting locale-aware URLs from the layout
as JS variables.
- Also fixes form submission (POST -> GET, missing = on form_tag), jQuery
.attr("value") -> .val() for typeahead input reading, and template name
for Rails 8 compatibility.
- Adds a visible "search" link to the admin menu so editors can discover
the feature without knowing the Alt+F shortcut. Search results now show
node path alongside title and link directly to the edit view.
Named route admin_menu_search added to routes.rb.
|
|
tag_list.to_s produces space-separated output which acts-as-taggable-on
13.0.0 (comma delimiter only) treats as a single tag on re-save.
Use join(', ') to render comma-separated tags in the input field.
|
|
- rss#tag_updates action: filters Page.heads by tag name, default
locale, 20 items, same caching as updates feed
- tag_updates.xml.builder: Atom feed with CGI.escapeHTML on title
and summary, consistent with updates.xml.builder
- tags/show.html.erb: add subscription link above article list
- routes: two routes per existing pattern (format-less + .:format
constrained to /xml/)
|
|
/rss/updates without format suffix returns HTTP 406 when the client
does not send an appropriate Accept header. The self link in the Atom
feed was pointing to the format-less URL, causing feed readers that
follow the self link to hit the 406. Fixed to /rss/updates.xml.
|
|
- nodes_controller: permit staged_slug and staged_parent_id in node
params; these were silently dropped since strong parameters migration,
breaking the two-phase slug/parent change workflow
- file_attachment: add SVG support; vector files are copied to all style
directories without rasterisation, preserving scalability in the browser
- assets index/show: constrain image display with max-width/max-height
via admin.css td img rule; fixes oversized SVG thumbnails while leaving
raster variants unaffected
|
|
|
|
|