From 68d66cc440f8504792e5dfc56379e98bc2750a62 Mon Sep 17 00:00:00 2001 From: Animesh Kumar Date: Tue, 20 Oct 2026 08:17:06 +0530 Subject: [PATCH] fix(campaigns): render the Email Messages tables with the native CDK table The four tables used the element form of the CDK table, which the shared table styles do not target, so their headers ran together as one line. Switch them, and the Survey Responses table, to table/tr/th/td. Add the shared empty row, translate the ID, Status and Actions headers, give the delete button an aria-label, and give the route a title. Closes #744 --- .../features/campaigns/campaigns.routes.ts | 1 + .../email-messages.component.test.ts | 31 ++++ .../email-messages.component.ts | 171 ++++++++++-------- .../survey-responses.component.ts | 26 +-- 4 files changed, 143 insertions(+), 86 deletions(-) diff --git a/src/app/features/campaigns/campaigns.routes.ts b/src/app/features/campaigns/campaigns.routes.ts index 5b1e3ea91..08995a0cb 100644 --- a/src/app/features/campaigns/campaigns.routes.ts +++ b/src/app/features/campaigns/campaigns.routes.ts @@ -74,6 +74,7 @@ export const CAMPAIGNS_ROUTES: Routes = [ }, { path: 'email-messages', + title: 'EMAIL_MESSAGES.TITLE', canActivate: [authGuard, permissionGuard], data: { permissions: 'READ_EMAIL_CAMPAIGN' }, loadComponent: () => diff --git a/src/app/features/campaigns/email-messages/email-messages.component.test.ts b/src/app/features/campaigns/email-messages/email-messages.component.test.ts index fb899da0a..d1edb850a 100644 --- a/src/app/features/campaigns/email-messages/email-messages.component.test.ts +++ b/src/app/features/campaigns/email-messages/email-messages.component.test.ts @@ -25,6 +25,7 @@ import { NotificationService } from '../../../core/services/notification.service import { createSpyObj } from '../../../testing/mocks'; import { provideTranslateTesting } from '../../../testing/i18n-testing'; import { expectLookedUp } from '../../../testing/translated-text'; +import { CAMPAIGNS_ROUTES } from '../campaigns.routes'; import { EMAIL_TAB, EmailMessagesComponent } from './email-messages.component'; describe('EmailMessagesComponent', () => { @@ -55,4 +56,34 @@ describe('EmailMessagesComponent', () => { expectLookedUp(fixture.nativeElement, ['EMAIL_MESSAGES.CONFIGURATION_JSON']); }); + + it.each([EMAIL_TAB.messages, EMAIL_TAB.pending, EMAIL_TAB.sent, EMAIL_TAB.failed])( + 'renders the %s list as a native table with an empty state', + (tab) => { + fixture.componentInstance.onTabChange(tab); + fixture.detectChanges(); + const root: HTMLElement = fixture.nativeElement; + + expect(root.querySelector('cdk-table')).toBeNull(); + expect(root.querySelector('table[cdk-table] tr[cdk-header-row]')).not.toBeNull(); + expect(root.querySelector('table[cdk-table] tr.no-data-row')).not.toBeNull(); + expectLookedUp(root, ['COMMON.ID', 'COMMON.NO_DATA']); + }, + ); + + it('translates the message headers and labels the delete action', () => { + fixture.componentInstance.messages.set([ + { id: 7, to: 'a@example.org', subject: 'Hi', status: 'pending' }, + ]); + fixture.detectChanges(); + const root: HTMLElement = fixture.nativeElement; + + expectLookedUp(root, ['COMMON.ID', 'COMMON.STATUS', 'COMMON.ACTIONS']); + expect(root.querySelector('tr[cdk-row] ion-button')?.getAttribute('aria-label')).toBeTruthy(); + }); + + it('gives the route a title', () => { + const route = CAMPAIGNS_ROUTES.find((r) => r.path === 'email-messages'); + expect(route?.title).toBe('EMAIL_MESSAGES.TITLE'); + }); }); diff --git a/src/app/features/campaigns/email-messages/email-messages.component.ts b/src/app/features/campaigns/email-messages/email-messages.component.ts index 4a25568be..3984a0711 100644 --- a/src/app/features/campaigns/email-messages/email-messages.component.ts +++ b/src/app/features/campaigns/email-messages/email-messages.component.ts @@ -160,133 +160,154 @@ export type EmailTab = (typeof EMAIL_TAB)[keyof typeof EMAIL_TAB]; } - + - ID - {{ row.id }} + + - {{ - 'EMAIL_MESSAGES.TO' | appTranslate - }} - {{ row.to }} + + - {{ - 'EMAIL_MESSAGES.SUBJECT' | appTranslate - }} - {{ row.subject }} + + - Status - {{ row.status }} + + - Actions - + + - - - + + + + + +
{{ 'COMMON.ID' | appTranslate }}{{ row.id }} + {{ 'EMAIL_MESSAGES.TO' | appTranslate }} + {{ row.to }} + {{ 'EMAIL_MESSAGES.SUBJECT' | appTranslate }} + {{ row.subject }} {{ 'COMMON.STATUS' | appTranslate }}{{ row.status }} {{ 'COMMON.ACTIONS' | appTranslate }} 🗑 - +
+ {{ 'COMMON.NO_DATA' | appTranslate }} +
} @if (activeTab() === TAB.pending) {
- + - ID - {{ row.id }} + + - {{ - 'EMAIL_MESSAGES.TO' | appTranslate - }} - {{ row.to }} + + - {{ - 'EMAIL_MESSAGES.SUBJECT' | appTranslate - }} - {{ row.subject }} + + - {{ - 'EMAIL_MESSAGES.SENT_DATE' | appTranslate - }} - {{ row.sentDate }} + + - - - + + + + + +
{{ 'COMMON.ID' | appTranslate }}{{ row.id }} + {{ 'EMAIL_MESSAGES.TO' | appTranslate }} + {{ row.to }} + {{ 'EMAIL_MESSAGES.SUBJECT' | appTranslate }} + {{ row.subject }} + {{ 'EMAIL_MESSAGES.SENT_DATE' | appTranslate }} + {{ row.sentDate }}
+ {{ 'COMMON.NO_DATA' | appTranslate }} +
} @if (activeTab() === TAB.sent) {
- + - ID - {{ row.id }} + + - {{ - 'EMAIL_MESSAGES.TO' | appTranslate - }} - {{ row.to }} + + - {{ - 'EMAIL_MESSAGES.SUBJECT' | appTranslate - }} - {{ row.subject }} + + - {{ - 'EMAIL_MESSAGES.SENT_DATE' | appTranslate - }} - {{ row.sentDate }} + + - - - + + + + + +
{{ 'COMMON.ID' | appTranslate }}{{ row.id }} + {{ 'EMAIL_MESSAGES.TO' | appTranslate }} + {{ row.to }} + {{ 'EMAIL_MESSAGES.SUBJECT' | appTranslate }} + {{ row.subject }} + {{ 'EMAIL_MESSAGES.SENT_DATE' | appTranslate }} + {{ row.sentDate }}
+ {{ 'COMMON.NO_DATA' | appTranslate }} +
} @if (activeTab() === TAB.failed) {
- + - ID - {{ row.id }} + + - {{ - 'EMAIL_MESSAGES.TO' | appTranslate - }} - {{ row.to }} + + - {{ - 'EMAIL_MESSAGES.SUBJECT' | appTranslate - }} - {{ row.subject }} + + - {{ - 'EMAIL_MESSAGES.SENT_DATE' | appTranslate - }} - {{ row.sentDate }} + + - - - + + + + + +
{{ 'COMMON.ID' | appTranslate }}{{ row.id }} + {{ 'EMAIL_MESSAGES.TO' | appTranslate }} + {{ row.to }} + {{ 'EMAIL_MESSAGES.SUBJECT' | appTranslate }} + {{ row.subject }} + {{ 'EMAIL_MESSAGES.SENT_DATE' | appTranslate }} + {{ row.sentDate }}
+ {{ 'COMMON.NO_DATA' | appTranslate }} +
} @if (activeTab() === TAB.configuration) { @@ -322,6 +343,10 @@ export type EmailTab = (typeof EMAIL_TAB)[keyof typeof EMAIL_TAB]; flex-direction: column; gap: 16px; } + .no-data-row td { + text-align: center; + color: var(--text-muted); + } .full-width { width: 100%; } diff --git a/src/app/features/spm/survey-responses/survey-responses.component.ts b/src/app/features/spm/survey-responses/survey-responses.component.ts index 038e33aed..9310c5bec 100644 --- a/src/app/features/spm/survey-responses/survey-responses.component.ts +++ b/src/app/features/spm/survey-responses/survey-responses.component.ts @@ -108,25 +108,25 @@ interface SurveyResponse { @if (responses().length > 0) {

{{ 'SURVEY_RESPONSES.RESPONSES' | appTranslate }}

- + - ID - {{ row.id ?? row.entryId }} + + - Score - {{ row.score }} + + - Date - {{ row.date }} + + - Actions - + + - - - + + +
ID{{ row.id ?? row.entryId }} Score{{ row.score }} Date{{ row.date }} Actions 🗑 - +
}