import { exhaustiveSwitch } from '../..'; import { CellValue, ColumnType, IStatus, ITypeOptions, Language, MaybeAbsentCellValue, StatusType, } from '../../types'; import { transformCellValueToString } from './transformCellValueToString'; import { ICollaboratorsById } from '.'; import flatten from 'lodash/flatten'; import groupBy from 'lodash/groupBy'; export const transformCellValueToStatus = ({ originCellValue, originTypeOptions, targetTypeOptions, opts, }: { originCellValue: CellValue; originTypeOptions: ITypeOptions; targetTypeOptions: Pick, 'statuses'>; opts?: { locale?: Language; collaboratorsById?: ICollaboratorsById; }; }) => { const originColumnType = originTypeOptions.type; const targetPendingStatus = targetTypeOptions.statuses.find( (status) => status.type === StatusType.PENDING ); const { groupedStatusesByType, orderedStatusesByTypeGroup } = getOrderedStatusesByType(targetTypeOptions.statuses); switch (originColumnType) { case ColumnType.CHECKBOX: { const checkboxValue = originCellValue as CellValue; const targetOption = targetTypeOptions.statuses.find( (status) => (!checkboxValue && status.type === StatusType.PENDING) || (checkboxValue && status.type === StatusType.DONE) ); return { statusId: targetOption?.statusId ?? null, optionNotFound: !targetOption, }; } case ColumnType.MULTI_ATTACHMENT: { return { statusId: targetPendingStatus?.statusId ?? null, optionNotFound: !targetPendingStatus, }; } case ColumnType.MULTI_SELECT: case ColumnType.SELECT: { if (originColumnType === ColumnType.MULTI_SELECT) { const multiSelectCellValue = originCellValue as CellValue; if (multiSelectCellValue.length < 1) { return { statusId: targetPendingStatus?.statusId ?? null, optionNotFound: !targetPendingStatus, }; } } const originSelectValue = originColumnType === ColumnType.SELECT ? (originCellValue as CellValue) : [(originCellValue as CellValue)[0]]; return transformCellValueToStatusByName({ originCellValue: originSelectValue as CellValue, originTypeOptions, opts, targetPendingStatus, targetStatuses: orderedStatusesByTypeGroup, }); } case ColumnType.STATUS: { const originStatusId = originCellValue as CellValue; const originStatuses = ( originTypeOptions as ITypeOptions ).statuses; if ( targetTypeOptions.statuses.find( ({ statusId }) => statusId === originStatusId ) ) { return { statusId: originStatusId, optionNotFound: false }; } const targetOptionId = mapOriginStatusIdToTargetStatusId({ originStatusId, originStatuses, groupedStatusesByType, }); return { statusId: targetOptionId, optionNotFound: targetOptionId === null, }; } case ColumnType.AUTO_NUMBER: case ColumnType.CREATED_AT: case ColumnType.CREATED_BY: case ColumnType.COLLABORATOR: case ColumnType.CURRENCY: case ColumnType.DATETIME: case ColumnType.EMAIL: case ColumnType.FORMULA: case ColumnType.PROGRESS: case ColumnType.INTEGRATION_REFERENCE: case ColumnType.LONG_TEXT: case ColumnType.LOOKUP: case ColumnType.NOOP: case ColumnType.NUMBER: case ColumnType.PHONE: case ColumnType.RATING: case ColumnType.RECORD_REFERENCE: case ColumnType.SUBTABLE: case ColumnType.ROLLUP: case ColumnType.TEXT: case ColumnType.UNIQUE_ID: { return transformCellValueToStatusByName({ originCellValue, originTypeOptions, opts, targetPendingStatus, targetStatuses: orderedStatusesByTypeGroup, }); } default: return exhaustiveSwitch({ switchValue: originColumnType, returnValue: [], }); } }; const transformCellValueToStatusByName = ({ originCellValue, originTypeOptions, opts, targetPendingStatus, targetStatuses, }: { originCellValue: MaybeAbsentCellValue; originTypeOptions: ITypeOptions; opts?: { preserveLongText?: boolean; locale?: Language; collaboratorsById?: ICollaboratorsById; }; targetPendingStatus?: IStatus; targetStatuses: IStatus[]; }) => { const stringValue = transformCellValueToString({ cellValue: originCellValue, typeOptions: originTypeOptions, opts, }); if (stringValue === null) { return { statusId: targetPendingStatus?.statusId ?? null, optionNotFound: !targetPendingStatus, }; } const targetOption = targetStatuses.find( (status) => status.name.trim() === stringValue.trim() ); return { statusId: targetOption?.statusId ?? null, optionNotFound: !targetOption, }; }; type StatusesGroupedByType = { [type: string]: IStatus[] }; const getOrderedStatusesByType = ( targetStatuses: IStatus[] ): { groupedStatusesByType: StatusesGroupedByType; orderedStatusesByTypeGroup: IStatus[]; } => { const groupedStatuses = groupBy(targetStatuses, (status) => status.type); const groupedStatusesByType = { [StatusType.PENDING]: groupedStatuses[StatusType.PENDING], [StatusType.DONE]: groupedStatuses[StatusType.DONE], [StatusType.DOING]: groupedStatuses[StatusType.DOING] ?? [], }; return { groupedStatusesByType, orderedStatusesByTypeGroup: flatten(Object.values(groupedStatusesByType)), }; }; const mapOriginStatusIdToTargetStatusId = ({ originStatusId, originStatuses, groupedStatusesByType, }: { originStatusId: string; originStatuses: IStatus[]; groupedStatusesByType: StatusesGroupedByType; }) => { const originStatus = originStatuses.find( ({ statusId }) => statusId === originStatusId ); if (!originStatus) { return null; } let targetStatus; // only has one "pending" type status if ( originStatus.type === StatusType.PENDING || (originStatus.type === StatusType.DONE && groupedStatusesByType[StatusType.DONE].length === 1) ) { targetStatus = groupedStatusesByType[originStatus.type][0]; } else { targetStatus = groupedStatusesByType[originStatus.type].find( (s) => s.name.trim() === originStatus.name.trim() ); } if (!targetStatus) { return null; } return targetStatus.statusId; };