Skip to content

Add blog post alert UI on homepage#13815

Draft
reteps wants to merge 28 commits intomasterfrom
reteps/blog-alert-ui
Draft

Add blog post alert UI on homepage#13815
reteps wants to merge 28 commits intomasterfrom
reteps/blog-alert-ui

Conversation

@reteps
Copy link
Member

@reteps reteps commented Jan 16, 2026

Description

This PR adds a dismissible alert on the PrairieLearn homepage that displays up to 3 most recent unread blog posts from the RSS feed. The feature is intended for instructors only - students do not see the alert.

Requirements:

Key changes:

  • New database tables: cached_blog_posts and user_blog_read_timestamps for tracking read status
  • RSS feed fetching service that runs hourly via cron job
  • Homepage component showing blog posts with dismiss functionality
  • Blog post model functions for database operations

Testing

To test locally:

INSERT INTO cached_news_items (title, link, pub_date, guid)
VALUES (
  'Another Test Post',
  'https://prairielearn.org/blog/another-test',
  NOW(),
  'manual-test-' || gen_random_uuid()
);
CleanShot 2026-01-19 at 11 39 02@2x

After dismissing, the alert should not re-appear.

CleanShot 2026-01-19 at 11 41 55@2x

@codecov
Copy link

codecov bot commented Jan 16, 2026

Codecov Report

❌ Patch coverage is 24.00000% with 57 lines in your changes missing coverage. Please review.
✅ Project coverage is 52.74%. Comparing base (489a167) to head (e9768a6).
⚠️ Report is 9 commits behind head on master.

Files with missing lines Patch % Lines
apps/prairielearn/src/lib/news-feed.ts 14.70% 28 Missing and 1 partial ⚠️
apps/prairielearn/src/models/news-items.ts 23.07% 10 Missing ⚠️
apps/prairielearn/src/tests/e2e/serverUtils.ts 0.00% 8 Missing ⚠️
apps/prairielearn/src/pages/home/home.tsx 50.00% 4 Missing and 1 partial ⚠️
...airielearn/src/pages/home/components/NewsAlert.tsx 20.00% 3 Missing and 1 partial ⚠️
apps/prairielearn/src/tests/e2e/fixtures.ts 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #13815      +/-   ##
==========================================
+ Coverage   52.63%   52.74%   +0.10%     
==========================================
  Files         886      893       +7     
  Lines       33636    33728      +92     
  Branches     5093     5103      +10     
==========================================
+ Hits        17705    17789      +84     
- Misses      14579    14593      +14     
+ Partials     1352     1346       -6     
Flag Coverage Δ
javascript 50.29% <24.00%> (+0.12%) ⬆️
python 70.86% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 16, 2026

All images — No significant size changes
Image Platform Old Size New Size Change
prairielearn/executor:c0259be7e25551190d2842fd224fef9825451a11 linux/amd64 1258.36 MB 1258.91 MB 0.04%
prairielearn/executor:c0259be7e25551190d2842fd224fef9825451a11 linux/arm64 1226.61 MB 1227.16 MB 0.04%
prairielearn/prairielearn:c0259be7e25551190d2842fd224fef9825451a11 linux/amd64 1258.36 MB 1258.91 MB 0.04%
prairielearn/prairielearn:c0259be7e25551190d2842fd224fef9825451a11 linux/arm64 1226.61 MB 1227.15 MB 0.04%
Bundle sizes — No significant size changes
Entry point Old (gzip) New (gzip) Change
scripts/esm-bundles/hydrated-components/InstructorStudentDetail.ts 278.4 kB 278.5 kB +52 B (+0.02%)
scripts/esm-bundles/hydrated-components/InstructorGradebookTable.ts 185.1 kB 185.2 kB +52 B (+0.03%)
scripts/esm-bundles/hydrated-components/InstructorStudents.ts 245.9 kB 245.9 kB +51 B (+0.02%)
scripts/esm-bundles/hydrated-components/AssessmentQuestionManualGrading.ts 280.6 kB 280.7 kB +51 B (+0.02%)
scripts/esm-bundles/hydrated-components/CopyCourseInstanceModal.ts 193.9 kB 193.9 kB +51 B (+0.03%)
scripts/esm-bundles/hydrated-components/TagsTopicsTable.ts 193.3 kB 193.3 kB +50 B (+0.03%)
scripts/esm-bundles/hydrated-components/HomeCards.ts 182.2 kB 182.3 kB +50 B (+0.03%)
scripts/esm-bundles/hydrated-components/CourseInstancePublishing.ts 245.0 kB 245.0 kB +50 B (+0.02%)

