Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
b93c863
update cover image generation logic to show uncropped images
yl5682 Apr 1, 2026
f244792
update cover image generation logic to show uncropped images (collect…
yl5682 Apr 1, 2026
a79161f
adjust foreground-background contrast for full description modal
yl5682 Apr 2, 2026
51bac2d
add an unescape filter to render html entities for collection descrip…
yl5682 Apr 2, 2026
380689d
add spacing between paragraphs in collection full description modal
yl5682 Apr 2, 2026
ab0a3e8
add a button/modal for collection metadata
yl5682 Apr 2, 2026
9a781d7
fix a missing include
yl5682 Apr 7, 2026
ce3890b
improve contrast for flatpage links
yl5682 Apr 7, 2026
69c6b81
update the collection hero layout and styles
yl5682 May 10, 2026
de4a593
hide pagination when there is no item to show
yl5682 May 10, 2026
abf5d7c
update flatpage link colors
yl5682 May 12, 2026
67d8e5f
make the vertical spacing between title and content consistent
yl5682 May 12, 2026
ae13442
update breadcrumb for profile pages
yl5682 May 13, 2026
75b9e47
style account overview page
yl5682 May 13, 2026
0f955fd
update other sections of user profile
yl5682 May 13, 2026
efa9fdc
polish user profile forms
yl5682 May 13, 2026
bc6fec9
update the logout uk-alert-success banner style
yl5682 May 13, 2026
87b402b
style the notification modal
yl5682 May 13, 2026
5bdb2bb
add pagination on the bottom
yl5682 May 13, 2026
8df36e0
update login modal social auth
yl5682 May 13, 2026
0db4c64
stretch page to fill entire viewport
yl5682 May 13, 2026
e6208ab
add label for homepage search field
yl5682 May 13, 2026
1d21373
accessibility: search and my account
yl5682 May 13, 2026
f113713
accessibility: add text to search page button
yl5682 May 13, 2026
ecf8adf
accessibility: search page form fields
yl5682 May 13, 2026
fcd5969
accessibility: volume page fields
yl5682 May 13, 2026
4f73859
accessibility: aria-label
yl5682 May 13, 2026
8d2dd18
Merge branch 'develop' into ui-bug-triage
yl5682 May 13, 2026
ab6b01a
[BUG] Text overlay toggle obstructing text
yl5682 Jun 10, 2026
19a1752
style login page (unstyled)
yl5682 Jun 11, 2026
d916768
render human-readable text on collections page
yl5682 Jun 11, 2026
6181c32
fix an issue with annotation loading
yl5682 Jun 11, 2026
7842aa1
skip MATOMO if unavailable
yl5682 Jun 12, 2026
6851184
Merge branch 'develop' into ui-bug-triage
yl5682 Jun 12, 2026
fca4935
eliminate warnings
yl5682 Jun 12, 2026
2b2dd7d
update wagtail to remove deprecation warnings
yl5682 Jun 12, 2026
8ad8f4f
BUG: Improve formatting of collection hero image and its metadata
yl5682 Jun 12, 2026
7c3ec71
handle html entities accordingly for collection view/pages
yl5682 Jun 12, 2026
9cf7e54
set default elasticsearch namespaces
yl5682 Jun 12, 2026
ff69351
address collection description html entries issue
yl5682 Jun 12, 2026
cb25a7a
use libsass for runtime compilation for now
yl5682 Jun 12, 2026
0da3d06
change annotation text color
yl5682 Jun 12, 2026
4e1ec55
fix annotation search query
yl5682 Jun 12, 2026
e636c63
prevent the annotator from being obstructed by the modals
yl5682 Jun 12, 2026
55404e1
adjust annotation index button css
yl5682 Jun 13, 2026
8ced497
address annotation and search result misalignments
yl5682 Jun 13, 2026
eff0e76
fix inconsistent pdf download button
yl5682 Jun 13, 2026
3e948ab
fix on-page annotation count update issues
yl5682 Jun 13, 2026
381ea29
Merge branch 'develop' into ui-bug-triage
yl5682 Jun 16, 2026
9972cbe
Merge branch 'develop' into ui-bug-triage
yl5682 Jul 9, 2026
456ffab
Improve formatting of collection hero image and its metadata
yl5682 Jul 9, 2026
f5e8c31
add missing aria label for accessibility compliance
yl5682 Jul 9, 2026
cc9519d
add missing aria labels
yl5682 Jul 9, 2026
62f70e3
add aria labels to achieve accessibility compliance
yl5682 Jul 10, 2026
313cb53
Update OCR option description
yl5682 Jul 28, 2026
3db6ce0
rework the date range filter to make it make more sense to users
yl5682 Jul 29, 2026
74e4741
remove unused, confusing css files and keep only the scss files
yl5682 Jul 29, 2026
3bd54f1
retore the apply button
yl5682 Jul 29, 2026
bfc8027
update how the dates are indexed into elasticsearch
yl5682 Jul 29, 2026
cb74848
adding missing banner templates
yl5682 Jul 29, 2026
a3327d0
add proper spacing to the pagination controls
yl5682 Jul 29, 2026
aabf339
use tooltips to show the full content of long collection descriptions
yl5682 Jul 29, 2026
8d5b8b2
add v-cloak to prevent FOUC
yl5682 Jul 29, 2026
7308956
Merge branch 'develop' into ui-bug-triage
yl5682 Jul 29, 2026
4ccac3b
Merge branch 'develop' into ui-bug-triage
jayvarner Aug 6, 2026
176b819
Merge branch 'develop' into ui-bug-triage
yl5682 Aug 12, 2026
7bcc679
fix half-sized hero image background
yl5682 Aug 13, 2026
c9fee32
update annotation handling
yl5682 Aug 13, 2026
544e17e
update annotation handling pt 2
yl5682 Aug 13, 2026
5d0f7b5
place some hiding stuff in html by design to treat FOUC
yl5682 Aug 13, 2026
542cb1d
tweak date filter in search
yl5682 Aug 13, 2026
b897b9b
rename wagtail.css to wagtail_admin.css to avoid confusion
yl5682 Aug 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ staticfiles/*
customizations/**/*.css
customizations/**/*.js

### Vite's temporary compiled copy of vite.config.mjs, created on every
### `vite build`/`vite dev` run and normally deleted on clean exit. A build
### that errors out (missing dep, etc.) can leave one behind.
vite.config.mjs.timestamp-*.mjs

### python gitignores auto-generated by github

# Byte-compiled / optimized / DLL files
Expand Down
9 changes: 7 additions & 2 deletions apps/cms/wagtail_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,10 @@
# Register a custom css file for the wagtail admin.
@hooks.register("insert_global_admin_css", order=100)
def global_admin_css():
"""Add /static/css/wagtail.css."""
return format_html('<link rel="stylesheet" href="{}">', static("css/wagtail.css"))
"""Add /static/css/wagtail_admin.css.

Named wagtail_admin.css (not wagtail.css) to avoid confusion with the
unrelated components/wagtail.scss, which styles rich-text embeds on the
public-facing site rather than admin widgets.
"""
return format_html('<link rel="stylesheet" href="{}">', static("css/wagtail_admin.css"))
23 changes: 10 additions & 13 deletions apps/readux/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,20 +224,17 @@ def get_context_data(self, **kwargs):
.count()
)

