diff --git a/src/containers/SheetIntegration/SheetIntegrationList/SheetIntegrationList.module.css b/src/containers/SheetIntegration/SheetIntegrationList/SheetIntegrationList.module.css index 74b168ed71..a7e042356f 100644 --- a/src/containers/SheetIntegration/SheetIntegrationList/SheetIntegrationList.module.css +++ b/src/containers/SheetIntegration/SheetIntegrationList/SheetIntegrationList.module.css @@ -29,7 +29,7 @@ } .LastSync { - width: 20%; + width: 15%; min-width: 200px; } @@ -37,8 +37,19 @@ min-width: 100px; } +.SyncStatus { + min-width: 150px; +} + +.FailureReason { + min-width: 30px; + width: 20%; + overflow: hidden; + text-overflow: ellipsis; +} + .Name { - width: 30%; + width: 25%; min-width: 200px; } @@ -61,4 +72,27 @@ font-weight: 400; margin: 0 12px; color: #073f24; + text-align: center; +} + +.SyncStatusBadge { + border-radius: 14px; + padding: 4px 8px; + min-width: 77px; + text-align: center; + font-size: 14px; + font-weight: 500; + display: inline-block; +} + +.SuccessBadge { + composes: SyncStatusBadge; + background-color: #c8ebdc; + color: #119656; +} + +.ErrorBadge { + composes: SyncStatusBadge; + background-color: #fbe8e8; + color: #dd1f1f; } diff --git a/src/containers/SheetIntegration/SheetIntegrationList/SheetIntegrationList.test.tsx b/src/containers/SheetIntegration/SheetIntegrationList/SheetIntegrationList.test.tsx index 15058c36f4..b55ed888b4 100644 --- a/src/containers/SheetIntegration/SheetIntegrationList/SheetIntegrationList.test.tsx +++ b/src/containers/SheetIntegration/SheetIntegrationList/SheetIntegrationList.test.tsx @@ -11,7 +11,7 @@ import { createSheetQuery, getSheetCountQuery, syncSheetMutation, - syncSheetMutationWithWarnings, + syncSheetMutationWithFailure, } from 'mocks/Sheet'; const mocks = [ @@ -94,8 +94,8 @@ describe('SheetIntegrationList', () => { }); }); - test('Should render warnings', async () => { - const { getByText, getByTestId, getAllByTestId, queryByText } = render(wrapper(syncSheetMutationWithWarnings)); + test('Should render failure reason dialog', async () => { + const { getByText, getByTestId, getAllByTestId, queryByText } = render(wrapper(syncSheetMutationWithFailure)); // loading is show initially expect(getByTestId('loading')).toBeInTheDocument(); @@ -107,13 +107,16 @@ describe('SheetIntegrationList', () => { fireEvent.click(getAllByTestId('additionalButton')[2]); await waitFor(() => { - expect(screen.getByText('Please check the warnings')).toBeInTheDocument(); + expect(screen.getByText('Sync Failed')).toBeInTheDocument(); + expect( + screen.getByText('Failed to fetch data from Google Sheets. Please check your permissions.') + ).toBeInTheDocument(); }); fireEvent.click(screen.getByTestId('ok-button')); await waitFor(() => { - expect(queryByText('Please check the warnings')).not.toBeInTheDocument(); + expect(queryByText('Sync Failed')).not.toBeInTheDocument(); }); }); @@ -134,7 +137,7 @@ describe('SheetIntegrationList', () => { fireEvent.click(screen.getByTestId('ok-button')); }); test('Dialog closes when cross icon is clicked', async () => { - const { getByText, getByTestId, getAllByTestId } = render(wrapper(syncSheetMutationWithWarnings)); + const { getByText, getByTestId, getAllByTestId } = render(wrapper(syncSheetMutationWithFailure)); expect(getByTestId('loading')).toBeInTheDocument(); await waitFor(() => { @@ -143,13 +146,48 @@ describe('SheetIntegrationList', () => { fireEvent.click(getAllByTestId('additionalButton')[2]); await waitFor(() => { - expect(screen.getByText('Please check the warnings')).toBeInTheDocument(); + expect(screen.getByText('Sync Failed')).toBeInTheDocument(); }); const crossIcon = screen.getByLabelText('close'); fireEvent.click(crossIcon); - expect(screen.queryByText('Please check the warnings')).not.toBeInTheDocument(); + expect(screen.queryByText('Sync Failed')).not.toBeInTheDocument(); + }); + + test('Should render Sync Status and Failure Reason columns', async () => { + const { getByText, getByTestId } = render(wrapper()); + + expect(getByTestId('loading')).toBeInTheDocument(); + + await waitFor(() => { + expect(getByText('Google sheets')).toBeInTheDocument(); + }); + + // Check if column headers are present + expect(getByText('Sync Status')).toBeInTheDocument(); + expect(getByText('Failure Reason')).toBeInTheDocument(); + }); + + test('Should display sync status and failure reason values correctly', async () => { + const { getByText, getByTestId } = render(wrapper()); + + expect(getByTestId('loading')).toBeInTheDocument(); + + await waitFor(() => { + expect(getByText('Google sheets')).toBeInTheDocument(); + }); + + // Check if sync status values are displayed + await waitFor(() => { + expect(getByText('SUCCESS')).toBeInTheDocument(); + expect(getByText('FAILED')).toBeInTheDocument(); + }); + + // Check if failure reason is displayed + await waitFor(() => { + expect(getByText('Failed to fetch data from Google Sheets')).toBeInTheDocument(); + }); }); }); diff --git a/src/containers/SheetIntegration/SheetIntegrationList/SheetIntegrationList.tsx b/src/containers/SheetIntegration/SheetIntegrationList/SheetIntegrationList.tsx index 107d5ce541..6cc9752c1f 100644 --- a/src/containers/SheetIntegration/SheetIntegrationList/SheetIntegrationList.tsx +++ b/src/containers/SheetIntegration/SheetIntegrationList/SheetIntegrationList.tsx @@ -40,7 +40,37 @@ const getLastSyncedAt = (date: string, fallback: string = '') => ( ); const getType = (type: SheetTypes) =>
{textForSheetType[type]}
; -const columnStyles = [styles.Name, styles.LastSync, styles.Type, styles.Actions]; + +const getSyncStatus = (status: string) => { + if (!status) { + return
N/A
; + } + + let badgeClass = styles.LastSyncText; + + if (status === 'SUCCESS') { + badgeClass = styles.SuccessBadge; + } else if (status === 'FAILED') { + badgeClass = styles.ErrorBadge; + } + + return
{status}
; +}; + +const getFailureReason = (error: string) => ( +
+ {error || 'N/A'} +
+); + +const columnStyles = [ + styles.Name, + styles.LastSync, + styles.Type, + styles.SyncStatus, + styles.FailureReason, + styles.Actions, +]; const sheetIcon = ; const queries = { @@ -52,17 +82,16 @@ const queries = { export const SheetIntegrationList = () => { const { t } = useTranslation(); - const [warnings, setWarnings] = useState({}); + const [failureReason, setFailureReason] = useState(''); const [showdialog, setShowDialog] = useState(false); let dialog; if (showdialog) { - const warningKeys = Object.keys(warnings); dialog = ( { handleOk={() => setShowDialog(false)} handleCancel={() => setShowDialog(false)} > - {warningKeys.map((key, index) => ( -
- - {index + 1}. {key}: - {' '} - {warnings[key]} -
- ))} +
{failureReason}
); } @@ -86,15 +108,9 @@ export const SheetIntegrationList = () => { fetchPolicy: 'network-only', onCompleted: async ({ syncSheet }) => { const notificationMessage = 'Data is successfully fetched from the Google sheet.'; - if (syncSheet.sheet && syncSheet.sheet.warnings) { - const sheetWarnings = JSON.parse(syncSheet.sheet.warnings); - - if (Object.keys(sheetWarnings).length) { - setShowDialog(true); - setWarnings(sheetWarnings); - } else { - setNotification(notificationMessage); - } + if (syncSheet.sheet && syncSheet.sheet.failureReason) { + setShowDialog(true); + setFailureReason(syncSheet.sheet.failureReason); } else { setNotification(notificationMessage); } @@ -139,16 +155,20 @@ export const SheetIntegrationList = () => { return actions; }; - const getColumns = ({ label, sheetDataCount, lastSyncedAt, type }: any) => ({ + const getColumns = ({ label, sheetDataCount, lastSyncedAt, type, syncStatus, failureReason }: any) => ({ name: getName(label, sheetDataCount, type), date: getLastSyncedAt(lastSyncedAt), type: getType(type), + syncStatus: getSyncStatus(syncStatus), + failureReason: getFailureReason(failureReason), }); const columnNames = [ { name: 'label', label: t('Name') }, { label: t('Last synced') }, { label: t('Type') }, + { label: t('Sync Status') }, + { label: t('Failure Reason') }, { label: t('Actions') }, ]; diff --git a/src/graphql/mutations/Sheet.ts b/src/graphql/mutations/Sheet.ts index 936e5fc49d..f31a5876b2 100644 --- a/src/graphql/mutations/Sheet.ts +++ b/src/graphql/mutations/Sheet.ts @@ -77,7 +77,8 @@ export const SYNC_SHEET = gql` updatedAt url insertedAt - warnings + syncStatus + failureReason } errors { key diff --git a/src/graphql/queries/Sheet.ts b/src/graphql/queries/Sheet.ts index 5b1a94c975..c509a84741 100644 --- a/src/graphql/queries/Sheet.ts +++ b/src/graphql/queries/Sheet.ts @@ -33,6 +33,8 @@ export const GET_SHEETS = gql` label sheetDataCount lastSyncedAt + syncStatus + failureReason insertedAt updatedAt } diff --git a/src/i18n/en/en.json b/src/i18n/en/en.json index c4543b8ca4..3f2e37ec7f 100644 --- a/src/i18n/en/en.json +++ b/src/i18n/en/en.json @@ -348,6 +348,9 @@ "API Key": "API Key", "Sync": "Sync", "Last synced": "Last synced", + "Sync Status": "Sync Status", + "Failure Reason": "Failure Reason", + "Sync Failed": "Sync Failed", "Confirm your credentials": "Confirm your credentials", "You won't be able to use this sheet.": "You won't be able to use this sheet.", "Google sheets": "Google sheets", diff --git a/src/mocks/Sheet.tsx b/src/mocks/Sheet.tsx index 7e422474e7..9a846870f7 100644 --- a/src/mocks/Sheet.tsx +++ b/src/mocks/Sheet.tsx @@ -60,6 +60,8 @@ export const getSheetQuery = { type: 'READ', autoSync: false, lastSyncedAt: '2022-10-16T14:54:54Z', + syncStatus: 'SUCCESS', + failureReason: null, updatedAt: '2022-10-16T14:54:55.000000Z', url: 'https://glific.test:8080/sheet-integration/add', }, @@ -72,6 +74,8 @@ export const getSheetQuery = { type: 'READ', autoSync: false, lastSyncedAt: null, + syncStatus: 'FAILED', + failureReason: 'Failed to fetch data from Google Sheets', updatedAt: '2022-10-16T14:54:55.000000Z', url: 'https://glific.test:8080/sheet-integration/add', }, @@ -177,7 +181,8 @@ export const syncSheetMutation = { lastSyncedAt: '2022-10-14T06:06:23Z', updatedAt: '2022-10-14T06:06:23.141322Z', url: 'https://docs.google.com/spreadsheets/d/e/2PACX-1vQ6L9eu5zCfiCQiULhy_yrw7VYDoMDnb8pNi3E4l226iH865Z8Nv-6XWaZ-CStITlT3EmiCZ_RnHzof/pub?gid=0&single=true&output=csv', - warnings: '{}', + syncStatus: 'SUCCESS', + failureReason: null, type: 'READ', }, errors: null, @@ -186,7 +191,7 @@ export const syncSheetMutation = { }, }; -export const syncSheetMutationWithWarnings = { +export const syncSheetMutationWithFailure = { request: { query: SYNC_SHEET, variables: { id: '2' }, @@ -203,8 +208,8 @@ export const syncSheetMutationWithWarnings = { lastSyncedAt: '2022-10-14T06:06:23Z', updatedAt: '2022-10-14T06:06:23.141322Z', url: 'https://docs.google.com/spreadsheets/d/e/2PACX-1vQ6L9eu5zCfiCQiULhy_yrw7VYDoMDnb8pNi3E4l226iH865Z8Nv-6XWaZ-CStITlT3EmiCZ_RnHzof/pub?gid=0&single=true&output=csv', - warnings: - '{"Warning 1":"This is the first mock warning message","Warning 2":"This is the second mock warning message","Warning 3":"This is the third mock warning message"}', + syncStatus: 'FAILED', + failureReason: 'Failed to fetch data from Google Sheets. Please check your permissions.', type: 'READ', }, errors: null, @@ -212,3 +217,5 @@ export const syncSheetMutationWithWarnings = { }, }, }; + +export const syncSheetMutationWithWarnings = syncSheetMutationWithFailure;