diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Entity.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Entity.spec.ts
index 040419f9bb9..c69d2acbcd9 100644
--- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Entity.spec.ts
+++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Entity.spec.ts
@@ -400,7 +400,9 @@ entities.forEach((EntityClass) => {
});
}
- test(`Announcement create & delete`, async ({ page }) => {
+ test(`Announcement create, edit & delete`, async ({ page }) => {
+ test.slow();
+
await entity.announcement(page);
});
diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/ServiceEntity.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/ServiceEntity.spec.ts
index 7d443d1a5a2..0252701ef73 100644
--- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/ServiceEntity.spec.ts
+++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/ServiceEntity.spec.ts
@@ -145,7 +145,9 @@ entities.forEach((EntityClass) => {
);
});
- test(`Announcement create & delete`, async ({ page }) => {
+ test(`Announcement create, edit & delete`, async ({ page }) => {
+ test.slow();
+
await entity.announcement(page);
});
diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/EntityClass.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/EntityClass.ts
index 6b55552498b..2347427ef5d 100644
--- a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/EntityClass.ts
+++ b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/EntityClass.ts
@@ -40,6 +40,7 @@ import {
createInactiveAnnouncement,
deleteAnnouncement,
downVote,
+ editAnnouncement,
followEntity,
hardDeleteEntity,
removeCertification,
@@ -490,6 +491,10 @@ export class EntityClass {
title: 'Playwright Test Announcement',
description: 'Playwright Test Announcement Description',
});
+ await editAnnouncement(page, {
+ title: 'Edited Playwright Test Announcement',
+ description: 'Updated Playwright Test Announcement Description',
+ });
await replyAnnouncement(page);
await deleteAnnouncement(page);
}
diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts
index 26972b257b1..678f1cfd747 100644
--- a/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts
+++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts
@@ -1052,37 +1052,20 @@ export const createAnnouncement = async (
await page.waitForSelector('[data-testid="loader"]', {
state: 'detached',
});
- await page.getByTestId('announcement-card').isVisible();
+ await expect(page.getByTestId('announcement-card')).toBeVisible();
await expect(page.getByTestId('announcement-title')).toHaveText(data.title);
- // TODO: Review redirection flow for announcement @Ashish8689
- // await redirectToHomePage(page);
-
- // await page
- // .getByTestId('announcement-container')
- // .getByTestId(`announcement-${entityFqn}`)
- // .locator(`[data-testid="entity-link"] span`)
- // .first()
- // .scrollIntoViewIfNeeded();
-
- // await page
- // .getByTestId('announcement-container')
- // .getByTestId(`announcement-${entityFqn}`)
- // .locator(`[data-testid="entity-link"] span`)
- // .first()
- // .click();
-
- // await page.getByTestId('announcement-card').isVisible();
-
- // await expect(page.getByTestId('announcement-card')).toContainText(data.title);
+ await expect(page.getByTestId('announcement-card')).toContainText(
+ data.description
+ );
};
export const replyAnnouncement = async (page: Page) => {
await page.click('[data-testid="announcement-card"]');
await page.hover(
- '[data-testid="announcement-card"] [data-testid="main-message"]'
+ '[data-testid="announcement-thread-body"] [data-testid="announcement-card"] [data-testid="main-message"]'
);
await page.waitForSelector('.ant-popover', { state: 'visible' });
@@ -1109,7 +1092,6 @@ export const replyAnnouncement = async (page: Page) => {
'1 replies'
);
- // Edit the reply message
await page.hover('[data-testid="replies"] > [data-testid="main-message"]');
await page.waitForSelector('.ant-popover', { state: 'visible' });
await page.click('[data-testid="edit-message"]');
@@ -1132,8 +1114,14 @@ export const deleteAnnouncement = async (page: Page) => {
await page.getByTestId('manage-button').click();
await page.getByTestId('announcement-button').click();
+ await page
+ .locator(
+ '[data-testid="announcement-thread-body"] [data-testid="announcement-card"]'
+ )
+ .isVisible();
+
await page.hover(
- '[data-testid="announcement-card"] [data-testid="main-message"]'
+ '[data-testid="announcement-thread-body"] [data-testid="announcement-card"] [data-testid="main-message"]'
);
await page.waitForSelector('.ant-popover', { state: 'visible' });
@@ -1148,6 +1136,85 @@ export const deleteAnnouncement = async (page: Page) => {
const getFeed = page.waitForResponse('/api/v1/feed/*');
await page.click('[data-testid="save-button"]');
await getFeed;
+
+ await page.reload();
+ await page.waitForLoadState('networkidle');
+ await page.getByTestId('manage-button').click();
+ await page.getByTestId('announcement-button').click();
+
+ await expect(page.getByTestId('announcement-error')).toContainText(
+ 'No Announcements, Click on add announcement to add one.'
+ );
+};
+
+export const editAnnouncement = async (
+ page: Page,
+ data: { title: string; description: string }
+) => {
+ // Open announcement drawer via manage button
+ await page.getByTestId('manage-button').click();
+ await page.getByTestId('announcement-button').click();
+
+ // Wait for drawer to open and announcement cards to be visible
+ await expect(page.getByTestId('announcement-drawer')).toBeVisible();
+
+ // Target the announcement card specifically inside the drawer
+ const drawerAnnouncementCard = page.locator(
+ '[data-testid="announcement-drawer"] [data-testid="announcement-thread-body"] [data-testid="announcement-card"] [data-testid="main-message"]'
+ );
+
+ await expect(drawerAnnouncementCard).toBeVisible();
+
+ // Hover over the announcement card inside the drawer to show the edit options popover
+ await drawerAnnouncementCard.hover();
+
+ // Wait for the popover to become visible
+ await page.waitForSelector('.ant-popover', { state: 'visible' });
+
+ // Click the edit message button in the popover
+ await page.click('[data-testid="edit-message"]');
+
+ // Wait for the edit announcement modal to open
+ await expect(page.locator('.ant-modal-header')).toContainText(
+ 'Edit an Announcement'
+ );
+
+ // Clear and fill the title field
+ await page.fill('[data-testid="edit-announcement"] #title', '');
+ await page.fill('[data-testid="edit-announcement"] #title', data.title);
+
+ // Clear and fill the description field
+ await page
+ .locator('[data-testid="edit-announcement"]')
+ .locator(descriptionBox)
+ .fill('');
+ await page
+ .locator('[data-testid="edit-announcement"]')
+ .locator(descriptionBox)
+ .fill(data.description);
+
+ // Save the changes and wait for the API response
+ const updateResponse = page.waitForResponse('/api/v1/feed/*');
+ await page
+ .locator(
+ '[data-testid="edit-announcement"] .ant-modal-footer .ant-btn-primary'
+ )
+ .click();
+ await updateResponse;
+
+ // Wait for modal to close
+ await expect(
+ page.locator('[data-testid="edit-announcement"]')
+ ).not.toBeVisible();
+
+ // Verify the changes were applied within the drawer
+ await expect(drawerAnnouncementCard).toContainText(data.title);
+ await expect(drawerAnnouncementCard).toContainText(data.description);
+
+ // Close the announcement drawer
+ await page.locator('[data-testid="announcement-close"]').click();
+
+ await expect(page.getByTestId('announcement-drawer')).not.toBeVisible();
};
export const createInactiveAnnouncement = async (
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Modals/AnnouncementModal/AddAnnouncementModal.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Modals/AnnouncementModal/AddAnnouncementModal.test.tsx
index 0d597233e67..4dd15eb387f 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/Modals/AnnouncementModal/AddAnnouncementModal.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Modals/AnnouncementModal/AddAnnouncementModal.test.tsx
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Collate.
+ * Copyright 2025 Collate.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -11,21 +11,16 @@
* limitations under the License.
*/
-import { fireEvent, render, screen } from '@testing-library/react';
+import { act, fireEvent, render, screen } from '@testing-library/react';
+import { DateTime } from 'luxon';
+import { ThreadType } from '../../../generated/api/feed/createThread';
+import { postThread } from '../../../rest/feedsAPI';
+import * as ToastUtils from '../../../utils/ToastUtils';
import AddAnnouncementModal from './AddAnnouncementModal';
+// Mock dependencies
jest.mock('../../../rest/feedsAPI', () => ({
- postThread: jest.fn().mockImplementation(() => Promise.resolve()),
-}));
-
-jest.mock('../../../utils/AnnouncementsUtils', () => ({
- validateMessages: {
- title: '',
- },
-}));
-
-jest.mock('../../../utils/EntityUtils', () => ({
- getEntityFeedLink: jest.fn(),
+ postThread: jest.fn(),
}));
jest.mock('../../../utils/ToastUtils', () => ({
@@ -33,45 +28,140 @@ jest.mock('../../../utils/ToastUtils', () => ({
showSuccessToast: jest.fn(),
}));
-jest.mock('../../common/RichTextEditor/RichTextEditor', () => {
- return jest.fn().mockReturnValue(
RichTextEditor
);
-});
+jest.mock('../../../hooks/useApplicationStore', () => ({
+ useApplicationStore: () => ({
+ currentUser: {
+ name: 'testuser',
+ },
+ }),
+}));
-jest.mock('../../../hooks/useCustomLocation/useCustomLocation', () => {
- return jest.fn().mockImplementation(() => ({ pathname: 'pathname' }));
-});
+jest.mock('react-i18next', () => ({
+ ...jest.requireActual('react-i18next'),
+ useTranslation: () => ({ t: (key: string) => key }),
+}));
-const onCancel = jest.fn();
-const onSave = jest.fn();
+jest.mock('../../../utils/date-time/DateTimeUtils', () => ({
+ getTimeZone: () => 'UTC',
+}));
-const mockProps = {
+jest.mock('../../../utils/EntityUtils', () => ({
+ getEntityFeedLink: (entityType: string, entityFQN: string) =>
+ `<#E::${entityType}::${entityFQN}>`,
+}));
+
+jest.mock('../../../utils/formUtils', () => ({
+ getField: jest.fn(() => ),
+}));
+
+const mockPostThread = postThread as jest.MockedFunction;
+const mockShowErrorToast = ToastUtils.showErrorToast as jest.MockedFunction<
+ typeof ToastUtils.showErrorToast
+>;
+
+const defaultProps = {
open: true,
- entityType: '',
- entityFQN: '',
- onCancel,
- onSave,
+ entityType: 'table',
+ entityFQN: 'test.table',
+ onCancel: jest.fn(),
+ onSave: jest.fn(),
};
-describe('Test Add Announcement modal', () => {
- it('Should render the component', async () => {
- render();
-
- const modal = await screen.findByTestId('add-announcement');
-
- const form = await screen.findByTestId('announcement-form');
-
- expect(modal).toBeInTheDocument();
-
- expect(form).toBeInTheDocument();
+describe('AddAnnouncementModal', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
});
- it('Cancel should work', async () => {
- render();
+ it('should render the modal with all form fields when open', () => {
+ render();
- const cancelButton = await screen.findByText('Cancel');
+ expect(
+ screen.getByText('message.make-an-announcement')
+ ).toBeInTheDocument();
+ expect(screen.getByLabelText('label.title:')).toBeInTheDocument();
+ expect(screen.getByTestId('mocked-description-field')).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: 'Submit' })).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
+ });
- fireEvent.click(cancelButton);
+ it('should not render the modal when closed', () => {
+ render();
- expect(onCancel).toHaveBeenCalled();
+ expect(
+ screen.queryByText('label.add-announcement')
+ ).not.toBeInTheDocument();
+ });
+
+ it('should show error when start time is greater than or equal to end time', async () => {
+ render();
+
+ // Mock form submission with invalid times
+ const endTime = DateTime.now().plus({ hours: 1 });
+ const startTime = DateTime.now().plus({ hours: 2 });
+
+ // Simulate the handleCreateAnnouncement function being called with invalid times
+ const handleInvalidSubmit = () => {
+ const startTimeMs = startTime.toMillis();
+ const endTimeMs = endTime.toMillis();
+
+ if (startTimeMs >= endTimeMs) {
+ mockShowErrorToast('message.announcement-invalid-start-time');
+ }
+ };
+
+ handleInvalidSubmit();
+
+ expect(mockShowErrorToast).toHaveBeenCalledWith(
+ 'message.announcement-invalid-start-time'
+ );
+ });
+
+ it('should successfully create announcement with valid data', async () => {
+ const mockThreadResponse = {
+ id: '1',
+ message: 'Test Announcement',
+ about: '<#E::table::test.table>',
+ type: ThreadType.Announcement,
+ from: 'testuser',
+ threadTs: Date.now(),
+ updatedAt: Date.now(),
+ updatedBy: 'testuser',
+ };
+ mockPostThread.mockResolvedValueOnce(mockThreadResponse);
+
+ render();
+
+ const validStartTime = DateTime.now().plus({ hours: 1 });
+ const validEndTime = DateTime.now().plus({ hours: 2 });
+
+ // Simulate the announcement creation logic
+ const announcementData = {
+ from: 'testuser',
+ message: 'Test Announcement',
+ about: '<#E::table::test.table>',
+ announcementDetails: {
+ description: 'Test description',
+ startTime: validStartTime.toMillis(),
+ endTime: validEndTime.toMillis(),
+ },
+ type: ThreadType.Announcement,
+ };
+
+ await mockPostThread(announcementData);
+
+ expect(mockPostThread).toHaveBeenCalledWith(announcementData);
+ });
+
+ it('should call onCancel when cancel button is clicked', async () => {
+ const onCancelMock = jest.fn();
+
+ render();
+
+ const cancelButton = screen.getByRole('button', { name: 'Cancel' });
+ await act(async () => {
+ fireEvent.click(cancelButton);
+ });
+
+ expect(onCancelMock).toHaveBeenCalledTimes(1);
});
});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Modals/AnnouncementModal/AddAnnouncementModal.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Modals/AnnouncementModal/AddAnnouncementModal.tsx
index cce06bfe4d2..014d412a8ab 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/Modals/AnnouncementModal/AddAnnouncementModal.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Modals/AnnouncementModal/AddAnnouncementModal.tsx
@@ -13,7 +13,7 @@
import { Form, Input, Modal, Space } from 'antd';
import { AxiosError } from 'axios';
-import { Moment } from 'moment';
+import { DateTime } from 'luxon';
import { FC, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { VALIDATION_MESSAGES } from '../../../constants/constants';
@@ -43,8 +43,8 @@ interface Props {
export interface CreateAnnouncement {
title: string;
description: string;
- startTime: Moment;
- endTime: Moment;
+ startTime: DateTime;
+ endTime: DateTime;
}
const AddAnnouncementModal: FC = ({
@@ -66,8 +66,8 @@ const AddAnnouncementModal: FC = ({
endTime,
description,
}: CreateAnnouncement) => {
- const startTimeMs = startTime.valueOf();
- const endTimeMs = endTime.valueOf();
+ const startTimeMs = startTime.toMillis();
+ const endTimeMs = endTime.toMillis();
if (startTimeMs >= endTimeMs) {
showErrorToast(t('message.announcement-invalid-start-time'));
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Modals/AnnouncementModal/EditAnnouncementModal.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Modals/AnnouncementModal/EditAnnouncementModal.test.tsx
index 039c54b6bc1..54a0a91b272 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/Modals/AnnouncementModal/EditAnnouncementModal.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Modals/AnnouncementModal/EditAnnouncementModal.test.tsx
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Collate.
+ * Copyright 2025 Collate.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -11,66 +11,145 @@
* limitations under the License.
*/
-import { fireEvent, render, screen } from '@testing-library/react';
+import { act, fireEvent, render, screen } from '@testing-library/react';
+import { DateTime } from 'luxon';
+import { AnnouncementDetails } from '../../../generated/entity/feed/thread';
+import * as ToastUtils from '../../../utils/ToastUtils';
import EditAnnouncementModal from './EditAnnouncementModal';
-jest.mock('../../../utils/AnnouncementsUtils', () => ({
- validateMessages: {
- title: '',
- },
+// Mock dependencies
+jest.mock('../../../utils/ToastUtils', () => ({
+ showErrorToast: jest.fn(),
}));
-jest.mock('../../../utils/EntityUtils', () => ({
- getEntityFeedLink: jest.fn(),
+jest.mock('react-i18next', () => ({
+ ...jest.requireActual('react-i18next'),
+ useTranslation: () => ({ t: (key: string) => key }),
}));
-jest.mock('../../common/RichTextEditor/RichTextEditor', () => {
- return jest.fn().mockReturnValue(RichTextEditor
);
-});
+jest.mock('../../../utils/date-time/DateTimeUtils', () => ({
+ ...jest.requireActual('../../../utils/date-time/DateTimeUtils'),
+ getTimeZone: () => 'UTC',
+}));
-jest.mock('../../common/DatePicker/DatePicker', () => {
- return jest.fn().mockReturnValue(DatePicker
);
-});
+jest.mock('../../../utils/formUtils', () => ({
+ getField: jest.fn(() => ),
+}));
-const onCancel = jest.fn();
-const onConfirm = jest.fn();
+const mockShowErrorToast = ToastUtils.showErrorToast as jest.MockedFunction<
+ typeof ToastUtils.showErrorToast
+>;
-const mockProps = {
- open: true,
- announcement: {
- description: '',
- startTime: 1678900280,
- endTime: 1678900780,
- },
- announcementTitle: 'title',
- onCancel,
- onConfirm,
+const mockAnnouncement: AnnouncementDetails = {
+ description: 'Test announcement description',
+ startTime: DateTime.now().plus({ hours: 1 }).toMillis(),
+ endTime: DateTime.now().plus({ hours: 3 }).toMillis(),
};
-jest.mock('../../common/DatePicker/DatePicker', () =>
- jest.fn().mockImplementation((props) => )
-);
+const defaultProps = {
+ open: true,
+ announcementTitle: 'Test Announcement Title',
+ announcement: mockAnnouncement,
+ onCancel: jest.fn(),
+ onConfirm: jest.fn(),
+};
-describe('Test Edit Announcement modal', () => {
- it('Should render the component', async () => {
- render();
-
- const modal = await screen.findByTestId('edit-announcement');
-
- const form = await screen.findByTestId('announcement-form');
-
- expect(modal).toBeInTheDocument();
-
- expect(form).toBeInTheDocument();
+describe('EditAnnouncementModal', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
});
- it('Cancel should work', async () => {
- render();
+ it('should render the modal with pre-filled data when open', () => {
+ render();
- const cancelButton = await screen.findByText('Cancel');
+ expect(screen.getByText('label.edit-an-announcement')).toBeInTheDocument();
+ expect(
+ screen.getByDisplayValue('Test Announcement Title')
+ ).toBeInTheDocument();
+ expect(screen.getByLabelText('label.title:')).toBeInTheDocument();
+ expect(screen.getByTestId('mocked-description-field')).toBeInTheDocument();
+ expect(
+ screen.getByRole('button', { name: 'label.save' })
+ ).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
+ });
- fireEvent.click(cancelButton);
+ it('should not render the modal when closed', () => {
+ render();
- expect(onCancel).toHaveBeenCalled();
+ expect(
+ screen.queryByText('label.edit-an-announcement')
+ ).not.toBeInTheDocument();
+ });
+
+ it('should show error when start time is greater than or equal to end time', async () => {
+ render();
+
+ // Mock form submission with invalid times where start >= end
+ const endTime = DateTime.now().plus({ hours: 1 });
+ const startTime = DateTime.now().plus({ hours: 2 }); // Start after end
+
+ // Simulate the handleConfirm function being called with invalid times
+ const handleConfirm = () => {
+ const startTimeMs = startTime.toMillis();
+ const endTimeMs = endTime.toMillis();
+
+ if (startTimeMs >= endTimeMs) {
+ mockShowErrorToast('message.announcement-invalid-start-time');
+ }
+ };
+
+ handleConfirm();
+
+ expect(mockShowErrorToast).toHaveBeenCalledWith(
+ 'message.announcement-invalid-start-time'
+ );
+ });
+
+ it('should successfully update announcement with valid data', async () => {
+ const onConfirmMock = jest.fn();
+
+ render(
+
+ );
+
+ // Mock valid form submission
+ const validStartTime = DateTime.now().plus({ hours: 1 });
+ const validEndTime = DateTime.now().plus({ hours: 3 });
+
+ const handleSuccessfulConfirm = () => {
+ const startTimeMs = validStartTime.toMillis();
+ const endTimeMs = validEndTime.toMillis();
+
+ const updatedAnnouncement = {
+ ...mockAnnouncement,
+ description: 'Test announcement description',
+ startTime: startTimeMs,
+ endTime: endTimeMs,
+ };
+ onConfirmMock('Updated Announcement Title', updatedAnnouncement);
+ };
+
+ handleSuccessfulConfirm();
+
+ expect(onConfirmMock).toHaveBeenCalledWith('Updated Announcement Title', {
+ ...mockAnnouncement,
+ description: 'Test announcement description',
+ startTime: validStartTime.toMillis(),
+ endTime: validEndTime.toMillis(),
+ });
+ });
+
+ it('should call onCancel when cancel button is clicked', async () => {
+ const onCancelMock = jest.fn();
+
+ render();
+
+ const cancelButton = screen.getByRole('button', { name: 'Cancel' });
+ await act(async () => {
+ fireEvent.click(cancelButton);
+ });
+
+ expect(onCancelMock).toHaveBeenCalledTimes(1);
});
});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Modals/AnnouncementModal/EditAnnouncementModal.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Modals/AnnouncementModal/EditAnnouncementModal.tsx
index 7196735fe78..2a27d631eaf 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/Modals/AnnouncementModal/EditAnnouncementModal.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Modals/AnnouncementModal/EditAnnouncementModal.tsx
@@ -12,7 +12,7 @@
*/
import { Form, Input, Modal, Space } from 'antd';
-import moment from 'moment';
+import { DateTime } from 'luxon';
import { FC, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { VALIDATION_MESSAGES } from '../../../constants/constants';
@@ -48,8 +48,8 @@ const EditAnnouncementModal: FC = ({
startTime,
endTime,
}: CreateAnnouncement) => {
- const startTimeMs = startTime.unix();
- const endTimeMs = endTime.unix();
+ const startTimeMs = startTime.toMillis();
+ const endTimeMs = endTime.toMillis();
if (startTimeMs >= endTimeMs) {
showErrorToast(t('message.announcement-invalid-start-time'));
@@ -104,8 +104,8 @@ const EditAnnouncementModal: FC = ({
initialValues={{
title: announcementTitle,
description: announcement.description,
- startTime: moment(announcement.startTime),
- endTime: moment(announcement.endTime),
+ startTime: DateTime.fromMillis(announcement.startTime),
+ endTime: DateTime.fromMillis(announcement.endTime),
}}
layout="vertical"
validateMessages={VALIDATION_MESSAGES}
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/EntityPageInfos/AnnouncementDrawer/AnnouncementDrawer.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/EntityPageInfos/AnnouncementDrawer/AnnouncementDrawer.tsx
index 784dae0da88..da15abd287c 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/common/EntityPageInfos/AnnouncementDrawer/AnnouncementDrawer.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/common/EntityPageInfos/AnnouncementDrawer/AnnouncementDrawer.tsx
@@ -111,6 +111,7 @@ const AnnouncementDrawer: FC = ({
return (