Total: 6.15 MB → 6.15 MB (+407 B (+0.01%))

reteps and others added 8 commits January 19, 2026 11:34
Show up to 3 most recent unread blog posts from the PrairieLearn RSS feed
as a dismissible alert to instructors. Includes RSS fetching cron job that
runs hourly, database schema for caching posts and tracking read status,
and homepage integration with dismiss functionality.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Rename all "blog" references to "news" throughout the codebase
- Add RSS category filtering (configurable via newsFeedCategories)
- Default newsFeedUrl to null (feature disabled by default)
- Add e2e tests for news alert visibility and dismissal

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@reteps reteps force-pushed the reteps/blog-alert-ui branch from a763ffd to ce422f1 Compare January 19, 2026 16:34
@github-actions github-actions bot added the documentation Related to user documentation (not code docs) label Jan 19, 2026
@reteps reteps marked this pull request as ready for review January 19, 2026 16:42
@reteps reteps requested a review from a team as a code owner January 19, 2026 16:42
@reteps reteps requested review from nwalters512 and removed request for a team January 19, 2026 16:42
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 19, 2026

Confidence Score: 5/5

  • This PR is safe to merge with no blocking issues
  • The implementation is well-structured with proper database migrations, schema definitions, type safety, error handling, and E2E test coverage. All changes follow established codebase conventions and patterns.
  • No files require special attention

Important Files Changed

Filename Overview
apps/prairielearn/src/migrations/20260116150000_news_alerts__create.sql Creates two tables for caching news items from RSS feed and tracking user read timestamps
apps/prairielearn/src/lib/news-feed.ts RSS parser service that fetches, filters by category, validates, and caches news items
apps/prairielearn/src/models/news-items.ts Model functions for selecting unread news and marking as read, with sequential upserts
apps/prairielearn/src/pages/home/components/NewsAlert.tsx React component rendering dismissible alert with news items and form submit button
apps/prairielearn/src/pages/home/home.tsx Route handler that fetches unread news for instructors and handles dismiss action via POST

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

17 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 19, 2026

📝 Walkthrough

Walkthrough

Introduces a news alert feature that periodically fetches RSS feed items via a new cron job, caches them in the database, and displays unread news items to instructors on the home page with the ability to dismiss alerts.

Changes

Cohort / File(s) Summary
Cron infrastructure
apps/prairielearn/src/cron/fetchNewsItems.ts, apps/prairielearn/src/cron/index.ts
New cron job module for fetching news items with configurable interval; integrated into cron scheduler with interval from config.
Configuration schema
apps/prairielearn/src/lib/config.ts, docs/assets/config-prairielearn.schema.json, docs/assets/config-unified.schema.json
Added three new configuration fields: cronIntervalFetchNewsItemsSec (default 3 hours), newsFeedUrl (optional), and newsFeedCategories (array) for news feed settings.
Database tables
apps/prairielearn/src/migrations/20260116150000_news_alerts__create.sql, database/tables/cached_news_items.pg, database/tables/user_news_read_timestamps.pg, database/tables/users.pg
Created two new tables—cached_news_items for RSS entries and user_news_read_timestamps to track read state—with appropriate indexes and foreign key constraints; updated users table reference.
Database type definitions
apps/prairielearn/src/lib/db-types.ts
Added Zod schemas and TypeScript types for CachedNewsItem and UserNewsReadTimestamp; registered new table names.
Database models and queries
apps/prairielearn/src/models/news-items.sql, apps/prairielearn/src/models/news-items.ts
Implemented SQL and TypeScript layers for selecting unread items per user, upserting cached news items, and tracking user read timestamps.
News feed fetching logic
apps/prairielearn/src/lib/news-feed.ts, apps/prairielearn/package.json
Added RSS feed parsing, validation, category filtering, and caching logic with rss-parser dependency; handles error logging and skips malformed entries.
Frontend integration
apps/prairielearn/src/pages/home/components/NewsAlert.tsx, apps/prairielearn/src/pages/home/home.html.tsx, apps/prairielearn/src/pages/home/home.tsx
New NewsAlert component displaying unread items with dismiss form; integrated into home page for instructors; added fetch and pass-through of unread items in page handler.
End-to-end testing
apps/prairielearn/src/tests/e2e/newsAlert.spec.ts, apps/prairielearn/src/tests/e2e/serverUtils.ts
Added Playwright test suite validating news alert visibility and dismiss functionality; improved server shutdown error handling in test utilities.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add blog post alert UI on homepage' uses sentence case, starts with the verb 'Add', and clearly summarizes the main change of adding a dismissible alert UI component to the homepage.
Description check ✅ Passed The description clearly explains the feature being added (dismissible blog post alert for instructors), lists key changes across database tables, services, and UI components, and provides testing instructions with visual artifacts.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/prairielearn/src/lib/db-types.ts (1)

