Skip to content

Commit

Permalink
feat: Add last updated caption to the S3 selector.
Browse files Browse the repository at this point in the history
  • Loading branch information
orangevolon committed Jul 19, 2024
1 parent ea59ab1 commit 47eb27c
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 2 deletions.
1 change: 1 addition & 0 deletions pages/s3-resource-selector/data/i18n-strings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const i18nStrings: S3ResourceSelectorProps.I18nStrings = {
modalCancelButton: 'Cancel',
modalSubmitButton: 'Choose',
modalBreadcrumbRootItem: 'S3 buckets',
modalLastUpdatedText: 'Last updated at',

selectionBuckets: 'Buckets',
selectionObjects: 'Objects',
Expand Down
1 change: 1 addition & 0 deletions src/s3-resource-selector/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ export namespace S3ResourceSelectorProps {
modalCancelButton?: string;
modalSubmitButton?: string;
modalBreadcrumbRootItem?: string;
modalLastUpdatedText?: string;

selectionBuckets?: string;
selectionObjects?: string;
Expand Down
48 changes: 46 additions & 2 deletions src/s3-resource-selector/s3-modal/basic-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import { S3ResourceSelectorProps } from '../interfaces';
import { EmptyState } from './empty-state';
import { ComponentFormatFunction } from '../../i18n/context';
import { useStableCallback } from '@cloudscape-design/component-toolkit/internal';
import InternalSpaceBetween from '../../space-between/internal';
import LiveRegion from '../../internal/components/live-region';
import InternalBox from '../../box/internal';
import formatDateLocalized from '../../internal/utils/date-time/format-date-localized';

interface BasicS3TableStrings<T> {
labelRefresh?: string;
Expand All @@ -25,6 +29,7 @@ interface BasicS3TableStrings<T> {
filteringAriaLabel?: string;
filteringClearAriaLabel?: string;
filteringCounterText?: S3ResourceSelectorProps.I18nStrings['filteringCounterText'];
lastUpdatedText?: string;
emptyText?: string;
noMatchTitle?: string;
noMatchSubtitle?: string;
Expand All @@ -49,7 +54,7 @@ interface BasicS3TableProps<T> {
export function getSharedI18Strings(
i18n: ComponentFormatFunction<'s3-resource-selector'>,
i18nStrings: S3ResourceSelectorProps.I18nStrings | undefined
) {
): BasicS3TableStrings<unknown> {
return {
filteringCounterText: i18n(
'i18nStrings.filteringCounterText',
Expand All @@ -62,6 +67,7 @@ export function getSharedI18Strings(
noMatchSubtitle: i18n('i18nStrings.filteringCantFindMatch', i18nStrings?.filteringCantFindMatch),
clearFilterButtonText: i18n('i18nStrings.clearFilterButtonText', i18nStrings?.clearFilterButtonText),
filteringClearAriaLabel: i18nStrings?.labelClearFilter,
lastUpdatedText: i18nStrings?.modalLastUpdatedText,
};
}

Expand All @@ -78,13 +84,15 @@ export function BasicS3Table<T>({
}: BasicS3TableProps<T>) {
const [loading, setLoading] = useState(false);
const [allItems, setAllItems] = useState<ReadonlyArray<T>>([]);
const [lastUpdated, setLastUpdated] = useState<Date>();
const textFilterRef = useRef<TextFilterProps.Ref>(null);
const onSelectLatest = useStableCallback(onSelect);

function loadData() {
setLoading(true);
fetchData()
.then(items => {
setLastUpdated(new Date());
setAllItems(items);
setLoading(false);
})
Expand Down Expand Up @@ -140,7 +148,9 @@ export function BasicS3Table<T>({
<InternalHeader
variant={isVisualRefresh ? 'h3' : 'h2'}
headingTagOverride={'h3'}
actions={<InternalButton iconName="refresh" ariaLabel={i18nStrings.labelRefresh} onClick={loadData} />}
actions={
<InternalHeaderActions<T> fetchData={fetchData} i18nStrings={i18nStrings} lastUpdated={lastUpdated} />
}
counter={selectedItem ? `(1/${allItems.length})` : `(${allItems.length})`}
>
{i18nStrings.header}
Expand Down Expand Up @@ -170,3 +180,37 @@ export function BasicS3Table<T>({
/>
);
}

interface InternalHeaderActionsProps<T> {
fetchData: BasicS3TableProps<T>['fetchData'];
i18nStrings: BasicS3TableProps<T>['i18nStrings'];
lastUpdated: Date | undefined;
}

export function InternalHeaderActions<T>({ i18nStrings, fetchData, lastUpdated }: InternalHeaderActionsProps<T>) {
function getLastUpdated() {
if (!lastUpdated || !i18nStrings.lastUpdatedText) {
return null;
}

return (

Check warning on line 196 in src/s3-resource-selector/s3-modal/basic-table.tsx

View check run for this annotation

Codecov / codecov/patch

src/s3-resource-selector/s3-modal/basic-table.tsx#L196

Added line #L196 was not covered by tests
<LiveRegion visible={true}>
<InternalBox textAlign="right" color="text-status-inactive">
{i18nStrings.lastUpdatedText}
<br />
{formatDateLocalized({
date: lastUpdated.toString(),
isDateOnly: false,
})}
</InternalBox>
</LiveRegion>
);
}

return (
<InternalSpaceBetween size="xs" direction="horizontal" alignItems="center">
{getLastUpdated()}
<InternalButton iconName="refresh" ariaLabel={i18nStrings.labelRefresh} onClick={fetchData} />
</InternalSpaceBetween>
);
}

0 comments on commit 47eb27c

Please sign in to comment.