mirror of
https://github.com/status-im/spiff-arena.git
synced 2025-02-04 22:23:56 +00:00
added a DateAndTimeService on the frontend to get those functions out of helpers w/ burnettk (#560)
Co-authored-by: jasquat <jasquat@users.noreply.github.com>
This commit is contained in:
parent
54b7c5c3ec
commit
5907339918
@ -2,7 +2,8 @@ import { useEffect, useState } from 'react';
|
|||||||
|
|
||||||
import HttpService from '../services/HttpService';
|
import HttpService from '../services/HttpService';
|
||||||
import { User } from '../interfaces';
|
import { User } from '../interfaces';
|
||||||
import { refreshAtInterval, REFRESH_TIMEOUT_SECONDS } from '../helpers';
|
import { refreshAtInterval } from '../helpers';
|
||||||
|
import DateAndTimeService from '../services/DateAndTimeService';
|
||||||
|
|
||||||
async function sha256(message: string) {
|
async function sha256(message: string) {
|
||||||
// encode as UTF-8
|
// encode as UTF-8
|
||||||
@ -48,7 +49,7 @@ export default function ActiveUsers() {
|
|||||||
|
|
||||||
return refreshAtInterval(
|
return refreshAtInterval(
|
||||||
15,
|
15,
|
||||||
REFRESH_TIMEOUT_SECONDS,
|
DateAndTimeService.REFRESH_TIMEOUT_SECONDS,
|
||||||
updateActiveUsers,
|
updateActiveUsers,
|
||||||
unregisterUser
|
unregisterUser
|
||||||
);
|
);
|
||||||
|
@ -7,13 +7,13 @@ import { Link, useSearchParams } from 'react-router-dom';
|
|||||||
import PaginationForTable from './PaginationForTable';
|
import PaginationForTable from './PaginationForTable';
|
||||||
import ProcessBreadcrumb from './ProcessBreadcrumb';
|
import ProcessBreadcrumb from './ProcessBreadcrumb';
|
||||||
import {
|
import {
|
||||||
convertSecondsToFormattedDateTime,
|
|
||||||
getPageInfoFromSearchParams,
|
getPageInfoFromSearchParams,
|
||||||
modifyProcessIdentifierForPathParam,
|
modifyProcessIdentifierForPathParam,
|
||||||
} from '../helpers';
|
} from '../helpers';
|
||||||
import HttpService from '../services/HttpService';
|
import HttpService from '../services/HttpService';
|
||||||
import { FormatProcessModelDisplayName } from './MiniComponents';
|
import { FormatProcessModelDisplayName } from './MiniComponents';
|
||||||
import { MessageInstance } from '../interfaces';
|
import { MessageInstance } from '../interfaces';
|
||||||
|
import DateAndTimeService from '../services/DateAndTimeService';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
processInstanceId?: number;
|
processInstanceId?: number;
|
||||||
@ -128,7 +128,9 @@ export default function MessageInstanceList({ processInstanceId }: OwnProps) {
|
|||||||
</td>
|
</td>
|
||||||
<td>{row.status}</td>
|
<td>{row.status}</td>
|
||||||
<td>
|
<td>
|
||||||
{convertSecondsToFormattedDateTime(row.created_at_in_seconds)}
|
{DateAndTimeService.convertSecondsToFormattedDateTime(
|
||||||
|
row.created_at_in_seconds
|
||||||
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
|
@ -36,22 +36,13 @@ import {
|
|||||||
DATE_FORMAT_FOR_DISPLAY,
|
DATE_FORMAT_FOR_DISPLAY,
|
||||||
} from '../config';
|
} from '../config';
|
||||||
import {
|
import {
|
||||||
convertDateAndTimeStringsToSeconds,
|
|
||||||
convertDateObjectToFormattedHoursMinutes,
|
|
||||||
convertSecondsToFormattedDateString,
|
|
||||||
convertSecondsToFormattedDateTime,
|
|
||||||
convertSecondsToFormattedTimeHoursMinutes,
|
|
||||||
getKeyByValue,
|
getKeyByValue,
|
||||||
getLastMilestoneFromProcessInstance,
|
getLastMilestoneFromProcessInstance,
|
||||||
getPageInfoFromSearchParams,
|
getPageInfoFromSearchParams,
|
||||||
modifyProcessIdentifierForPathParam,
|
modifyProcessIdentifierForPathParam,
|
||||||
refreshAtInterval,
|
refreshAtInterval,
|
||||||
REFRESH_INTERVAL_SECONDS,
|
|
||||||
REFRESH_TIMEOUT_SECONDS,
|
|
||||||
titleizeString,
|
titleizeString,
|
||||||
truncateString,
|
truncateString,
|
||||||
formatDurationForDisplay,
|
|
||||||
formatDateTime,
|
|
||||||
} from '../helpers';
|
} from '../helpers';
|
||||||
import { useUriListForPermissions } from '../hooks/UriListForPermissions';
|
import { useUriListForPermissions } from '../hooks/UriListForPermissions';
|
||||||
|
|
||||||
@ -86,6 +77,7 @@ import { Can } from '../contexts/Can';
|
|||||||
import TableCellWithTimeAgoInWords from './TableCellWithTimeAgoInWords';
|
import TableCellWithTimeAgoInWords from './TableCellWithTimeAgoInWords';
|
||||||
import UserService from '../services/UserService';
|
import UserService from '../services/UserService';
|
||||||
import Filters from './Filters';
|
import Filters from './Filters';
|
||||||
|
import DateAndTimeService from '../services/DateAndTimeService';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
filtersEnabled?: boolean;
|
filtersEnabled?: boolean;
|
||||||
@ -443,13 +435,15 @@ export default function ProcessInstanceListTable({
|
|||||||
const timeFunctionToCall =
|
const timeFunctionToCall =
|
||||||
dateParametersToAlwaysFilterBy[reportFilter.field_name][1];
|
dateParametersToAlwaysFilterBy[reportFilter.field_name][1];
|
||||||
if (reportFilter.field_value) {
|
if (reportFilter.field_value) {
|
||||||
const dateString = convertSecondsToFormattedDateString(
|
const dateString =
|
||||||
reportFilter.field_value as any
|
DateAndTimeService.convertSecondsToFormattedDateString(
|
||||||
);
|
reportFilter.field_value as any
|
||||||
|
);
|
||||||
dateFunctionToCall(dateString);
|
dateFunctionToCall(dateString);
|
||||||
const timeString = convertSecondsToFormattedTimeHoursMinutes(
|
const timeString =
|
||||||
reportFilter.field_value as any
|
DateAndTimeService.convertSecondsToFormattedTimeHoursMinutes(
|
||||||
);
|
reportFilter.field_value as any
|
||||||
|
);
|
||||||
timeFunctionToCall(timeString);
|
timeFunctionToCall(timeString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -566,8 +560,8 @@ export default function ProcessInstanceListTable({
|
|||||||
checkFiltersAndRun();
|
checkFiltersAndRun();
|
||||||
if (autoReload) {
|
if (autoReload) {
|
||||||
clearRefreshRef.current = refreshAtInterval(
|
clearRefreshRef.current = refreshAtInterval(
|
||||||
REFRESH_INTERVAL_SECONDS,
|
DateAndTimeService.REFRESH_INTERVAL_SECONDS,
|
||||||
REFRESH_TIMEOUT_SECONDS,
|
DateAndTimeService.REFRESH_TIMEOUT_SECONDS,
|
||||||
checkFiltersAndRun
|
checkFiltersAndRun
|
||||||
);
|
);
|
||||||
return clearRefreshRef.current;
|
return clearRefreshRef.current;
|
||||||
@ -627,19 +621,22 @@ export default function ProcessInstanceListTable({
|
|||||||
// with the use of the setErrorMessageSafely function. we are not sure why the context not
|
// with the use of the setErrorMessageSafely function. we are not sure why the context not
|
||||||
// changing still causes things to rerender when we call its setter without our extra check.
|
// changing still causes things to rerender when we call its setter without our extra check.
|
||||||
const calculateStartAndEndSeconds = (validate: boolean = true) => {
|
const calculateStartAndEndSeconds = (validate: boolean = true) => {
|
||||||
const startFromSeconds = convertDateAndTimeStringsToSeconds(
|
const startFromSeconds =
|
||||||
startFromDate,
|
DateAndTimeService.convertDateAndTimeStringsToSeconds(
|
||||||
startFromTime || '00:00:00'
|
startFromDate,
|
||||||
);
|
startFromTime || '00:00:00'
|
||||||
const startToSeconds = convertDateAndTimeStringsToSeconds(
|
);
|
||||||
startToDate,
|
const startToSeconds =
|
||||||
startToTime || '00:00:00'
|
DateAndTimeService.convertDateAndTimeStringsToSeconds(
|
||||||
);
|
startToDate,
|
||||||
const endFromSeconds = convertDateAndTimeStringsToSeconds(
|
startToTime || '00:00:00'
|
||||||
endFromDate,
|
);
|
||||||
endFromTime || '00:00:00'
|
const endFromSeconds =
|
||||||
);
|
DateAndTimeService.convertDateAndTimeStringsToSeconds(
|
||||||
const endToSeconds = convertDateAndTimeStringsToSeconds(
|
endFromDate,
|
||||||
|
endFromTime || '00:00:00'
|
||||||
|
);
|
||||||
|
const endToSeconds = DateAndTimeService.convertDateAndTimeStringsToSeconds(
|
||||||
endToDate,
|
endToDate,
|
||||||
endToTime || '00:00:00'
|
endToTime || '00:00:00'
|
||||||
);
|
);
|
||||||
@ -872,7 +869,9 @@ export default function ProcessInstanceListTable({
|
|||||||
onChange={(dateChangeEvent: any) => {
|
onChange={(dateChangeEvent: any) => {
|
||||||
if (!initialDate && !initialTime) {
|
if (!initialDate && !initialTime) {
|
||||||
onChangeTimeFunction(
|
onChangeTimeFunction(
|
||||||
convertDateObjectToFormattedHoursMinutes(new Date())
|
DateAndTimeService.convertDateObjectToFormattedHoursMinutes(
|
||||||
|
new Date()
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
onChangeDateFunction(dateChangeEvent.srcElement.value);
|
onChangeDateFunction(dateChangeEvent.srcElement.value);
|
||||||
@ -1691,7 +1690,7 @@ export default function ProcessInstanceListTable({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const formatSecondsForDisplay = (_row: ProcessInstance, seconds: any) => {
|
const formatSecondsForDisplay = (_row: ProcessInstance, seconds: any) => {
|
||||||
return convertSecondsToFormattedDateTime(seconds) || '-';
|
return DateAndTimeService.convertSecondsToFormattedDateTime(seconds) || '-';
|
||||||
};
|
};
|
||||||
const defaultFormatter = (_row: ProcessInstance, value: any) => {
|
const defaultFormatter = (_row: ProcessInstance, value: any) => {
|
||||||
return value;
|
return value;
|
||||||
@ -1710,8 +1709,8 @@ export default function ProcessInstanceListTable({
|
|||||||
last_milestone_bpmn_name: formatLastMilestone,
|
last_milestone_bpmn_name: formatLastMilestone,
|
||||||
};
|
};
|
||||||
const displayTypeFormatters: Record<string, any> = {
|
const displayTypeFormatters: Record<string, any> = {
|
||||||
date_time: formatDateTime,
|
date_time: DateAndTimeService.formatDateTime,
|
||||||
duration: formatDurationForDisplay,
|
duration: DateAndTimeService.formatDurationForDisplay,
|
||||||
};
|
};
|
||||||
const columnAccessor = column.accessor as keyof ProcessInstance;
|
const columnAccessor = column.accessor as keyof ProcessInstance;
|
||||||
const formatter = column.display_type
|
const formatter = column.display_type
|
||||||
|
@ -15,7 +15,6 @@ import { createSearchParams, Link, useSearchParams } from 'react-router-dom';
|
|||||||
import PaginationForTable from './PaginationForTable';
|
import PaginationForTable from './PaginationForTable';
|
||||||
import {
|
import {
|
||||||
getPageInfoFromSearchParams,
|
getPageInfoFromSearchParams,
|
||||||
convertSecondsToFormattedDateTime,
|
|
||||||
selectKeysFromSearchParams,
|
selectKeysFromSearchParams,
|
||||||
} from '../helpers';
|
} from '../helpers';
|
||||||
import HttpService from '../services/HttpService';
|
import HttpService from '../services/HttpService';
|
||||||
@ -32,6 +31,7 @@ import {
|
|||||||
childrenForErrorObject,
|
childrenForErrorObject,
|
||||||
errorForDisplayFromProcessInstanceErrorDetail,
|
errorForDisplayFromProcessInstanceErrorDetail,
|
||||||
} from './ErrorDisplay';
|
} from './ErrorDisplay';
|
||||||
|
import DateAndTimeService from '../services/DateAndTimeService';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
variant: string; // 'all' or 'for-me'
|
variant: string; // 'all' or 'for-me'
|
||||||
@ -306,7 +306,11 @@ export default function ProcessInstanceLogList({
|
|||||||
}
|
}
|
||||||
|
|
||||||
let timestampComponent = (
|
let timestampComponent = (
|
||||||
<td>{convertSecondsToFormattedDateTime(logEntry.timestamp)}</td>
|
<td>
|
||||||
|
{DateAndTimeService.convertSecondsToFormattedDateTime(
|
||||||
|
logEntry.timestamp
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
);
|
);
|
||||||
if (logEntry.spiff_task_guid && logEntry.event_type !== 'task_cancelled') {
|
if (logEntry.spiff_task_guid && logEntry.event_type !== 'task_cancelled') {
|
||||||
timestampComponent = (
|
timestampComponent = (
|
||||||
@ -317,7 +321,9 @@ export default function ProcessInstanceLogList({
|
|||||||
to={`${processInstanceShowPageBaseUrl}/${logEntry.process_instance_id}/${logEntry.spiff_task_guid}`}
|
to={`${processInstanceShowPageBaseUrl}/${logEntry.process_instance_id}/${logEntry.spiff_task_guid}`}
|
||||||
title="View state when task was completed"
|
title="View state when task was completed"
|
||||||
>
|
>
|
||||||
{convertSecondsToFormattedDateTime(logEntry.timestamp)}
|
{DateAndTimeService.convertSecondsToFormattedDateTime(
|
||||||
|
logEntry.timestamp
|
||||||
|
)}
|
||||||
</Link>
|
</Link>
|
||||||
</td>
|
</td>
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { TimeAgo } from '../helpers/timeago';
|
import { TimeAgo } from '../helpers/timeago';
|
||||||
import { convertSecondsToFormattedDateTime } from '../helpers';
|
import DateAndTimeService from '../services/DateAndTimeService';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
timeInSeconds: number;
|
timeInSeconds: number;
|
||||||
@ -16,7 +16,10 @@ export default function TableCellWithTimeAgoInWords({
|
|||||||
return (
|
return (
|
||||||
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
|
||||||
<td
|
<td
|
||||||
title={convertSecondsToFormattedDateTime(timeInSeconds) || '-'}
|
title={
|
||||||
|
DateAndTimeService.convertSecondsToFormattedDateTime(timeInSeconds) ||
|
||||||
|
'-'
|
||||||
|
}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
onKeyDown={onKeyDown}
|
onKeyDown={onKeyDown}
|
||||||
>
|
>
|
||||||
|
@ -6,18 +6,16 @@ import { TimeAgo } from '../helpers/timeago';
|
|||||||
import UserService from '../services/UserService';
|
import UserService from '../services/UserService';
|
||||||
import PaginationForTable from './PaginationForTable';
|
import PaginationForTable from './PaginationForTable';
|
||||||
import {
|
import {
|
||||||
convertSecondsToFormattedDateTime,
|
|
||||||
getPageInfoFromSearchParams,
|
getPageInfoFromSearchParams,
|
||||||
modifyProcessIdentifierForPathParam,
|
modifyProcessIdentifierForPathParam,
|
||||||
refreshAtInterval,
|
refreshAtInterval,
|
||||||
REFRESH_INTERVAL_SECONDS,
|
|
||||||
REFRESH_TIMEOUT_SECONDS,
|
|
||||||
} from '../helpers';
|
} from '../helpers';
|
||||||
import HttpService from '../services/HttpService';
|
import HttpService from '../services/HttpService';
|
||||||
import { PaginationObject, ProcessInstanceTask, Task } from '../interfaces';
|
import { PaginationObject, ProcessInstanceTask, Task } from '../interfaces';
|
||||||
import TableCellWithTimeAgoInWords from './TableCellWithTimeAgoInWords';
|
import TableCellWithTimeAgoInWords from './TableCellWithTimeAgoInWords';
|
||||||
import CustomForm from './CustomForm';
|
import CustomForm from './CustomForm';
|
||||||
import InstructionsForEndUser from './InstructionsForEndUser';
|
import InstructionsForEndUser from './InstructionsForEndUser';
|
||||||
|
import DateAndTimeService from '../services/DateAndTimeService';
|
||||||
|
|
||||||
const PER_PAGE_FOR_TASKS_ON_HOME_PAGE = 5;
|
const PER_PAGE_FOR_TASKS_ON_HOME_PAGE = 5;
|
||||||
|
|
||||||
@ -100,8 +98,8 @@ export default function TaskListTable({
|
|||||||
getTasks();
|
getTasks();
|
||||||
if (autoReload) {
|
if (autoReload) {
|
||||||
return refreshAtInterval(
|
return refreshAtInterval(
|
||||||
REFRESH_INTERVAL_SECONDS,
|
DateAndTimeService.REFRESH_INTERVAL_SECONDS,
|
||||||
REFRESH_TIMEOUT_SECONDS,
|
DateAndTimeService.REFRESH_TIMEOUT_SECONDS,
|
||||||
getTasks
|
getTasks
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -288,7 +286,7 @@ export default function TaskListTable({
|
|||||||
if (showDateStarted) {
|
if (showDateStarted) {
|
||||||
rowElements.push(
|
rowElements.push(
|
||||||
<td>
|
<td>
|
||||||
{convertSecondsToFormattedDateTime(
|
{DateAndTimeService.convertSecondsToFormattedDateTime(
|
||||||
processInstanceTask.created_at_in_seconds
|
processInstanceTask.created_at_in_seconds
|
||||||
) || '-'}
|
) || '-'}
|
||||||
</td>
|
</td>
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
convertSecondsToFormattedDateString,
|
|
||||||
isANumber,
|
isANumber,
|
||||||
slugifyString,
|
slugifyString,
|
||||||
underscorizeString,
|
underscorizeString,
|
||||||
recursivelyChangeNullAndUndefined,
|
recursivelyChangeNullAndUndefined,
|
||||||
formatDurationForDisplay,
|
|
||||||
} from './helpers';
|
} from './helpers';
|
||||||
|
|
||||||
test('it can slugify a string', () => {
|
test('it can slugify a string', () => {
|
||||||
@ -19,11 +17,6 @@ test('it can underscorize a string', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('it can keep the correct date when converting seconds to date', () => {
|
|
||||||
const dateString = convertSecondsToFormattedDateString(1666325400);
|
|
||||||
expect(dateString).toEqual('2022-10-21');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('it can validate numeric values', () => {
|
test('it can validate numeric values', () => {
|
||||||
expect(isANumber('11')).toEqual(true);
|
expect(isANumber('11')).toEqual(true);
|
||||||
expect(isANumber('hey')).toEqual(false);
|
expect(isANumber('hey')).toEqual(false);
|
||||||
@ -102,13 +95,3 @@ test('it can replace null values in object with undefined', () => {
|
|||||||
expect(result.contacts.awesome).toEqual(false);
|
expect(result.contacts.awesome).toEqual(false);
|
||||||
expect(result.contacts.info).toEqual('');
|
expect(result.contacts.info).toEqual('');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('it can properly format a duration', () => {
|
|
||||||
expect(formatDurationForDisplay(null, '0')).toEqual('0s');
|
|
||||||
expect(formatDurationForDisplay(null, '60')).toEqual('1m');
|
|
||||||
expect(formatDurationForDisplay(null, '65')).toEqual('1m 5s');
|
|
||||||
expect(formatDurationForDisplay(null, 65)).toEqual('1m 5s');
|
|
||||||
expect(formatDurationForDisplay(null, 86500)).toEqual('1d 1m 40s');
|
|
||||||
expect(formatDurationForDisplay(null, 2629746)).toEqual('30d 10h 29m 6s');
|
|
||||||
expect(formatDurationForDisplay(null, 31536765)).toEqual('365d 12m 45s');
|
|
||||||
});
|
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
import { Duration, format } from 'date-fns';
|
|
||||||
import { Buffer } from 'buffer';
|
import { Buffer } from 'buffer';
|
||||||
|
|
||||||
import {
|
|
||||||
DATE_TIME_FORMAT,
|
|
||||||
DATE_FORMAT,
|
|
||||||
TIME_FORMAT_HOURS_MINUTES,
|
|
||||||
} from './config';
|
|
||||||
import { ProcessInstance } from './interfaces';
|
import { ProcessInstance } from './interfaces';
|
||||||
|
|
||||||
export const DEFAULT_PER_PAGE = 50;
|
export const DEFAULT_PER_PAGE = 50;
|
||||||
@ -87,128 +81,6 @@ export const titleizeString = (string: any) => {
|
|||||||
return capitalizeFirstLetter((string || '').replaceAll('_', ' '));
|
return capitalizeFirstLetter((string || '').replaceAll('_', ' '));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const convertDateToSeconds = (
|
|
||||||
date: any,
|
|
||||||
onChangeFunction: any = null
|
|
||||||
) => {
|
|
||||||
let dateInSeconds = date;
|
|
||||||
if (date !== null) {
|
|
||||||
let dateInMilliseconds = date;
|
|
||||||
if (typeof date.getTime === 'function') {
|
|
||||||
dateInMilliseconds = date.getTime();
|
|
||||||
}
|
|
||||||
dateInSeconds = Math.floor(dateInMilliseconds / 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onChangeFunction) {
|
|
||||||
onChangeFunction(dateInSeconds);
|
|
||||||
} else {
|
|
||||||
return dateInSeconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const convertDateObjectToFormattedString = (dateObject: Date) => {
|
|
||||||
if (dateObject) {
|
|
||||||
return format(dateObject, DATE_FORMAT);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const dateStringToYMDFormat = (dateString: string) => {
|
|
||||||
if (dateString && dateString.match(/^\d{2}-\d{2}-\d{4}$/)) {
|
|
||||||
if (DATE_FORMAT.startsWith('dd')) {
|
|
||||||
const d = dateString.split('-');
|
|
||||||
return `${d[2]}-${d[1]}-${d[0]}`;
|
|
||||||
}
|
|
||||||
if (DATE_FORMAT.startsWith('MM')) {
|
|
||||||
const d = dateString.split('-');
|
|
||||||
return `${d[2]}-${d[0]}-${d[1]}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dateString;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const convertDateAndTimeStringsToDate = (
|
|
||||||
dateString: string,
|
|
||||||
timeString: string
|
|
||||||
) => {
|
|
||||||
if (dateString && timeString) {
|
|
||||||
return new Date(`${dateStringToYMDFormat(dateString)}T${timeString}`);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const convertDateAndTimeStringsToSeconds = (
|
|
||||||
dateString: string,
|
|
||||||
timeString: string
|
|
||||||
) => {
|
|
||||||
const dateObject = convertDateAndTimeStringsToDate(dateString, timeString);
|
|
||||||
if (dateObject) {
|
|
||||||
return convertDateToSeconds(dateObject);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const convertStringToDate = (dateString: string) => {
|
|
||||||
return convertDateAndTimeStringsToDate(dateString, '00:10:00');
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ymdDateStringToConfiguredFormat = (dateString: string) => {
|
|
||||||
const dateObject = convertStringToDate(dateString);
|
|
||||||
if (dateObject) {
|
|
||||||
return convertDateObjectToFormattedString(dateObject);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const convertSecondsToDateObject = (seconds: number) => {
|
|
||||||
if (seconds) {
|
|
||||||
return new Date(seconds * 1000);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const convertSecondsToFormattedDateTime = (seconds: number) => {
|
|
||||||
const dateObject = convertSecondsToDateObject(seconds);
|
|
||||||
if (dateObject) {
|
|
||||||
return format(dateObject, DATE_TIME_FORMAT);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const convertDateObjectToFormattedHoursMinutes = (dateObject: Date) => {
|
|
||||||
if (dateObject) {
|
|
||||||
return format(dateObject, TIME_FORMAT_HOURS_MINUTES);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const convertSecondsToFormattedTimeHoursMinutes = (seconds: number) => {
|
|
||||||
const dateObject = convertSecondsToDateObject(seconds);
|
|
||||||
if (dateObject) {
|
|
||||||
return convertDateObjectToFormattedHoursMinutes(dateObject);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const convertSecondsToFormattedDateString = (seconds: number) => {
|
|
||||||
const dateObject = convertSecondsToDateObject(seconds);
|
|
||||||
if (dateObject) {
|
|
||||||
return convertDateObjectToFormattedString(dateObject);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const convertDateStringToSeconds = (dateString: string) => {
|
|
||||||
const dateObject = convertStringToDate(dateString);
|
|
||||||
if (dateObject) {
|
|
||||||
return convertDateToSeconds(dateObject);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const objectIsEmpty = (obj: object) => {
|
export const objectIsEmpty = (obj: object) => {
|
||||||
return Object.keys(obj).length === 0;
|
return Object.keys(obj).length === 0;
|
||||||
};
|
};
|
||||||
@ -368,14 +240,6 @@ export const decodeBase64 = (data: string) => {
|
|||||||
return Buffer.from(data, 'base64').toString('ascii');
|
return Buffer.from(data, 'base64').toString('ascii');
|
||||||
};
|
};
|
||||||
|
|
||||||
const MINUTES_IN_HOUR = 60;
|
|
||||||
const SECONDS_IN_MINUTE = 60;
|
|
||||||
const SECONDS_IN_HOUR = MINUTES_IN_HOUR * SECONDS_IN_MINUTE;
|
|
||||||
const FOUR_HOURS_IN_SECONDS = SECONDS_IN_HOUR * 4;
|
|
||||||
|
|
||||||
export const REFRESH_INTERVAL_SECONDS = 5;
|
|
||||||
export const REFRESH_TIMEOUT_SECONDS = FOUR_HOURS_IN_SECONDS;
|
|
||||||
|
|
||||||
export const getLastMilestoneFromProcessInstance = (
|
export const getLastMilestoneFromProcessInstance = (
|
||||||
processInstance: ProcessInstance,
|
processInstance: ProcessInstance,
|
||||||
value: any
|
value: any
|
||||||
@ -402,61 +266,3 @@ export const getLastMilestoneFromProcessInstance = (
|
|||||||
}
|
}
|
||||||
return [valueToUse, truncatedValue];
|
return [valueToUse, truncatedValue];
|
||||||
};
|
};
|
||||||
|
|
||||||
// logic from https://stackoverflow.com/a/28510323/6090676
|
|
||||||
export const secondsToDuration = (secNum: number) => {
|
|
||||||
const days = Math.floor(secNum / 86400);
|
|
||||||
const hours = Math.floor(secNum / 3600) % 24;
|
|
||||||
const minutes = Math.floor(secNum / 60) % 60;
|
|
||||||
const seconds = secNum % 60;
|
|
||||||
|
|
||||||
const duration: Duration = {
|
|
||||||
days,
|
|
||||||
hours,
|
|
||||||
minutes,
|
|
||||||
seconds,
|
|
||||||
};
|
|
||||||
return duration;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const formatDurationForDisplay = (_row: any, value: any) => {
|
|
||||||
if (value === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
const duration = secondsToDuration(parseInt(value, 10));
|
|
||||||
const durationTimes = [];
|
|
||||||
if (duration.seconds !== undefined && duration.seconds > 0) {
|
|
||||||
durationTimes.unshift(`${duration.seconds}s`);
|
|
||||||
}
|
|
||||||
if (duration.minutes !== undefined && duration.minutes > 0) {
|
|
||||||
durationTimes.unshift(`${duration.minutes}m`);
|
|
||||||
}
|
|
||||||
if (duration.hours !== undefined && duration.hours > 0) {
|
|
||||||
durationTimes.unshift(`${duration.hours}h`);
|
|
||||||
}
|
|
||||||
if (duration.days !== undefined && duration.days > 0) {
|
|
||||||
durationTimes.unshift(`${duration.days}d`);
|
|
||||||
}
|
|
||||||
if (durationTimes.length < 1) {
|
|
||||||
durationTimes.push('0s');
|
|
||||||
}
|
|
||||||
return durationTimes.join(' ');
|
|
||||||
};
|
|
||||||
|
|
||||||
export const formatDateTime = (_row: any, value: any) => {
|
|
||||||
if (value === undefined || value === null) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
let dateInSeconds = value;
|
|
||||||
if (!isANumber(value)) {
|
|
||||||
const timeArgs = value.split('T');
|
|
||||||
dateInSeconds = convertDateAndTimeStringsToSeconds(
|
|
||||||
timeArgs[0],
|
|
||||||
timeArgs[1]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (dateInSeconds) {
|
|
||||||
return convertSecondsToFormattedDateTime(dateInSeconds);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
|
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { DATE_FORMAT_CARBON, DATE_FORMAT_FOR_DISPLAY } from '../../../config';
|
import { DATE_FORMAT_CARBON, DATE_FORMAT_FOR_DISPLAY } from '../../../config';
|
||||||
import { ymdDateStringToConfiguredFormat } from '../../../helpers';
|
import DateAndTimeService from '../../../services/DateAndTimeService';
|
||||||
import { getCommonAttributes } from '../../helpers';
|
import { getCommonAttributes } from '../../helpers';
|
||||||
|
|
||||||
/** The `BaseInputTemplate` is the template to use to render the basic `<input>` component for the `core` theme.
|
/** The `BaseInputTemplate` is the template to use to render the basic `<input>` component for the `core` theme.
|
||||||
@ -87,7 +87,7 @@ export default function BaseInputTemplate<
|
|||||||
dateValue = value;
|
dateValue = value;
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
dateValue = ymdDateStringToConfiguredFormat(value);
|
dateValue = DateAndTimeService.ymdDateStringToConfiguredFormat(value);
|
||||||
// let the date component and form validators handle bad dates and do not blow up
|
// let the date component and form validators handle bad dates and do not blow up
|
||||||
} catch (RangeError) {}
|
} catch (RangeError) {}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { getTemplate, WidgetProps } from '@rjsf/utils';
|
import { getTemplate, WidgetProps } from '@rjsf/utils';
|
||||||
import { dateStringToYMDFormat } from '../../../helpers';
|
import DateAndTimeService from '../../../services/DateAndTimeService';
|
||||||
|
|
||||||
function DateWidget(props: WidgetProps) {
|
function DateWidget(props: WidgetProps) {
|
||||||
const { onChange, options, registry } = props;
|
const { onChange, options, registry } = props;
|
||||||
@ -12,7 +12,7 @@ function DateWidget(props: WidgetProps) {
|
|||||||
const handleChange = useCallback(
|
const handleChange = useCallback(
|
||||||
(value: any) => {
|
(value: any) => {
|
||||||
// react json schema forces y-m-d format for dates
|
// react json schema forces y-m-d format for dates
|
||||||
const newValue = dateStringToYMDFormat(value);
|
const newValue = DateAndTimeService.dateStringToYMDFormat(value);
|
||||||
onChange(newValue || undefined);
|
onChange(newValue || undefined);
|
||||||
},
|
},
|
||||||
[onChange]
|
[onChange]
|
||||||
|
@ -5,12 +5,8 @@ import {
|
|||||||
DATE_FORMAT_FOR_DISPLAY,
|
DATE_FORMAT_FOR_DISPLAY,
|
||||||
DATE_RANGE_DELIMITER,
|
DATE_RANGE_DELIMITER,
|
||||||
} from '../../../config';
|
} from '../../../config';
|
||||||
import {
|
|
||||||
convertDateObjectToFormattedString,
|
|
||||||
convertStringToDate,
|
|
||||||
dateStringToYMDFormat,
|
|
||||||
} from '../../../helpers';
|
|
||||||
import { getCommonAttributes } from '../../helpers';
|
import { getCommonAttributes } from '../../helpers';
|
||||||
|
import DateAndTimeService from '../../../services/DateAndTimeService';
|
||||||
|
|
||||||
interface widgetArgs {
|
interface widgetArgs {
|
||||||
id: string;
|
id: string;
|
||||||
@ -52,13 +48,18 @@ export default function DateRangePickerWidget({
|
|||||||
const onChangeLocal = useCallback(
|
const onChangeLocal = useCallback(
|
||||||
(dateRange: Date[]) => {
|
(dateRange: Date[]) => {
|
||||||
let dateRangeString;
|
let dateRangeString;
|
||||||
const startDate = convertDateObjectToFormattedString(dateRange[0]);
|
const startDate = DateAndTimeService.convertDateObjectToFormattedString(
|
||||||
|
dateRange[0]
|
||||||
|
);
|
||||||
if (startDate) {
|
if (startDate) {
|
||||||
const startDateYMD = dateStringToYMDFormat(startDate);
|
const startDateYMD =
|
||||||
const endDate = convertDateObjectToFormattedString(dateRange[1]);
|
DateAndTimeService.dateStringToYMDFormat(startDate);
|
||||||
|
const endDate = DateAndTimeService.convertDateObjectToFormattedString(
|
||||||
|
dateRange[1]
|
||||||
|
);
|
||||||
dateRangeString = startDateYMD;
|
dateRangeString = startDateYMD;
|
||||||
if (endDate) {
|
if (endDate) {
|
||||||
const endDateYMD = dateStringToYMDFormat(endDate);
|
const endDateYMD = DateAndTimeService.dateStringToYMDFormat(endDate);
|
||||||
dateRangeString = `${dateRangeString}${DATE_RANGE_DELIMITER}${endDateYMD}`;
|
dateRangeString = `${dateRangeString}${DATE_RANGE_DELIMITER}${endDateYMD}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,11 +74,11 @@ export default function DateRangePickerWidget({
|
|||||||
let startDate = null;
|
let startDate = null;
|
||||||
let endDate = null;
|
let endDate = null;
|
||||||
try {
|
try {
|
||||||
startDate = convertStringToDate(startDateString);
|
startDate = DateAndTimeService.convertStringToDate(startDateString);
|
||||||
// eslint-disable-next-line no-empty
|
// eslint-disable-next-line no-empty
|
||||||
} catch (RangeError) {}
|
} catch (RangeError) {}
|
||||||
try {
|
try {
|
||||||
endDate = convertStringToDate(endDateString);
|
endDate = DateAndTimeService.convertStringToDate(endDateString);
|
||||||
// eslint-disable-next-line no-empty
|
// eslint-disable-next-line no-empty
|
||||||
} catch (RangeError) {}
|
} catch (RangeError) {}
|
||||||
|
|
||||||
|
@ -8,8 +8,6 @@ import {
|
|||||||
getPageInfoFromSearchParams,
|
getPageInfoFromSearchParams,
|
||||||
modifyProcessIdentifierForPathParam,
|
modifyProcessIdentifierForPathParam,
|
||||||
refreshAtInterval,
|
refreshAtInterval,
|
||||||
REFRESH_INTERVAL_SECONDS,
|
|
||||||
REFRESH_TIMEOUT_SECONDS,
|
|
||||||
} from '../helpers';
|
} from '../helpers';
|
||||||
import HttpService from '../services/HttpService';
|
import HttpService from '../services/HttpService';
|
||||||
import {
|
import {
|
||||||
@ -19,6 +17,7 @@ import {
|
|||||||
RecentProcessModel,
|
RecentProcessModel,
|
||||||
} from '../interfaces';
|
} from '../interfaces';
|
||||||
import ProcessInstanceRun from '../components/ProcessInstanceRun';
|
import ProcessInstanceRun from '../components/ProcessInstanceRun';
|
||||||
|
import DateAndTimeService from '../services/DateAndTimeService';
|
||||||
|
|
||||||
const PER_PAGE_FOR_TASKS_ON_HOME_PAGE = 5;
|
const PER_PAGE_FOR_TASKS_ON_HOME_PAGE = 5;
|
||||||
|
|
||||||
@ -47,8 +46,8 @@ export default function MyTasks() {
|
|||||||
|
|
||||||
getTasks();
|
getTasks();
|
||||||
refreshAtInterval(
|
refreshAtInterval(
|
||||||
REFRESH_INTERVAL_SECONDS,
|
DateAndTimeService.REFRESH_INTERVAL_SECONDS,
|
||||||
REFRESH_TIMEOUT_SECONDS,
|
DateAndTimeService.REFRESH_TIMEOUT_SECONDS,
|
||||||
getTasks
|
getTasks
|
||||||
);
|
);
|
||||||
}, [searchParams]);
|
}, [searchParams]);
|
||||||
|
@ -45,7 +45,6 @@ import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
|||||||
import HttpService from '../services/HttpService';
|
import HttpService from '../services/HttpService';
|
||||||
import ReactDiagramEditor from '../components/ReactDiagramEditor';
|
import ReactDiagramEditor from '../components/ReactDiagramEditor';
|
||||||
import {
|
import {
|
||||||
convertSecondsToFormattedDateTime,
|
|
||||||
getLastMilestoneFromProcessInstance,
|
getLastMilestoneFromProcessInstance,
|
||||||
HUMAN_TASK_TYPES,
|
HUMAN_TASK_TYPES,
|
||||||
modifyProcessIdentifierForPathParam,
|
modifyProcessIdentifierForPathParam,
|
||||||
@ -78,6 +77,7 @@ import {
|
|||||||
errorForDisplayFromString,
|
errorForDisplayFromString,
|
||||||
} from '../components/ErrorDisplay';
|
} from '../components/ErrorDisplay';
|
||||||
import { Notification } from '../components/Notification';
|
import { Notification } from '../components/Notification';
|
||||||
|
import DateAndTimeService from '../services/DateAndTimeService';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
variant: string;
|
variant: string;
|
||||||
@ -380,7 +380,9 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||||||
<dl>
|
<dl>
|
||||||
<dt>{lastUpdatedTimeLabel}:</dt>
|
<dt>{lastUpdatedTimeLabel}:</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{convertSecondsToFormattedDateTime(lastUpdatedTime || 0) || 'N/A'}
|
{DateAndTimeService.convertSecondsToFormattedDateTime(
|
||||||
|
lastUpdatedTime || 0
|
||||||
|
) || 'N/A'}
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
);
|
);
|
||||||
@ -442,7 +444,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||||||
<dl>
|
<dl>
|
||||||
<dt>Started:</dt>
|
<dt>Started:</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{convertSecondsToFormattedDateTime(
|
{DateAndTimeService.convertSecondsToFormattedDateTime(
|
||||||
processInstance.start_in_seconds || 0
|
processInstance.start_in_seconds || 0
|
||||||
)}
|
)}
|
||||||
</dd>
|
</dd>
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
import DateAndTimeService from './DateAndTimeService';
|
||||||
|
|
||||||
|
test('it can keep the correct date when converting seconds to date', () => {
|
||||||
|
const dateString =
|
||||||
|
DateAndTimeService.convertSecondsToFormattedDateString(1666325400);
|
||||||
|
expect(dateString).toEqual('2022-10-21');
|
||||||
|
});
|
||||||
|
test('it can properly format a duration', () => {
|
||||||
|
expect(DateAndTimeService.formatDurationForDisplay(null, '0')).toEqual('0s');
|
||||||
|
expect(DateAndTimeService.formatDurationForDisplay(null, '60')).toEqual('1m');
|
||||||
|
expect(DateAndTimeService.formatDurationForDisplay(null, '65')).toEqual(
|
||||||
|
'1m 5s'
|
||||||
|
);
|
||||||
|
expect(DateAndTimeService.formatDurationForDisplay(null, 65)).toEqual(
|
||||||
|
'1m 5s'
|
||||||
|
);
|
||||||
|
expect(DateAndTimeService.formatDurationForDisplay(null, 86500)).toEqual(
|
||||||
|
'1d 1m 40s'
|
||||||
|
);
|
||||||
|
expect(DateAndTimeService.formatDurationForDisplay(null, 2629746)).toEqual(
|
||||||
|
'30d 10h 29m 6s'
|
||||||
|
);
|
||||||
|
expect(DateAndTimeService.formatDurationForDisplay(null, 31536765)).toEqual(
|
||||||
|
'365d 12m 45s'
|
||||||
|
);
|
||||||
|
});
|
216
spiffworkflow-frontend/src/services/DateAndTimeService.tsx
Normal file
216
spiffworkflow-frontend/src/services/DateAndTimeService.tsx
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
import { Duration, format } from 'date-fns';
|
||||||
|
import {
|
||||||
|
DATE_TIME_FORMAT,
|
||||||
|
DATE_FORMAT,
|
||||||
|
TIME_FORMAT_HOURS_MINUTES,
|
||||||
|
} from '../config';
|
||||||
|
import { isANumber } from '../helpers';
|
||||||
|
|
||||||
|
const MINUTES_IN_HOUR = 60;
|
||||||
|
const SECONDS_IN_MINUTE = 60;
|
||||||
|
const SECONDS_IN_HOUR = MINUTES_IN_HOUR * SECONDS_IN_MINUTE;
|
||||||
|
const FOUR_HOURS_IN_SECONDS = SECONDS_IN_HOUR * 4;
|
||||||
|
|
||||||
|
const REFRESH_INTERVAL_SECONDS = 5;
|
||||||
|
const REFRESH_TIMEOUT_SECONDS = FOUR_HOURS_IN_SECONDS;
|
||||||
|
|
||||||
|
const convertDateToSeconds = (date: any, onChangeFunction: any = null) => {
|
||||||
|
let dateInSeconds = date;
|
||||||
|
if (date !== null) {
|
||||||
|
let dateInMilliseconds = date;
|
||||||
|
if (typeof date.getTime === 'function') {
|
||||||
|
dateInMilliseconds = date.getTime();
|
||||||
|
}
|
||||||
|
dateInSeconds = Math.floor(dateInMilliseconds / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onChangeFunction) {
|
||||||
|
onChangeFunction(dateInSeconds);
|
||||||
|
} else {
|
||||||
|
return dateInSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertDateObjectToFormattedString = (dateObject: Date) => {
|
||||||
|
if (dateObject) {
|
||||||
|
return format(dateObject, DATE_FORMAT);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const dateStringToYMDFormat = (dateString: string) => {
|
||||||
|
if (dateString && dateString.match(/^\d{2}-\d{2}-\d{4}$/)) {
|
||||||
|
if (DATE_FORMAT.startsWith('dd')) {
|
||||||
|
const d = dateString.split('-');
|
||||||
|
return `${d[2]}-${d[1]}-${d[0]}`;
|
||||||
|
}
|
||||||
|
if (DATE_FORMAT.startsWith('MM')) {
|
||||||
|
const d = dateString.split('-');
|
||||||
|
return `${d[2]}-${d[0]}-${d[1]}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dateString;
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertDateAndTimeStringsToDate = (
|
||||||
|
dateString: string,
|
||||||
|
timeString: string
|
||||||
|
) => {
|
||||||
|
if (dateString && timeString) {
|
||||||
|
return new Date(`${dateStringToYMDFormat(dateString)}T${timeString}`);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertDateAndTimeStringsToSeconds = (
|
||||||
|
dateString: string,
|
||||||
|
timeString: string
|
||||||
|
) => {
|
||||||
|
const dateObject = convertDateAndTimeStringsToDate(dateString, timeString);
|
||||||
|
if (dateObject) {
|
||||||
|
return convertDateToSeconds(dateObject);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertStringToDate = (dateString: string) => {
|
||||||
|
return convertDateAndTimeStringsToDate(dateString, '00:10:00');
|
||||||
|
};
|
||||||
|
|
||||||
|
const ymdDateStringToConfiguredFormat = (dateString: string) => {
|
||||||
|
const dateObject = convertStringToDate(dateString);
|
||||||
|
if (dateObject) {
|
||||||
|
return convertDateObjectToFormattedString(dateObject);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertSecondsToDateObject = (seconds: number) => {
|
||||||
|
if (seconds) {
|
||||||
|
return new Date(seconds * 1000);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertSecondsToFormattedDateTime = (seconds: number) => {
|
||||||
|
const dateObject = convertSecondsToDateObject(seconds);
|
||||||
|
if (dateObject) {
|
||||||
|
return format(dateObject, DATE_TIME_FORMAT);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertDateObjectToFormattedHoursMinutes = (dateObject: Date) => {
|
||||||
|
if (dateObject) {
|
||||||
|
return format(dateObject, TIME_FORMAT_HOURS_MINUTES);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertSecondsToFormattedTimeHoursMinutes = (seconds: number) => {
|
||||||
|
const dateObject = convertSecondsToDateObject(seconds);
|
||||||
|
if (dateObject) {
|
||||||
|
return convertDateObjectToFormattedHoursMinutes(dateObject);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertSecondsToFormattedDateString = (seconds: number) => {
|
||||||
|
const dateObject = convertSecondsToDateObject(seconds);
|
||||||
|
if (dateObject) {
|
||||||
|
return convertDateObjectToFormattedString(dateObject);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertDateStringToSeconds = (dateString: string) => {
|
||||||
|
const dateObject = convertStringToDate(dateString);
|
||||||
|
if (dateObject) {
|
||||||
|
return convertDateToSeconds(dateObject);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// logic from https://stackoverflow.com/a/28510323/6090676
|
||||||
|
const secondsToDuration = (secNum: number) => {
|
||||||
|
const days = Math.floor(secNum / 86400);
|
||||||
|
const hours = Math.floor(secNum / 3600) % 24;
|
||||||
|
const minutes = Math.floor(secNum / 60) % 60;
|
||||||
|
const seconds = secNum % 60;
|
||||||
|
|
||||||
|
const duration: Duration = {
|
||||||
|
days,
|
||||||
|
hours,
|
||||||
|
minutes,
|
||||||
|
seconds,
|
||||||
|
};
|
||||||
|
return duration;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatDurationForDisplay = (_row: any, value: any) => {
|
||||||
|
if (value === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const duration = secondsToDuration(parseInt(value, 10));
|
||||||
|
const durationTimes = [];
|
||||||
|
if (duration.seconds !== undefined && duration.seconds > 0) {
|
||||||
|
durationTimes.unshift(`${duration.seconds}s`);
|
||||||
|
}
|
||||||
|
if (duration.minutes !== undefined && duration.minutes > 0) {
|
||||||
|
durationTimes.unshift(`${duration.minutes}m`);
|
||||||
|
}
|
||||||
|
if (duration.hours !== undefined && duration.hours > 0) {
|
||||||
|
durationTimes.unshift(`${duration.hours}h`);
|
||||||
|
}
|
||||||
|
if (duration.days !== undefined && duration.days > 0) {
|
||||||
|
durationTimes.unshift(`${duration.days}d`);
|
||||||
|
}
|
||||||
|
if (durationTimes.length < 1) {
|
||||||
|
durationTimes.push('0s');
|
||||||
|
}
|
||||||
|
return durationTimes.join(' ');
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatDateTime = (_row: any, value: any) => {
|
||||||
|
if (value === undefined || value === null) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
let dateInSeconds = value;
|
||||||
|
if (!isANumber(value)) {
|
||||||
|
const timeArgs = value.split('T');
|
||||||
|
dateInSeconds = convertDateAndTimeStringsToSeconds(
|
||||||
|
timeArgs[0],
|
||||||
|
timeArgs[1]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (dateInSeconds) {
|
||||||
|
return convertSecondsToFormattedDateTime(dateInSeconds);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DateAndTimeService = {
|
||||||
|
REFRESH_INTERVAL_SECONDS,
|
||||||
|
REFRESH_TIMEOUT_SECONDS,
|
||||||
|
|
||||||
|
convertDateAndTimeStringsToDate,
|
||||||
|
convertDateAndTimeStringsToSeconds,
|
||||||
|
convertDateObjectToFormattedHoursMinutes,
|
||||||
|
convertDateObjectToFormattedString,
|
||||||
|
convertDateStringToSeconds,
|
||||||
|
convertDateToSeconds,
|
||||||
|
convertSecondsToDateObject,
|
||||||
|
convertSecondsToFormattedDateString,
|
||||||
|
convertSecondsToFormattedDateTime,
|
||||||
|
convertSecondsToFormattedTimeHoursMinutes,
|
||||||
|
convertStringToDate,
|
||||||
|
dateStringToYMDFormat,
|
||||||
|
formatDateTime,
|
||||||
|
formatDurationForDisplay,
|
||||||
|
secondsToDuration,
|
||||||
|
ymdDateStringToConfiguredFormat,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DateAndTimeService;
|
@ -1,8 +1,9 @@
|
|||||||
import { formatDateTime, formatDurationForDisplay } from '../helpers';
|
import DateAndTimeService from './DateAndTimeService';
|
||||||
|
|
||||||
const spiffFormatFunctions: { [key: string]: Function } = {
|
const spiffFormatFunctions: { [key: string]: Function } = {
|
||||||
convert_seconds_to_date_time_for_display: formatDateTime,
|
convert_seconds_to_date_time_for_display: DateAndTimeService.formatDateTime,
|
||||||
convert_seconds_to_duration_for_display: formatDurationForDisplay,
|
convert_seconds_to_duration_for_display:
|
||||||
|
DateAndTimeService.formatDurationForDisplay,
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkForSpiffFormats = (markdown: string) => {
|
const checkForSpiffFormats = (markdown: string) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user