1559-1661: Add new table names to the TableNames array.

The new tables cached_news_items and user_news_read_timestamps should be added to the TableNames array for consistency with other tables that have corresponding Zod schemas. Based on learnings, all database tables should have corresponding entries here.

Proposed fix
 export const TableNames = [
   'access_logs',
   'access_tokens',
   'administrators',
   'ai_grading_jobs',
   'ai_question_generation_prompts',
   'alternative_groups',
   'assessment_access_rules',
   'assessment_instances',
   'assessment_modules',
   'assessment_question_role_permissions',
   'assessment_questions',
   'assessment_score_logs',
   'assessment_sets',
   'assessment_state_logs',
   'assessments',
   'audit_events',
   'audit_logs',
   'authn_providers',
   'authors',
   'batched_migration_jobs',
   'batched_migrations',
+  'cached_news_items',
   'chunks',
   'client_fingerprints',
   ...
   'users',
+  'user_news_read_timestamps',
   'variant_view_logs',
   ...
🤖 Fix all issues with AI agents
In `@apps/prairielearn/src/lib/news-feed.ts`:
- Around line 14-22: hasMatchingCategory currently returns false for items with
no categories even when allowedCategories is empty; move or adjust the check so
that when allowedCategories.length === 0 the function returns true
unconditionally (i.e., allow all, including uncategorized items). Update the
logic in hasMatchingCategory to check allowedCategories.length === 0
before/independent of the categories existence check, and only perform the
categories empty check when filtering is enabled; keep using the
normalizedAllowed Set and the categories.some(...) match logic for the filtered
case.
- Line 1: hasMatchingCategory currently filters out items without categories
before honoring an empty-allowedCategories rule; change the logic in
hasMatchingCategory so it first returns true if allowedCategories is empty, then
returns false if item.categories is missing, and otherwise checks for any
intersection between item.categories and allowedCategories; also add
"rss-parser" to the apps/prairielearn package.json dependencies (or
workspace-specific deps) so the import Parser from 'rss-parser' is declared.
🧹 Nitpick comments (2)
apps/prairielearn/src/tests/e2e/newsAlert.e2e.spec.ts (1)

47-71: Consider test isolation for dismiss behavior.

The test correctly inserts a new news item to avoid dependency on the first test's state. However, if the first test dismisses the alert (it doesn't currently, but could in future refactoring), the beforeAll item would already be dismissed for the second test.

For better isolation, consider using test.describe.serial() explicitly or ensuring each test is fully independent by cleaning up read timestamps.

apps/prairielearn/src/models/news-items.ts (1)

51-57: Consider batching/parallelizing cached item upserts.

Sequential awaits can add noticeable latency if the feed grows. A simple Promise.all is a low-effort improvement.

