Skip to content

Commit

Permalink
Merge pull request #349 from IFRCGo/project/2023-dec-release
Browse files Browse the repository at this point in the history
2023 December Release
  • Loading branch information
samshara authored Dec 13, 2023
2 parents 96ad189 + faf5904 commit 8aa80f8
Show file tree
Hide file tree
Showing 80 changed files with 2,329 additions and 919 deletions.
1 change: 1 addition & 0 deletions src/App/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1942,6 +1942,7 @@ const preparednessGlobalCatalogue = customWrapRoute({
},
});

// FIXME: update name to `preparednessOperationalLearning`
const preparednessGlobalOperational = customWrapRoute({
parent: preparednessLayout,
path: 'operational-learning',
Expand Down
6 changes: 3 additions & 3 deletions src/components/DateOutput/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { useMemo } from 'react';
import { _cs } from '@togglecorp/fujs';
import { formatDate } from '#utils/common';
import { DateLike, formatDate } from '#utils/common';

import styles from './styles.module.css';

export interface Props {
className?: string;
value?: string | number | null;
value: DateLike | undefined | null;
format?: string;
invalidText?: React.ReactNode;
}

function DateOutput(props: Props) {
const {
value,
format = 'yyyy-MM-dd',
format,
className,
invalidText,
} = props;
Expand Down
2 changes: 1 addition & 1 deletion src/components/MapPopup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ function MapPopup(props: Props) {
// eslint-disable-next-line react/jsx-props-no-spreading
{...containerProps}
className={styles.container}
ellipsizeHeading
withoutWrapInHeading
childrenContainerClassName={_cs(styles.content, childrenContainerClassName)}
withHeaderBorder
withInternalPadding
Expand Down
43 changes: 43 additions & 0 deletions src/components/Table/ColumnShortcuts/TimelineHeader/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import DateOutput from '#components/DateOutput';
import { _cs } from '@togglecorp/fujs';

import HeaderCell, { HeaderCellProps } from '../../HeaderCell';

import styles from './styles.module.css';

export interface Props extends HeaderCellProps {
className?: string;
dateRange: {
start: Date,
end: Date,
} | undefined;
}

function TimelineHeader(props: Props) {
const {
className,
dateRange,
...otherProps
} = props;

return (
<HeaderCell
// eslint-disable-next-line react/jsx-props-no-spreading
{...otherProps}
className={_cs(styles.timelineHeader, className)}
titleClassName={styles.title}
title={(
<>
<DateOutput
value={dateRange?.start}
/>
<DateOutput
value={dateRange?.end}
/>
</>
)}
/>
);
}

export default TimelineHeader;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.timeline-header {
.title {
display: flex;
flex-grow: 1;
justify-content: space-between;
}
}
88 changes: 88 additions & 0 deletions src/components/Table/ColumnShortcuts/TimelineItem/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { _cs, isNotDefined } from '@togglecorp/fujs';

import Tooltip from '#components/Tooltip';
import TextOutput from '#components/TextOutput';

import { type DateLike, isValidDate } from '#utils/common';

import styles from './styles.module.css';

export interface Props {
className?: string;
startDate: DateLike | null | undefined;
endDate: DateLike | null | undefined;
dateRange: {
start: Date,
end: Date,
} | undefined;
}

function TimelineItem(props: Props) {
const {
className,
startDate,
endDate,
dateRange,
} = props;

if (isNotDefined(dateRange)) {
return null;
}

if (!isValidDate(startDate)) {
return null;
}

if (!isValidDate(endDate)) {
return null;
}

const domainWidth = dateRange.end.getTime() - dateRange.start.getTime();

const start = 1 - (dateRange.end.getTime() - new Date(startDate).getTime()) / domainWidth;
const end = (dateRange.end.getTime() - new Date(endDate).getTime()) / domainWidth;

const today = 1 - (dateRange.end.getTime() - new Date().getTime()) / domainWidth;

return (
<>
<div className={_cs(styles.timelineItem, className)}>
<div className={styles.startDateMarker} />
<div className={styles.endDateMarker} />
<div
className={styles.todayMarker}
style={{
left: `${100 * today}%`,
}}
/>
<div
className={styles.timelineProgress}
style={{
left: `${100 * start}%`,
right: `${100 * end}%`,
}}
/>
</div>
<Tooltip
description={(
<>
<TextOutput
valueType="date"
// FIXME: use translation
label="Start Date"
value={startDate}
/>
<TextOutput
// FIXME: use translation
label="End Date"
value={endDate}
valueType="date"
/>
</>
)}
/>
</>
);
}

export default TimelineItem;
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.timeline-item {
position: absolute;
top: 0;
left: var(--go-ui-spacing-sm);
width: calc(100% - 2 * var(--go-ui-spacing-sm));
height: 100%;

.timeline-progress {
position: absolute;
top: 50%;
transform: translateY(-50%);
border-radius: 0.25em;
background-color: var(--go-ui-color-primary-red);
height: 0.5rem;
}

.today-marker {
position: absolute;
border-left: var(--go-ui-width-separator-sm) dashed var(--go-ui-color-primary-blue);
height: 100%;
}

.start-date-marker {
position: absolute;
left: 0;
border-left: var(--go-ui-width-separator-sm) dashed var(--go-ui-color-separator);
height: 100%;
}

.end-date-marker {
position: absolute;
right: 0;
border-left: var(--go-ui-width-separator-sm) dashed var(--go-ui-color-separator);
height: 100%;
}
}
82 changes: 57 additions & 25 deletions src/components/Table/ColumnShortcuts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,13 @@ import {
randomString,
} from '@togglecorp/fujs';

import DateOutput from '#components/DateOutput';
import { type Props as DateOutputProps } from '#components/DateOutput';
import DateRangeOutput from '#components/DateRangeOutput';
import { type Props as DateRangeOutputProps } from '#components/DateRangeOutput';
import NumberOutput from '#components/NumberOutput';
import { type Props as NumberOutputProps } from '#components/NumberOutput';
import BooleanOutput from '#components/BooleanOutput';
import { type Props as BooleanOutputProps } from '#components/BooleanOutput';
import ProgressBar from '#components/ProgressBar';
import { type Props as ProgressBarProps } from '#components/ProgressBar';
import ReducedListDisplay, {
Props as ReducedListDisplayProps,
} from '#components/ReducedListDisplay';
import { type Props as LinkProps } from '#components/Link';
import Link from '#components/Link';
import DateOutput, { type Props as DateOutputProps } from '#components/DateOutput';
import DateRangeOutput, { type Props as DateRangeOutputProps } from '#components/DateRangeOutput';
import NumberOutput, { type Props as NumberOutputProps } from '#components/NumberOutput';
import BooleanOutput, { type Props as BooleanOutputProps } from '#components/BooleanOutput';
import ProgressBar, { type Props as ProgressBarProps } from '#components/ProgressBar';
import ReducedListDisplay, { Props as ReducedListDisplayProps } from '#components/ReducedListDisplay';
import Link, { type Props as LinkProps } from '#components/Link';
import { numericIdSelector } from '#utils/selectors';
import { type GoApiResponse } from '#utils/restRequest';

Expand All @@ -38,6 +30,8 @@ import { type ExpandButtonProps } from './ExpandButton';
import ExpansionIndicator from './ExpansionIndicator';
import { type Props as ExpansionIndicatorProps } from './ExpansionIndicator';
import CountryLink from './CountryLink';
import TimelineItem, { type Props as TimelineItemProps } from './TimelineItem';
import TimelineHeader, { type Props as TimelineHeaderProps } from './TimelineHeader';

import type { Props as CountryLinkProps } from './CountryLink';
import RegionLink from './RegionLink';
Expand Down Expand Up @@ -383,10 +377,10 @@ export function createExpandColumn<D, K>(
return item;
}

export function createExpansionIndicatorColumn<D, K>(
export function createExpansionIndicatorColumn<DATUM, KEY>(
isExpanded?: boolean,
) {
const item: Column<D, K, ExpansionIndicatorProps, HeaderCellProps> = {
const item: Column<DATUM, KEY, ExpansionIndicatorProps, HeaderCellProps> = {
id: randomString(),
title: '',
headerCellRenderer: HeaderCell,
Expand Down Expand Up @@ -417,14 +411,14 @@ export function createExpansionIndicatorColumn<D, K>(
return item;
}

export function createElementColumn<DATA, KEY, ELEMENT_PROPS>(
export function createElementColumn<DATUM, KEY, ELEMENT_PROPS>(
id: string,
title: string,
renderer: React.ComponentType<ELEMENT_PROPS>,
rendererParams: (key: KEY, datum: DATA) => ELEMENT_PROPS,
options?: Options<DATA, KEY, ELEMENT_PROPS, HeaderCellProps>,
rendererParams: (key: KEY, datum: DATUM) => ELEMENT_PROPS,
options?: Options<DATUM, KEY, ELEMENT_PROPS, HeaderCellProps>,
) {
const item: Column<DATA, KEY, ELEMENT_PROPS, HeaderCellProps> = {
const item: Column<DATUM, KEY, ELEMENT_PROPS, HeaderCellProps> = {
id,
title,
headerCellRenderer: HeaderCell,
Expand All @@ -446,12 +440,50 @@ export function createElementColumn<DATA, KEY, ELEMENT_PROPS>(
return item;
}

export function createActionColumn<D, K>(
export function createTimelineColumn<DATUM, KEY>(
id: string,
rendererParams: (datum: D) => TableActionsProps,
options?: Options<D, K, TableActionsProps, HeaderCellProps>,
dateRange: {
start: Date,
end: Date,
} | undefined,
rendererParams: (datum: DATUM) => Omit<TimelineItemProps, 'dateRange'>,
options?: Options<DATUM, KEY, TableActionsProps, HeaderCellProps>,
) {
const item: Column<DATUM, KEY, TimelineItemProps, TimelineHeaderProps> = {
id,
title: '',
headerCellRenderer: TimelineHeader,
headerCellRendererParams: {
dateRange,
sortable: options?.sortable,
},
cellRenderer: TimelineItem,
cellRendererParams: (_, datum) => ({
dateRange,
...rendererParams(datum),
}),
headerContainerClassName: options?.headerContainerClassName,
cellRendererClassName: options?.cellRendererClassName,
columnClassName: options?.columnClassName,
headerCellRendererClassName: options?.headerCellRendererClassName,
cellContainerClassName: _cs(
options?.cellContainerClassName,
styles.timelineCellContainer,
),
columnWidth: options?.columnWidth,
columnStretch: options?.columnStretch,
columnStyle: options?.columnStyle,
};

return item;
}

export function createActionColumn<DATUM, KEY>(
id: string,
rendererParams: (datum: DATUM) => TableActionsProps,
options?: Options<DATUM, KEY, TableActionsProps, HeaderCellProps>,
) {
const item: Column<D, K, TableActionsProps, HeaderCellProps> = {
const item: Column<DATUM, KEY, TableActionsProps, HeaderCellProps> = {
id,
title: '',
headerCellRenderer: HeaderCell,
Expand Down
4 changes: 4 additions & 0 deletions src/components/Table/ColumnShortcuts/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@
.expansion-indicator-cell-container {
position: relative;
}

.timeline-cell-container {
position: relative;
}
1 change: 1 addition & 0 deletions src/components/Table/HeaderCell/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ function HeaderCell(props: HeaderCellProps) {
</div>
{infoTitle && infoDescription && (
<InfoPopup
className={styles.infoPopupIcon}
title={infoTitle}
description={infoDescription}
/>
Expand Down
5 changes: 5 additions & 0 deletions src/components/Table/HeaderCell/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
}

.icon {
flex-shrink: 0;
font-size: var(--go-ui-height-icon-multiplier);
}

.info-popup-icon {
flex-shrink: 0;
}
}
2 changes: 1 addition & 1 deletion src/components/Table/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export interface BaseHeader {
name: string;
index: number;

title?: string;
title?: React.ReactNode;
}

export interface BaseCell {
Expand Down
2 changes: 1 addition & 1 deletion src/components/TextArea/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import InputContainer, { Props as InputContainerProps } from '../InputContainer'
import RawTextArea, { Props as RawTextAreaProps } from '../RawTextArea';

const BULLET = '•';
const KEY_ENTER = 'ENTER';
const KEY_ENTER = 'Enter';

type InheritedProps<N> = (Omit<InputContainerProps, 'input'> & Omit<RawTextAreaProps<N>, 'type'>);
export interface Props<T> extends InheritedProps<T> {
Expand Down
Loading

0 comments on commit 8aa80f8

Please sign in to comment.