user_annotation_index = UserAnnotation.objects.all()

user_annotation_index = user_annotation_index.filter(
canvas__manifest__label=manifest.label
)

user_annotation_index = user_annotation_index.filter(
owner_id=self.request.user.id
).distinct()

# Filter by manifest id (not label — labels aren't guaranteed unique,
# so filtering by label risks mixing in annotations from a different
# manifest that happens to share a title). Grouping happens via
# .values().annotate(Count(...)); an upstream .distinct() on the
# un-grouped queryset is unnecessary here (the GROUP BY already
# collapses to one row per canvas__position) and was masking/dropping
# canvases from the index in practice, so it's been removed.
user_annotation_index = (
user_annotation_index.values(
"canvas__position", "canvas__manifest__label", "canvas__pid"
)
UserAnnotation.objects.filter(canvas__manifest__id=manifest.id)
.filter(owner_id=self.request.user.id)
.values("canvas__position", "canvas__manifest__label", "canvas__pid")
.annotate(Count("canvas__position"))
.order_by("canvas__position")
)
Expand Down
11 changes: 11 additions & 0 deletions apps/static/css/components/search.scss
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,17 @@ form#search-form {
background-color: $rx-color-faded-mint !important;
}

// Scoped to the date range filter only (its selectize dropdowns render inline
// within #date-range-filter, since no dropdownParent is set in search.js) —
// the start/end year selects are single-select, so "selected" here means the
// currently chosen year, not a multi-select tag like the collection/author/
// language facets above. Use the same dark blue as those facet chips instead
// of selectize's default light blue, to match the rest of the design.
#date-range-filter .selectize-dropdown .option.selected {
background-color: $rx-color-midnight-blue !important;
color: $color-white !important;
}