Possible refactor
 export async function upsertCachedNewsItems(items: NewsItemInput[]): Promise<CachedNewsItem[]> {
-  const results: CachedNewsItem[] = [];
-  for (const item of items) {
-    const result = await upsertCachedNewsItem(item);
-    results.push(result);
-  }
-  return results;
+  return await Promise.all(items.map((item) => upsertCachedNewsItem(item)));
 }

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/prairielearn/src/tests/e2e/newsAlert.spec.ts`:
- Around line 40-52: The 'can dismiss the news alert' test mutates persistent
state and can race with 'shows news alert to instructors with unread items'; fix
by isolating state: either wrap both tests in a Playwright test.describe.serial
block to enforce order (use test.describe.serial(...) and keep the existing test
names 'can dismiss the news alert' and 'shows news alert to instructors with
unread items'), or add per-test setup/teardown that ensures a fresh news item
and clears dismissals — implement a test.beforeEach that calls your test helper
(e.g., insertNewsItem or API endpoint) to create a fresh news alert and/or a
test.afterEach that resets the dismissal state via the same helper (or call a
resetDismissal API) so 'can dismiss the news alert' no longer affects other
tests.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

20 files reviewed, 1 comment

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

20 files reviewed, no comments

@reteps reteps added do not merge This pull request should not be merged yet blocking This PR is blocking other in-progress work. labels Jan 20, 2026
@reteps reteps removed the do not merge This pull request should not be merged yet label Jan 26, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/prairielearn/src/pages/home/home.tsx`:
- Around line 18-22: Remove the leftover Git conflict markers (<<<<<<< HEAD,
=======, >>>>>>> master) and reconcile the duplicated imports so the module
imports are valid TypeScript; specifically ensure there's a single import for
assertNever and keep the correct import for typedAsyncHandler (or remove it if
unused) in the top of home.tsx (refer to symbols typedAsyncHandler and
assertNever) so only one assertNever import remains and no conflict markers are
left.

@reteps reteps marked this pull request as draft February 3, 2026 21:39
Copy link
Contributor

@nwalters512 nwalters512 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looking good! Biggest outstanding questions:

  • Should we merge the legacy news items removal so that we can use the news_items table for this functionality?
  • Can/should we improve the design?

cronIntervalWorkspaceHostTransitionsSec: z.number().default(10),
cronIntervalChunksHostAutoScalingSec: z.number().default(10),
cronIntervalCleanTimeSeriesSec: z.number().default(10 * 60),
cronIntervalFetchNewsItemsSec: z.number().default(60 * 60 * 3),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like we could do this much more often - maybe every 5 minutes?

It might be nice to give global admins a button to click to perform this sync in case something goes wrong, like we need to correct a title or something.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already addressed — the cron interval defaults to 5 minutes (cronIntervalFetchNewsItemsSec: z.number().default(5 * 60)), the cron job is gated on config.newsFeedUrl, and there's a "Sync news feed" button on the admin settings page.

🤖 Comment by Claude Code

