News
Portal-level news items (ju_news.journal_code = 0) surfaced on the root public site; entry point is main/index.php, reached via the "System News" sidebar gadget rendered by main/right.php. Authoring lives in class/news.class.php under Super Admin's content-management dispatch (main/adm.php?_action=news), out of scope for this module.
| Page | Status | E2E | Enhanced | Legacy Ref | Route | Roles |
|---|---|---|---|---|---|---|
| News Detail | Full | Yes | breadcrumb | main/index.php?newsCode=... | /?newsCode=... | Public |
| News List | New | Yes | — | — | /en/news | Public |
Features
| Feature | Status | E2E | Description |
|---|---|---|---|
| Visitor can read a single portal news item (title, publish date, body) at its own URL | Full | Yes | Detail shows formatted publish date and sanitized rich-HTML body; legacy rendered raw title/date/body into the main content pane. |
| Visitor gets an explicit not-found page when following a dead or unknown news link | New | Yes | Direct visit to an unknown newsCode yields a proper 404 instead of a blank content pane. |
| Visitor can browse the full portal news archive as a paginated list | New | Yes | Canonical /news index page with breadcrumb, Suspense skeleton, ErrorBoundary, and explicit empty/error states. |
| Visitor can sort the news list by publish date (newest/oldest first) | New | Yes | Sort is by newsDate so order matches the displayed Published label rather than insert order. |
| Visitor sees the latest portal news teased on the landing page, linking into detail and to the full list | Full | — | Legacy gadget was persistent sidebar chrome across portal pages; the port scopes it to a landing-page section — the gadget itself is Landing-module chrome per the inventory note. |
| Disabled news items (news_status = 0) are excluded from all public listings | Full | Yes | Only active items appear in the list page and landing section. |
| Disabled news item remains viewable by direct link (legacy status-filter quirk) | Dropped | — | Behavioral divergence from legacy: direct links to disabled items break instead of showing stale content. |
| News detail renders a hero image with graceful placeholder fallback | New | Yes | Items without an image get a styled placeholder rather than broken markup. |
| Long news articles get an auto-generated table of contents with heading anchors | New | — | TOC renders only when the sanitized body contains headings. |
| Visitor can navigate back from a news item via breadcrumb and Back-to-All-News button | New | Yes | Covers list-to-detail-and-back round trip exercised by the detail spec. |
Single-screen module — no standalone list page.
main/index.php's only news branch is isset($_GET['newsCode']), which swaps the main content pane for a single item's title/date/body (query filters journal_code = 0; notably it does not filter news_status, so a disabled item is still viewable by direct link even though it's excluded from the widget below). There is no dispatch branch that renders "all portal news" as its own screen — the closest thing is the "System News" (اخبار سامانه) gadget in main/right.php, a `LIMIT 5` sidebar list of links into this same detail view. That gadget is chrome embedded on the Landing module's page (and persists across most portal pages), not a distinct News-module screen, so it is not listed as a separate row here.Excluded: cross-journal "Journals' News" gadget.
main/right.php also renders a second, visually similar gadget ("اخبار نشریات") aggregating the latest ju_news rows across every journal (journal_code > 0) and linking each headline out to that journal's own news.php?newsCode=... on the journal's own base URL. It's portal chrome, but the content and destination are journal-scoped, not portal-scoped, so it isn't a Portal News screen either — flagging it here so it isn't mistakenly re-added as a row.Verified
news.php is journal-scoped, not portal.The top-level
apps/legacy/js/news.php (and its view/news.view.php + theme templates under themes/*/front/pages/news_list.php / news_detail.php) reads $cnf->journalCode from JU_Config (domain/tenant-resolved), not a hardcoded 0, and is documented as the per-journal public news list/detail in apps/legacy/spec/journal/home-page-sections/home-page-news-section.md. It belongs to the Journal segment's home module, not here.Parallel implementation not added as a row:
mainm/mainn "Highlights" tab.mainm/index.php — the file apps/legacy/apache-httpd/httpd-vhosts.conf maps as DocumentRoot for the branded root-portal domain (journals.ekb.eg / journal.ekb.eg) — renders this same conceptual screen through a differently-named query param: its home page shows a tabbed widget (heading via MENU_NEWS) whose "Highlights" tab lists up to 5 ju_news rows filtered journal_code = 0, each linking to ./?highlights=<news_code>, and a dedicated dispatch branch renders that item's title/date/body from the same table and filter as this row's newsCode branch. mainn/index.php independently reimplements both patterns — its own ?newsCode= branch mirroring main/'s, plus its own separate ?highlights= branch mirroring mainm/'s — so three dispatch files (main/, mainm/, mainn/) each independently implement this one screen. Per the design doc's segment taxonomy, mainm/mainn are Journal-segment source, not Portal; journal/home.html already traced both files, found they hardcode journal_code = 0 and reproduce the Portal segment's cross-journal pattern rather than a themed per-journal home, and now captures this sub-view inside its "Cross-Journal Directory (mainm/mainn default view)" row, whose note explicitly bundles the settings-driven menu/highlights/contact/rss/years sub-views (including this one) into that single composite-screen row rather than splitting each out. Consistent with that resolution, this screen already has a home in journal/home.html and is not added as a second row here; flagging so the duplicate isn't mistaken for an orphaned screen during Phase C/D triage.main/index.php?newsCode=... route vs. the branded portal domain.The
newsCode branch cited above does exist verbatim in main/index.php and filters journal_code = 0 as documented — the Legacy Ref/Route above are accurate for main/ itself. However, per httpd-vhosts.conf, the branded journals.ekb.eg / journal.ekb.eg vhost's DocumentRoot is mainm, not the app root, so a request to that domain never executes main/index.php by default; reaching this exact route requires the generic j.ekb.eg vhost (whose DocumentRoot is the app root) with an explicit /main/index.php path. mainm/index.php's own equivalent screen only understands ?highlights= — it has no ?newsCode= branch at all. This is the same mainm/mainn duplication flagged in the note above, not a distinct row-level defect.