.selectize-control.plugin-clear_button .clear {
height: 85%;
top: -3px !important;
Expand Down
8 changes: 6 additions & 2 deletions apps/static/css/readux.scss
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ main { flex-grow: 1; }
width: 100%;
height: 80vh;
min-height: 500px;
background-color: rgba($rx-color-midnight-blue, 0.8);
background-color: rgba($rx-color-midnight-blue, 0.85);
}

.content {
Expand All @@ -82,7 +82,11 @@ main { flex-grow: 1; }
/* Text & headings */
.paragraph { color: $rx-color-midnight-blue; line-height: normal; }
.title { color: $rx-color-midnight-blue; font-size: x-large; font-weight: bold; }
.hero { padding-top: 15vh; padding-bottom: 2rem; color: $color-white; background-color: rgba($rx-color-midnight-blue, 0.85); }
/* No background-color here: .hero sits on top of .overlay (see above), which
already provides the scrim over the hero image. Giving .hero its own
background would double-stack with .overlay and make the hero area visibly
more opaque than the surrounding .home-nav / .overlay-only regions. */
.hero { padding-top: 15vh; padding-bottom: 2rem; color: $color-white; }
.uk-container h2 { margin-bottom: 0.35rem;}

/* Utilities */
Expand Down
File renamed without changes.
44 changes: 38 additions & 6 deletions apps/static/js/components/VolumeAnnotations.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,34 @@ export default {
// navigation, where added/deleted can be spuriously true because the
// counts of two different pages get compared. Track the current canvas
// and only treat add/delete as real when the canvas hasn't changed.
//
// The annotator (ecds-annotator) also dispatches a synthetic RESET
// "canvasswitch" — {canvas: "all", annotationsOnPage: 0, ...} — before
// the real per-canvas event for whatever canvas is loading. That's not
// a timing race to be debounced away; it's a deliberate, deterministic
// placeholder event that never represents a real page's annotation
// count. Treating it like any other canvas (as the old code did) let it
// poison _prevPageCount with 0, so the next real event for the actual
// canvas got diffed against that bogus 0 and double-counted an
// annotation that was already included in the server-rendered total.
// Fix: ignore canvas === "all" outright rather than guess a settle time.
const RESET_CANVAS = "all";
this._currentCanvas = null;
this._prevPageCount = null;

this._onCanvasSwitch = (event) => {
const detail = event && event.detail ? event.detail : {};
const sameCanvas = detail.canvas && detail.canvas === this._currentCanvas;
const newPageCount = typeof detail.annotationsOnPage === "number" ? detail.annotationsOnPage : null;

if (!detail.canvas || detail.canvas === RESET_CANVAS) {
// Synthetic reset event: carries no real per-canvas count. Ignore
// it entirely — don't touch localPageCount, _currentCanvas, or
// _prevPageCount from it.
return;
}

const sameCanvas = detail.canvas === this._currentCanvas;

if (sameCanvas && newPageCount !== null && this._prevPageCount !== null) {
const delta = newPageCount - this._prevPageCount;
if (delta > 0) {
Expand Down Expand Up @@ -117,12 +138,23 @@ export default {
}
}

if (detail.canvas) {
if (detail.canvas !== this._currentCanvas) {
this._prevPageCount = newPageCount;
}
this._currentCanvas = detail.canvas;
if (detail.canvas !== this._currentCanvas) {
// First sighting of this canvas (or a switch to it). Don't trust
// this event's own annotationsOnPage as the baseline — it can be a
// transient/incomplete read fired before the annotator's async
// fetch for this canvas has resolved, and a later event for the
// SAME canvas with the real count would then get diffed against
// that bogus baseline and double-count an annotation that's already
// included in the server-rendered totals. annotationData (seeded
// from the server-rendered json_data) already has the authoritative
// per-canvas count for anything with existing annotations, so use
// that as the baseline instead. Only fall back to this event's
// value for a canvas annotationData has never heard of (a page with
// zero annotations, where 0 is correct either way).
const known = this.annotationData.find((a) => a.canvas__pid === detail.canvas);
this._prevPageCount = known ? known.canvas__position__count : newPageCount;
}
this._currentCanvas = detail.canvas;
};

window.addEventListener("canvasswitch", this._onCanvasSwitch);
Expand Down
25 changes: 25 additions & 0 deletions apps/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,31 @@
<meta name="twitter:site" content="@emorycds" />
<meta name="twitter:creator" content="@emorycds" />
<link rel="icon" href="{% static 'images/favicons/favicon.ico' %}" />
<style>
/* Critical CSS to prevent a flash of unstyled nav on slow connections.
The top nav's submenus (e.g. "About") are rendered inline in the raw
HTML via {% main_menu add_sub_menus_inline=True %} so the dropdown
works even without JS — but that means they're hidden/positioned as
an overlay purely by the external UIkit/readux stylesheets below. On
a slow connection those stylesheets can still be loading when the
browser's render-blocking timeout expires and it paints anyway, so
the submenu briefly renders in normal document flow: a wide-open
plain list sitting under the nav instead of a hidden dropdown. This
duplicates just enough of UIkit's own navbar/dropdown rules, inline
and dependency-free, to avoid that flash until the full stylesheets
arrive. */
[uk-navbar], .uk-navbar-left, .uk-navbar-right, .uk-navbar-nav {
display: flex;
align-items: center;
list-style: none;
margin: 0;
padding: 0;
}
.uk-navbar-dropdown {
display: none;
position: absolute;
}
</style>
{% block css %}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.17.0/css/uikit.min.css" />
<link type="text/css" href="{% sass_src 'css/readux.scss' %}" rel="stylesheet" />
Expand Down
16 changes: 15 additions & 1 deletion apps/templates/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
{% endblock nav %}

{% block content %}
{{ json_data|json_script:"context" }}
{% block inner %}

<!-- uiAction search -->
Expand Down Expand Up @@ -76,6 +75,21 @@
{% endif %}
{% endblock viewer %}

{% block javascript %}
{% comment %}
Rendered here (outside #v-readux, before main.js loads) rather than inside
the content block: Vue 3 strips <script> tags when it compiles an in-DOM
template, so a json_script tag placed anywhere inside the #v-readux mount
target never survives to be read by VolumeAnnotations.vue's mounted() hook —
document.getElementById("context") comes back null every time, even though
the server renders this tag correctly on every request. Keeping it outside
Vue's mount target (and before main.js, so it's already in the DOM by the
time Vue mounts) is what makes it actually readable.
{% endcomment %}
{{ json_data|json_script:"context" }}
{{ block.super }}
{% endblock javascript %}

{% block extra_javascript %}
<script type="text/javascript">
window.onload = function() {
Expand Down
16 changes: 14 additions & 2 deletions apps/templates/search_results.html
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,14 @@
<select id="id_end_year" name="end_date" aria-label="Filter by end year published"></select>
</div>
</div>
<p class="date-range-bce-note">
{% comment %}
Element stays in the DOM (just visually hidden) even when there's nothing
BCE-dated in the current results, rather than being removed with {% if %} —
search.js toggles an "is-disabled" class on this element by selector with
no null check, so removing it outright would throw when the date filter is
switched on/off.
{% endcomment %}
<p class="date-range-bce-note"{% if not date_range_has_bce %} hidden{% endif %}>
Volumes dated before year 1 CE (BCE) can't be shown individually here — they're grouped under the earliest year in the list above{% if date_range_has_bce %}, labeled "1 or earlier"{% endif %}.
</p>
<button
Expand All @@ -141,7 +148,12 @@
class="date-range-reset-link"
hidden
>Reset Date Range</button>
<div class="date-range-filter-label uk-flex uk-flex-middle date-range-undated-toggle">
{% comment %}
Same reasoning as the BCE note above: kept in the DOM and just hidden when
there's nothing for it to control, since search.js reads this checkbox
unconditionally (id_include_undated.checked, etc.) on every page load.
{% endcomment %}
<div class="date-range-filter-label uk-flex uk-flex-middle date-range-undated-toggle"{% if not undated_volume_count %} hidden{% endif %}>
<input type="checkbox" name="include_undated" id="id_include_undated" class="uk-checkbox uk-margin-small-right"/>
<label for="id_include_undated">
{{ form.include_undated.label }}
Expand Down
Loading