Comment on lines 117 to 121
{
name: 'fetchNewsItems',
module: await import('./fetchNewsItems.js'),
intervalSec: config.cronOverrideAllIntervalsSec || config.cronIntervalFetchNewsItemsSec,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider making this conditional on the presence of config.newsFeedUrl - no need to run if it's not set.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already addressed — cron job is conditional on config.newsFeedUrl (line 119 of cron/index.ts).

🤖 Comment by Claude Code

const body = BodySchema.parse(req.body);

if (body.__action === 'dismiss_news_alert') {
await markNewsItemsAsReadForUser(authn_user_id);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, consider having this take an entire User object.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to accept User instead of Pick<User, 'id'> in a5fd221.\n\n🤖 Comment by Claude Code

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: conventionally model files/function match the name of the table, which in this case is actually cached_news_items.

Presumably the only reason we're not actually using news_items is because that's already taken by the legacy implementation? Should we merge #13747 before this PR now that we have a concrete plan to replace it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The table is now named news_items (the legacy tables were dropped in #14049 which has been merged).

🤖 Comment by Claude Code

Comment on lines 51 to 58
export async function upsertCachedNewsItems(items: NewsItemInput[]): Promise<CachedNewsItem[]> {
const results: CachedNewsItem[] = [];
for (const item of items) {
const result = await upsertCachedNewsItem(item);
results.push(result);
}
return results;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Say we accidentally publish something and want to remove it - this doesn't handle that case, right?

Note saying we need to, I think that'll be rare. If it does happen, I guess we can always fix it in the database manually? I think that's acceptable, just want to make sure this is considered.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The admin settings page has a "Hide" button per news item (sets hidden_at), which removes it from the user-facing alert. For the rare accidental publish case, this should be sufficient — admins can hide the item immediately.

🤖 Comment by Claude Code

logger.verbose('news-feed: Cached news items', { count: newsItems.length });
}
} catch (err) {
logger.error('news-feed: Error fetching or parsing RSS feed', { feedUrl, err });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, a given installation will only ever have one feed URL, so IMO no need to log it - there will never be any ambiguity as to which feed we're trying to fetch. Ditto above.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already addressed — the feed URL is no longer logged. Line 33 just logs 'news-feed: Fetching RSS feed' without the URL.\n\n🤖 Comment by Claude Code

logger.verbose('news-feed: Cached news items', { count: newsItems.length });
}
} catch (err) {
logger.error('news-feed: Error fetching or parsing RSS feed', { feedUrl, err });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider reporting errors here to Sentry for visibility.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already addressed — errors are reported to Sentry at line 74: Sentry.captureException(err).

🤖 Comment by Claude Code

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd feel much more comfortable kicking this into another PR for review discussion. I don't understand why this is here and I've never seen these errors.

If you want a specific question (again, I think we should do this in another PR), I would expect this to have to be in the subprocess where the PL server is actually running, not the parent. Why is this here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The serverUtils.ts changes have been reverted — the file now matches master with no diff.

🤖 Comment by Claude Code

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can zhuzh up the design a bit. I've been throwing prompts to v0 as a way to get something to discuss as a starting point. Here's one such generation:

Image

Things I like about this:

  • Includes dates
  • No bullets (IMO they look too plain for something like this)
  • "View all posts" link
  • Less "blue" - at a minimum, I'd like to avoid blue link text on top of a blue alert

I also think we should consider constraining the width a bit - 100% width leaves us with a ton of empty space:

Image

I'm happy to take a crack at making some improvements if you want, let me know what you think of any of these directions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated design includes: dates per item, no bullets, "View all posts" link, muted blue accent (left border only, no blue background), and constrained width (maxWidth: 720px).

🤖 Comment by Claude Code

reteps and others added 4 commits February 5, 2026 20:40
- Reduce cron interval from 3h to 5min for faster news updates
- Only register fetchNewsItems cron job when newsFeedUrl is configured
- Accept User objects instead of bare strings in news model functions
- Remove feed URL from log messages (only one per installation)
- Add Sentry error reporting for RSS fetch failures
- Add "Sync news feed" button to administrator settings page
- Redesign NewsAlert as a card with blue accent border, structured
  item layout with dates, and optional "View all posts" link
- Revert unrelated serverUtils.ts changes
- Update E2E test selectors for new component structure

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
# Conflicts:
#	apps/prairielearn/package.json
#	yarn.lock
Add hidden_at column to news_items table for soft-deleting news items.
Filter hidden items from user-facing queries and add an admin UI table
on the administrator settings page to view and hide news items.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

Bundle sizes — No significant size changes
Entry point Old (gzip) New (gzip) Change
scripts/esm-bundles/hydrated-components/InstructorStudentDetail.ts 278.4 kB 278.5 kB +52 B (+0.02%)
scripts/esm-bundles/hydrated-components/InstructorGradebookTable.ts 185.1 kB 185.2 kB +52 B (+0.03%)
scripts/esm-bundles/hydrated-components/InstructorStudents.ts 245.9 kB 245.9 kB +51 B (+0.02%)
scripts/esm-bundles/hydrated-components/AssessmentQuestionManualGrading.ts 280.6 kB 280.7 kB +51 B (+0.02%)
scripts/esm-bundles/hydrated-components/CopyCourseInstanceModal.ts 193.9 kB 193.9 kB +51 B (+0.03%)
scripts/esm-bundles/hydrated-components/TagsTopicsTable.ts 193.3 kB 193.3 kB +50 B (+0.03%)
scripts/esm-bundles/hydrated-components/HomeCards.ts 182.2 kB 182.3 kB +50 B (+0.03%)
scripts/esm-bundles/hydrated-components/CourseInstancePublishing.ts 245.0 kB 245.0 kB +50 B (+0.02%)

Total: 6.18 MB → 6.18 MB (+407 B (+0.01%))

reteps and others added 5 commits February 17, 2026 15:38
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rts on newsFeedUrl

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blocking This PR is blocking other in-progress work. documentation Related to user documentation (not code docs)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants