From 41e565b990b286b62a7f375fa15c8d8037a6560a Mon Sep 17 00:00:00 2001
From: Timo
Date: Wed, 3 Jan 2024 11:11:20 +0100
Subject: [PATCH] feat: Add updated manual refresh pattern to editable table
---
src/pages/table-editable/index.jsx | 22 ++++++++++++++--------
src/pages/table/common-components.jsx | 26 +++++++++++++++++++++++++-
test/e2e/page/table-page-object.ts | 10 ++++++++++
test/e2e/table-editable.test.ts | 9 +++++++++
4 files changed, 58 insertions(+), 9 deletions(-)
diff --git a/src/pages/table-editable/index.jsx b/src/pages/table-editable/index.jsx
index 3b1143d..6e3f7bc 100644
--- a/src/pages/table-editable/index.jsx
+++ b/src/pages/table-editable/index.jsx
@@ -1,9 +1,9 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0
import { createRoot } from 'react-dom/client';
-import React, { useRef, useState } from 'react';
+import React, { useRef, useState, useEffect } from 'react';
import { useCollection } from '@cloudscape-design/collection-hooks';
-import { Button, Pagination, Table, TextFilter } from '@cloudscape-design/components';
+import { Pagination, Table, TextFilter } from '@cloudscape-design/components';
import {
distributionEditableTableAriaLabels,
getHeaderCounterText,
@@ -22,7 +22,7 @@ import {
} from '../commons/common-components';
import DataProvider from '../commons/data-provider';
import { useColumnWidths } from '../commons/use-column-widths';
-import { Breadcrumbs, ToolsContent } from '../table/common-components';
+import { Breadcrumbs, ManualRefresh, ToolsContent } from '../table/common-components';
import {
DEFAULT_PREFERENCES,
EDITABLE_COLUMN_DEFINITIONS,
@@ -42,7 +42,9 @@ const withSideEffect =
const fakeDataFetch = delay => new Promise(resolve => setTimeout(() => resolve(), delay));
function TableContent({ loadHelpPanelContent, distributions }) {
- const [loading, setLoading] = useState(false);
+ const [loading, setLoading] = useState(true);
+ const [refreshing, setRefreshing] = useState(false);
+ const [lastRefresh, setLastRefresh] = useState(null);
const [tableItems, setTableItems] = useState(distributions);
const [columnDefinitions, saveWidths] = useColumnWidths('React-TableEditable-Widths', EDITABLE_COLUMN_DEFINITIONS);
const [preferences, setPreferences] = useLocalStorage('React-TableEditable-Preferences', DEFAULT_PREFERENCES);
@@ -80,13 +82,17 @@ function TableContent({ loadHelpPanelContent, distributions }) {
};
const onRefresh = async () => {
- setLoading(true);
+ setRefreshing(true);
await fakeDataFetch(500);
persistChanges();
- setLoading(false);
+ setLastRefresh(new Date());
+ setRefreshing(false);
};
- const refreshButtonProps = { onClick: onRefresh };
+ useEffect(() => {
+ // Demonstrates an initial fetching of the data from the backend.
+ setTimeout(() => setLoading(false), 500);
+ }, []);
const handleSubmit = async (currentItem, column, value) => {
await new Promise(resolve => setTimeout(resolve, 1500));
@@ -140,7 +146,7 @@ function TableContent({ loadHelpPanelContent, distributions }) {
}
+ extraActions={}
onInfoLinkClick={loadHelpPanelContent}
/>
}
diff --git a/src/pages/table/common-components.jsx b/src/pages/table/common-components.jsx
index 367f18e..45611ad 100644
--- a/src/pages/table/common-components.jsx
+++ b/src/pages/table/common-components.jsx
@@ -1,7 +1,8 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0
import React from 'react';
-import { BreadcrumbGroup, HelpPanel } from '@cloudscape-design/components';
+import { Box, BreadcrumbGroup, Button, HelpPanel, SpaceBetween } from '@cloudscape-design/components';
+import formatDate from 'date-fns/format';
import { resourcesBreadcrumbs } from '../../common/breadcrumbs';
import { ExternalLinkGroup } from '../commons';
@@ -43,3 +44,26 @@ export const EC2ToolsContent = () => (
);
+
+export const ManualRefresh = ({ onRefresh, loading, lastRefresh }) => {
+ return (
+
+ {lastRefresh && (
+
+
+ Last updated
+
+ {formatDate(lastRefresh, "MMMM d, yyyy, HH:mm ('UTC'xxx)")}
+
+
+ )}
+
+
+ );
+};
diff --git a/test/e2e/page/table-page-object.ts b/test/e2e/page/table-page-object.ts
index 36b0fa7..db10235 100644
--- a/test/e2e/page/table-page-object.ts
+++ b/test/e2e/page/table-page-object.ts
@@ -34,6 +34,16 @@ export default class TablePageObject extends AppLayoutPage {
return headers.map(header => header.getText());
}
+ // Selector for the manual refresh button
+ refreshButton() {
+ return this.pageWrapper.find('[data-testid="manual-refresh"]').findButton().toSelector();
+ }
+
+ // Selector of the ARIA live region that contains the "Last updated" information for manual refresh
+ lastRefresh() {
+ return this.pageWrapper.find('[data-testid="manual-refresh"] [aria-live]').toSelector();
+ }
+
// Table - Header Buttons
protected async isTableHeaderButtonEnabled(index: number) {
const el = await this.browser.$(
diff --git a/test/e2e/table-editable.test.ts b/test/e2e/table-editable.test.ts
index d9230fd..66b565e 100644
--- a/test/e2e/table-editable.test.ts
+++ b/test/e2e/table-editable.test.ts
@@ -50,4 +50,13 @@ describe('Table - Inline Editing', () => {
expect(afterEditText).toBe('ACM');
})
);
+
+ test(
+ 'Can manually refresh table data',
+ setupTest(async page => {
+ await page.click(page.refreshButton());
+ await page.waitForVisible(page.lastRefresh());
+ await page.waitForAssertion(() => expect(page.getText(page.lastRefresh())).resolves.toContain('Last updated'));
+ })
+ );
});