Skip to content

[AIDAPP-1595]: Improve the user interface of advisories in the portal - #1561

Merged
danharrin merged 26 commits into
mainfrom
AIDAPP-1595
Oct 23, 2026
Merged

danharrin merged 26 commits into
mainfrom
AIDAPP-1595

Conversation

@nency-canyon

@nency-canyon nency-canyon commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Ticket(s) or GitHub Issue

Technical Description

  • Replaced the stacked advisory cards in the portal with a list view: active/no-active callout, Active and Resolved tabs with counts, search, severity and status filters, highest/lowest severity sort, and pagination.
  • Added an advisory detail page with severity and status badges, assigned department, description and an updates timeline (newest first).
  • Search covers advisory title, description, department, and public update titles and descriptions. Internal updates are excluded from the portal, including search and "Last updated".
  • Admins rank severities by dragging them on the Severities page (new sort column, backfilled in creation order), behind a feature flag for zero-downtime deploys.
  • Reworked the portal advisories endpoint and added a detail endpoint; both require the Advisory Management licence. The asset and licence endpoints now require their licences too.
  • Moved Status, Projects, Advisories and Assets onto the shared common components, deleted the local copies, and replaced arbitrary rounding and colour values with themed utilities.
  • Every portal table now uses a single "View" row action.
  • Simplified tab handling on the knowledge base, project and service request pages, using Filament relation manager tabs for service request Assignments and Chats.
  • Bumped canyongbs/common to ^2.45.0 ([AIDAPP-1595]: Improve the user interface of advisories in the portal common#172). Note: common 2.43+ adds Rector's type-declaration rules, so format-dryrun now flags existing code across the app.

Any deployment steps required?

No

Cleanup Tasks

Added .cleanup-tasks/2026_10_09_advisory_severity_sort_feature.md to remove the AdvisorySeveritySortFeature flag after deployment.


Before contributing and submitting this PR, make sure you have Read, agree, and are compliant with the contributing guidelines.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The portal endpoint never applies the new sorting logic, and the temporary feature flag lacks required cleanup tracking.

2 open findings
What changed in this PR

Adds advisory severity ranking infrastructure intended to improve portal ordering.

Changes:

  • Adds sortable advisory severities with migration, observer, feature flag, and Filament reordering.
  • Adds last-updated and severity-based portal sorting primitives.
  • Adds ranking tests and advisory status factory states.
File Description
app/​Features/​AdvisorySeveritySortFeature.php Gates severity sorting during deployment.
app-modules/​service-management/​tests/​Tenant/​Observers/​AdvisorySeverityObserverTest.php Tests automatic severity ranking.
app-modules/​service-management/​tests/​Tenant/​Filament/​Resources/​AdvisorySeverities/​Pages/​ListAdvisorySeveritiesTest.php Tests listing and reordering behavior.
app-modules/​service-management/​src/​Observers/​AdvisorySeverityObserver.php Assigns new severities the lowest rank.
app-modules/​service-management/​src/​Models/​Scopes/​WithLastUpdatedAt.php Selects each advisory’s latest update time.
app-modules/​service-management/​src/​Models/​AdvisorySeverity.php Registers ranking support.
app-modules/​service-management/​src/​Models/​Advisory.php Exposes the selected last-update timestamp.
app-modules/​service-management/​src/​Filament/​Resources/​AdvisorySeverities/​Pages/​ListAdvisorySeverities.php Enables drag-and-drop ranking.
app-modules/​service-management/​database/​migrations/​2026_10_09_100457_add_sort_column_to_advisory_severities_table.php Adds and backfills severity ranks.
app-modules/​service-management/​database/​factories/​AdvisoryStatusFactory.php Adds open and resolved factory states.
app-modules/​portal/​src/​Enums/​AdvisorySort.php Defines severity-based portal ordering.

🧠 Review effort: Balanced


💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@nency-canyon nency-canyon added the Change Type | Chore Cleanup and refactors that improve performance or the codebase that do not largely affect logic. label Oct 14, 2026
@nency-canyon
nency-canyon marked this pull request as ready for review October 14, 2026 14:08
@nency-canyon
nency-canyon requested a review from a team as a code owner October 14, 2026 14:08
@nency-canyon
nency-canyon requested review from danharrin and jayushi-canyon and a balanced review from Copilot and removed request for danharrin and jayushi-canyon October 14, 2026 14:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Portal queries currently expose and derive searchable metadata from advisory updates marked internal.

5 open findings

🧠 Review effort: Balanced

@danharrin danharrin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Between Status, Projects and Advisories, the portal now has a lot of local UI that other apps' portals will want too. Before this PR merges, I'd like to use it to tidy the components once:

Design system ground rules

  1. Use the themed utilities instead of arbitrary values. The portal's Tailwind preset already maps rounded-sm / rounded / rounded-md / rounded-lg to the tenant's rounding setting, and brand-* to the tenant's primary palette.
    • Write rounded-lg instead of rounded-[var(--rounding-lg)], which appears in about 18 files.
    • Write brand-500 instead of rgba(var(--primary-500),1) or rgb(var(--primary-500)). These appear in AssetFilterTabs, ServiceMonitorDetailsCard, ServiceMonitorStatusCounts, ServiceMonitorUptimeCards, AssetStatCards, BaseSearchInput, BaseSelect, BaseTableSortableHeaderCell and the FormKit theme.
  2. Match the rounding scale to Filament's. At the tenant's default rounding, the themed scale already matches Filament exactly:
    • Containers (cards, tables, empty states, the tabs bar): rounded-lg, which is 0.75rem.
    • Controls (inputs, selects, buttons, tab items, pagination buttons): rounded-md, which is 0.5rem.
    • Badges: rounded, which is 0.375rem.
    • Never use rounded-xl on a surface. It isn't themed, so it ignores the tenant's setting. Common's PageCard, EmptyState, Tabs and Pagination do this today.
  3. Use one surface style everywhere: bg-white shadow-sm ring-1 ring-gray-950/5 rounded-lg. This matches Filament and the existing common components. The local border border-gray-200 shadow-xs style should go.
  4. Keep Tailwind classes out of domain files. Files like serviceMonitorStatuses.js and advisoryPresentation.js should only map domain values to a tone or colour name, such as operational → success. The components own the classes. The severity colour map and the badge colour fallbacks in advisoryPresentation.js should disappear.

New components for canyongbs/common

  • BaseSection (like Filament's Section). Props: heading, description, icon; slots #actions and default.
    • Replaces BaseCard with hand-written <h2> headers: advisory Description and Updates, and the uptime history card with its period select in #actions.
    • Also replaces the shell of ServiceMonitorDetailsCard.
  • BaseTable family, moved from Components/ui:
    • The table container gets #toolbar and #footer slots, so search and filters sit in the same surface as the rows and Pagination sits in the footer. This removes the PageCard wrappers that create a card inside a card on Projects, ViewProject and Advisories, and the -mx-6 pagination hack on Advisories.
    • The header cell gets a sortable prop, replacing BaseTableSortableHeaderCell.
    • The container gets a loading prop, replacing the hand-rolled opacity-60 + aria-busy wrappers on Status and Advisories.
    • BaseTableCellText uses CSS line-clamp instead of cutting text in JavaScript. Advisories then uses it too, instead of its own title and description markup.
  • BaseSelect / BaseSearchInput / BaseInputError, moved from Components/ui:
    • Use Filament's input style: ring-1 ring-gray-950/10 shadow-sm, with a brand focus ring.
    • Give BaseSearchInput a debounce prop. Status and Advisories both duplicate watch + setTimeout today.
    • Give BaseInputError role="alert".
  • BaseCallout (one notice component). Props: tone (success / warning / danger / info / neutral), icon (defaults per tone), title, description, size (sm | lg); a #meta slot plus a small BaseCalloutMeta item.
    • Replaces ServiceMonitorStatusBanner, ServiceMonitorStatusBannerMeta and ServiceMonitorHealthNote, the inline role="note" box in ViewProject, and the advisories summary banner.
    • The advisories page then no longer borrows service-monitor statuses (degraded / operational).
  • BaseStatCard: label, value, icon. It replaces the hand-built cards inside ServiceMonitorUptimeCards. AssetStatCards can move to it later once it gains a tone.

Changes to existing common components

  • Tabs:
    • Add a per-tab badge (count), so Advisories shows "Active" with a count badge instead of "Active (4)", like Filament tabs.
    • Add an idPrefix and full tab accessibility markup: tablist, tab, aria-selected, aria-controls. AssetFilterTabs has this today; common Tabs doesn't.
    • Then delete AssetFilterTabs. The label and idPrefix props and the mb-0! override added to it in this PR go with it.
  • BaseBadge:
    • Add black, light-gray, dark-gray and navy, so every case of the Color enum (which lives in common) works.
    • Add a dot prop and switch to themed rounded.
    • Then delete BaseStatusPill. ServiceMonitorStatusPill becomes BaseBadge with a colour from the status config. Advisory severity uses BaseBadge in both the list and the detail page; today it's a dot in one and a badge in the other.
  • EmptyState: make it the only empty state. Use :contained="false" inside tables and delete BaseTableEmptyState, which draws a dashed box inside the card on Status, Projects and Advisories.
  • PageCard, EmptyState, Tabs, Pagination: follow rule 2 for rounding.
  • Pagination: it's already shaped as a table footer (border-t px-6 py-3), so use it only through BaseTable's #footer.

Keep in the app

  • ServiceMonitorHistoryChart, ServiceMonitorHistorySparkline, ServiceMonitorStatusCounts, ProjectPipelineTable and AdvisoryUpdatesTimeline are domain-specific, so keep them local. Build them from the common pieces above and their status configs.
  • The timeline can move to common once a second page needs it.

Consistency across the three features

  • One row action for every table: a "View" button in the last column, as ProjectsTable and ServiceMonitorsTable already do. Advisories currently has a title link plus a chevron, which gives screen readers two links per row.

Suggested order

  1. Common PR first. Use the local-common-development skill to link common locally. Add the rounding fixes, the Tabs, BaseBadge and EmptyState changes, and the new BaseSection, BaseTable*, inputs, BaseCallout and BaseStatCard. Then we can release that.
  2. This PR: bump common, then move Status, Projects and Advisories onto the shared components. Delete the local copies: AssetFilterTabs, BaseTableEmptyState, BaseStatusPill, BaseCard, BaseTable*, BaseSelect, BaseSearchInput and BaseInputError. Then sweep the arbitrary rounding and colour values, including the FormKit theme.
    • Assets should come along wherever it uses the same components, since it shares the tabs, tables and empty states.
    • BaseDetailSection and BaseList are only used on the service request page and can move to BaseSection later.

@nency-canyon

nency-canyon commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor Author

@danharrin
Thanks, this made sense to do once. I followed the suggested order:
I have pushed changes in canyongbs/common#172, once it will get merged, I will update this PR accordingly.

@nency-canyon

nency-canyon commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Between Status, Projects and Advisories, the portal now has a lot of local UI that other apps' portals will want too. Before this PR merges, I'd like to use it to tidy the components once:

@danharrin

  • I've updated this PR to use common 2.45.0 ([AIDAPP-186]: Update success message when submitting a request #172). Here's what changed:
  • I moved Status, Projects, project detail and Assets onto the shared components and deleted the local copies.
  • I replaced the arbitrary rounding and colour values with themed utilities, including in the FormKit theme.
  • Pagination now sits in the table footer on every table, and it also shows on single-page results ("Showing 1 to 3 of 3"). I also removed the outer card around Assets.
  • Following your review, a few things differ from the mockups: severity uses BaseBadge instead of a coloured dot, each row has a single "View" button instead of a title link plus chevron, and the tabs show count badges ("Active 5") instead of "Active (5)".
  • I merged the latest main, so the severity ranking now lives in the new AdvisoryForm schema.
  • One question: common 2.43+ adds Rector's type-declaration rules, so format-dryrun now flags about 1,000 existing PHP files across the app, not just the ones in this PR. How would you like me to handle this?

danharrin and others added 2 commits October 23, 2026 12:08
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danharrin
danharrin changed the base branch from main to rector-type-declaration-set October 23, 2026 11:08
@danharrin
danharrin added this pull request to stack #1609 October 23, 2026 11:08
@danharrin
danharrin self-requested a review October 23, 2026 11:15
…up rows

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Base automatically changed from rector-type-declaration-set to main October 23, 2026 12:13
danharrin and others added 9 commits October 23, 2026 13:23
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…o their respondent

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…e pagination

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nagement is available

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
# Conflicts:
#	app-modules/engagement/src/Filament/Actions/BulkDraftWithAiAction.php
#	app-modules/engagement/src/Filament/Actions/RelationManagerDraftWithAiAction.php
#	app-modules/knowledge-base/src/Filament/Resources/Actions/DraftKnowledgeBaseItemWithAiAction.php
#	app-modules/portal/tests/Tenant/Unit/AdvisoryApiTest.php
#	app-modules/project/tests/Tenant/Filament/Resources/ProjectResource/Pages/ViewProjectTest.php
#	app-modules/service-management/src/Filament/Resources/ServiceRequests/Pages/ViewServiceRequest.php
#	app-modules/service-management/tests/Tenant/Filament/Resources/Advisories/Pages/ListAdvisoriesTest.php
#	app-modules/service-management/tests/Tenant/Filament/Resources/ServiceRequests/Pages/ViewServiceRequestTest.php
#	app/Filament/Concerns/FiltersManagersFromGroups.php
#	app/Providers/Filament/AdminPanelProvider.php
#	app/Providers/Filament/LandlordPanelProvider.php
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danharrin
danharrin added this pull request to the merge queue Oct 23, 2026
Merged via the queue into main with commit e2c1617 Oct 23, 2026
12 checks passed
@danharrin
danharrin deleted the AIDAPP-1595 branch October 23, 2026 14:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Change Type | Chore Cleanup and refactors that improve performance or the codebase that do not largely affect logic.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants