diff --git a/.changeset/early-hairs-itch.md b/.changeset/early-hairs-itch.md new file mode 100644 index 0000000000..7a7c6b715c --- /dev/null +++ b/.changeset/early-hairs-itch.md @@ -0,0 +1,6 @@ +--- +'@ballerine/react-pdf-toolkit': patch +'@ballerine/common': patch +--- + +bump diff --git a/.changeset/five-wombats-thank.md b/.changeset/five-wombats-thank.md new file mode 100644 index 0000000000..7262341bd3 --- /dev/null +++ b/.changeset/five-wombats-thank.md @@ -0,0 +1,5 @@ +--- +'@ballerine/react-pdf-toolkit': patch +--- + +Updated exports & bump diff --git a/.changeset/heavy-apes-double.md b/.changeset/heavy-apes-double.md new file mode 100644 index 0000000000..7d8ada7577 --- /dev/null +++ b/.changeset/heavy-apes-double.md @@ -0,0 +1,12 @@ +--- +'@ballerine/report-generation-example': minor +'@ballerine/react-pdf-toolkit': minor +'@ballerine/workflows-service': minor +'@ballerine/headless-example': minor +'@ballerine/backoffice-v2': minor +'@ballerine/common': minor +'@ballerine/kyb-app': minor +'@ballerine/ui': minor +--- + +Bump diff --git a/.changeset/kind-melons-hammer.md b/.changeset/kind-melons-hammer.md new file mode 100644 index 0000000000..5311b4bcf1 --- /dev/null +++ b/.changeset/kind-melons-hammer.md @@ -0,0 +1,5 @@ +--- +'@ballerine/react-pdf-toolkit': patch +--- + +Added report templates & storybook stories diff --git a/.changeset/loud-hornets-switch.md b/.changeset/loud-hornets-switch.md new file mode 100644 index 0000000000..7854daa4b9 --- /dev/null +++ b/.changeset/loud-hornets-switch.md @@ -0,0 +1,7 @@ +--- +'@ballerine/react-pdf-toolkit': patch +'@ballerine/workflows-service': patch +'@ballerine/backoffice-v2': patch +--- + +bump alpha diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 0000000000..32d5e607a6 --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,39 @@ +{ + "mode": "pre", + "tag": "11210907c", + "initialVersions": { + "@ballerine/backoffice-v2": "0.5.44", + "@ballerine/kyb-app": "0.1.39", + "@ballerine/workflows-dashboard": "0.1.11", + "@ballerine/headless-example": "0.1.39", + "@ballerine/report-generation-example": "0.0.1", + "@ballerine/blocks": "0.1.24", + "@ballerine/common": "0.7.39", + "@ballerine/config": "1.0.4", + "@ballerine/eslint-config": "1.0.4", + "@ballerine/eslint-config-react": "1.0.5", + "@ballerine/react-pdf-toolkit": "1.0.12", + "@ballerine/rules-engine-lib": "0.4.24", + "@ballerine/ui": "0.3.26", + "@ballerine/workflow-core": "0.5.39", + "@ballerine/web-ui-sdk": "1.4.36", + "@ballerine/workflow-browser-sdk": "0.5.39", + "@ballerine/workflow-node-sdk": "0.5.39", + "@ballerine/websocket-service": "0.0.16", + "@ballerine/workflows-service": "0.5.39", + "@ballerine/docs-site": "0.0.1" + }, + "changesets": [ + "early-hairs-itch", + "five-wombats-thank", + "heavy-apes-double", + "kind-melons-hammer", + "loud-hornets-switch", + "rare-eels-tan", + "rotten-owls-invent", + "shiny-rocks-suffer", + "tough-nails-teach", + "wicked-ducks-act", + "young-jeans-fail" + ] +} diff --git a/.changeset/rare-eels-tan.md b/.changeset/rare-eels-tan.md new file mode 100644 index 0000000000..ad65033fd7 --- /dev/null +++ b/.changeset/rare-eels-tan.md @@ -0,0 +1,5 @@ +--- +'@ballerine/common': patch +--- + +Added base64 provider type diff --git a/.changeset/rotten-owls-invent.md b/.changeset/rotten-owls-invent.md new file mode 100644 index 0000000000..1279dcc9a3 --- /dev/null +++ b/.changeset/rotten-owls-invent.md @@ -0,0 +1,17 @@ +--- +'@ballerine/report-generation-example': patch +'@ballerine/react-pdf-toolkit': patch +'@ballerine/workflows-service': patch +'@ballerine/headless-example': patch +'@ballerine/workflow-browser-sdk': patch +'@ballerine/workflow-core': patch +'@ballerine/workflow-node-sdk': patch +'@ballerine/backoffice-v2': patch +'@ballerine/blocks': patch +'@ballerine/common': patch +'@ballerine/web-ui-sdk': patch +'@ballerine/kyb-app': patch +'@ballerine/ui': patch +--- + +bump diff --git a/.changeset/shiny-rocks-suffer.md b/.changeset/shiny-rocks-suffer.md new file mode 100644 index 0000000000..2ed90b4e72 --- /dev/null +++ b/.changeset/shiny-rocks-suffer.md @@ -0,0 +1,11 @@ +--- +'@ballerine/react-pdf-toolkit': patch +'@ballerine/workflows-service': patch +'@ballerine/headless-example': patch +'@ballerine/backoffice-v2': patch +'@ballerine/common': patch +'@ballerine/kyb-app': patch +'@ballerine/ui': patch +--- + +Version bump diff --git a/.changeset/tough-nails-teach.md b/.changeset/tough-nails-teach.md new file mode 100644 index 0000000000..e97196a796 --- /dev/null +++ b/.changeset/tough-nails-teach.md @@ -0,0 +1,5 @@ +--- +'@ballerine/react-pdf-toolkit': patch +--- + +Updated Header date formatting diff --git a/.changeset/wicked-ducks-act.md b/.changeset/wicked-ducks-act.md new file mode 100644 index 0000000000..6548c913b3 --- /dev/null +++ b/.changeset/wicked-ducks-act.md @@ -0,0 +1,5 @@ +--- +'@ballerine/react-pdf-toolkit': patch +--- + +bump diff --git a/.changeset/young-jeans-fail.md b/.changeset/young-jeans-fail.md new file mode 100644 index 0000000000..d37f7eec8b --- /dev/null +++ b/.changeset/young-jeans-fail.md @@ -0,0 +1,5 @@ +--- +'@ballerine/react-pdf-toolkit': patch +--- + +Cleanup & Bump diff --git a/apps/backoffice-v2/CHANGELOG.md b/apps/backoffice-v2/CHANGELOG.md index 071399c1d0..436701727e 100644 --- a/apps/backoffice-v2/CHANGELOG.md +++ b/apps/backoffice-v2/CHANGELOG.md @@ -1,5 +1,20 @@ # @ballerine/backoffice-v2 +## 0.7.0-11210907c.0 + +### Minor Changes + +- Bump + +### Patch Changes + +- Updated dependencies + - @ballerine/common@0.9.0-11210907c.0 + - @ballerine/ui@0.5.0-11210907c.0 + - @ballerine/blocks@0.2.1-11210907c.0 + - @ballerine/workflow-browser-sdk@0.6.1-11210907c.0 + - @ballerine/workflow-node-sdk@0.6.1-11210907c.0 + ## 0.6.0 ### Minor Changes @@ -113,6 +128,11 @@ ### Patch Changes - Updated dependencies + - @ballerine/common@0.7.42-11210907c.0 + - @ballerine/blocks@0.1.27-11210907c.0 + - @ballerine/ui@0.3.29-11210907c.0 + - @ballerine/workflow-browser-sdk@0.5.42-11210907c.0 + - @ballerine/workflow-node-sdk@0.5.42-11210907c.0 - @ballerine/common@0.7.42 - @ballerine/workflow-browser-sdk@0.5.42 - @ballerine/workflow-node-sdk@0.5.42 @@ -165,6 +185,8 @@ - @ballerine/common@0.7.38 - @ballerine/workflow-browser-sdk@0.5.38 - @ballerine/workflow-node-sdk@0.5.38 +- Updated dependencies + - @ballerine/ui@0.3.27 ## 0.5.42 diff --git a/apps/backoffice-v2/package.json b/apps/backoffice-v2/package.json index 217b6dd678..4c8f3763b8 100644 --- a/apps/backoffice-v2/package.json +++ b/apps/backoffice-v2/package.json @@ -1,6 +1,6 @@ { "name": "@ballerine/backoffice-v2", - "version": "0.6.0", + "version": "0.7.0-11210907c.0", "description": "Ballerine - Backoffice", "homepage": "https://github.com/ballerine-io/ballerine", "repository": { @@ -50,11 +50,11 @@ "preview": "vite preview" }, "dependencies": { - "@ballerine/blocks": "0.2.0", - "@ballerine/common": "0.8.0", - "@ballerine/ui": "^0.4.0", - "@ballerine/workflow-browser-sdk": "0.6.0", - "@ballerine/workflow-node-sdk": "0.6.0", + "@ballerine/blocks": "0.2.1-11210907c.0", + "@ballerine/common": "0.9.0-11210907c.0", + "@ballerine/ui": "^0.5.0-11210907c.0", + "@ballerine/workflow-browser-sdk": "0.6.1-11210907c.0", + "@ballerine/workflow-node-sdk": "0.6.1-11210907c.0", "@fontsource/inter": "^4.5.15", "@formkit/auto-animate": "1.0.0-beta.5", "@hookform/resolvers": "^3.1.0", diff --git a/apps/backoffice-v2/src/common/components/atoms/Select/Select.Content.tsx b/apps/backoffice-v2/src/common/components/atoms/Select/Select.Content.tsx index 962f4ede23..5ee5061f86 100644 --- a/apps/backoffice-v2/src/common/components/atoms/Select/Select.Content.tsx +++ b/apps/backoffice-v2/src/common/components/atoms/Select/Select.Content.tsx @@ -1,5 +1,5 @@ -import * as React from 'react'; import * as SelectPrimitive from '@radix-ui/react-select'; +import * as React from 'react'; import { ctw } from '../../../utils/ctw/ctw'; export const SelectContent = React.forwardRef< diff --git a/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/ProcessTracker.tsx b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/ProcessTracker.tsx index d30b58e8fb..cce07f1140 100644 --- a/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/ProcessTracker.tsx +++ b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/ProcessTracker.tsx @@ -1,28 +1,20 @@ -import { FunctionComponent } from 'react'; import { AccordionCard, HoverCard, HoverCardContent, HoverCardTrigger } from '@ballerine/ui'; +import { FunctionComponent } from 'react'; +import { Icon } from '@/common/components/molecules/ProcessTracker/constants'; import { useProcessTrackerLogic } from '@/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/useProcessTrackerLogic'; import { IProcessTrackerProps } from '@/common/components/molecules/ProcessTracker/interfaces'; import { HelpCircle } from 'lucide-react'; -import { Icon } from '@/common/components/molecules/ProcessTracker/constants'; export const ProcessTracker: FunctionComponent = ({ - tags, plugins, - context, - childWorkflows, + workflow, + processes, }) => { - const { - uncollapsedItemValue, - onValueChange, - thirdPartyProcessesSubitems, - collectionFlowSubitems, - uboFlowsSubitems, - } = useProcessTrackerLogic({ - tags, + const { uncollapsedItemValue, onValueChange, trackedProcesses } = useProcessTrackerLogic({ plugins, - context, - childWorkflows, + workflow, + processes, }); return ( @@ -69,17 +61,9 @@ export const ProcessTracker: FunctionComponent = ({ Processes - - - + {trackedProcesses.map(({ name, title, subitems }) => ( + + ))} diff --git a/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/constants.tsx b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/constants.tsx index dd9663aeaf..28ec5daf96 100644 --- a/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/constants.tsx +++ b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/constants.tsx @@ -1,10 +1,10 @@ -import { ProcessStatus, StateTag } from '@ballerine/common'; -import { RefreshCircle } from '@/common/components/atoms/RefreshCircle/RefreshCircle'; -import { ClockCircle } from '@/common/components/atoms/ClockCircle/ClockCircle'; -import { XCircle } from '@/common/components/atoms/XCircle/XCircle'; -import { MinusCircle } from '@/common/components/atoms/MinusCircle/MinusCircle'; import { CheckCircle } from '@/common/components/atoms/CheckCircle/CheckCircle'; +import { ClockCircle } from '@/common/components/atoms/ClockCircle/ClockCircle'; import { IndicatorCircle } from '@/common/components/atoms/IndicatorCircle/IndicatorCircle'; +import { MinusCircle } from '@/common/components/atoms/MinusCircle/MinusCircle'; +import { RefreshCircle } from '@/common/components/atoms/RefreshCircle/RefreshCircle'; +import { XCircle } from '@/common/components/atoms/XCircle/XCircle'; +import { ProcessStatus, StateTag } from '@ballerine/common'; export const tagToAccordionCardItem = { [StateTag.COLLECTION_FLOW]: 'Collection flow', diff --git a/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/interfaces.ts b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/interfaces.ts index 62108668ba..53fbb9466d 100644 --- a/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/interfaces.ts +++ b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/interfaces.ts @@ -1,8 +1,7 @@ -import { TWorkflowById } from '@/domains/workflows/fetchers'; import { TWorkflowDefinitionById } from '@/domains/workflow-definitions/fetchers'; +import { TWorkflowById } from '@/domains/workflows/fetchers'; export interface IUseProcessTrackerLogicParams { - tags: TWorkflowById['tags']; plugins: Array< | NonNullable['apiPlugins']>[number] | NonNullable< @@ -10,6 +9,6 @@ export interface IUseProcessTrackerLogicParams { >[number] | NonNullable['commonPlugins']>[number] >; - context: TWorkflowById['context']; - childWorkflows: TWorkflowById['childWorkflows']; + workflow: TWorkflowById; + processes?: string[]; } diff --git a/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/collection-flow.process-tracker.ts b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/collection-flow.process-tracker.ts new file mode 100644 index 0000000000..b13b1d7901 --- /dev/null +++ b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/collection-flow.process-tracker.ts @@ -0,0 +1,46 @@ +import { processStatusToIcon } from '@/common/components/molecules/ProcessTracker/constants'; +import { + IProcessTracker, + ProcessTrackerItem, +} from '@/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/process-tracker.abstract'; +import { TWorkflowById } from '@/domains/workflows/fetchers'; +import { ProcessStatus } from '@ballerine/common'; +import { titleCase } from 'string-ts'; + +export class CollectionFlowProcessTracker implements IProcessTracker { + PROCESS_NAME = 'collection-flow'; + + constructor(readonly workflow: TWorkflowById) {} + + buildItems(): ProcessTrackerItem[] { + return ( + this.getSteps()?.map(step => { + return { + text: titleCase(step), + leftIcon: this.getCollectionFlowStatus(step), + }; + }) || [] + ); + } + + getReadableName(): string { + return 'Collection Flow'; + } + + private getSteps() { + return Object.keys(this.workflow?.context?.flowConfig?.stepsProgress ?? {})?.sort((a, b) => { + return ( + (this.workflow?.context?.flowConfig?.stepsProgress?.[a]?.number ?? 0) - + (this.workflow?.context?.flowConfig?.stepsProgress?.[b]?.number ?? 0) + ); + }); + } + + private getCollectionFlowStatus(step: string) { + if (this.workflow?.context?.flowConfig?.stepsProgress?.[step]?.isCompleted) { + return processStatusToIcon[ProcessStatus.SUCCESS]; + } + + return processStatusToIcon[ProcessStatus.IDLE]; + } +} diff --git a/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/index.ts b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/index.ts new file mode 100644 index 0000000000..5047dcc9c5 --- /dev/null +++ b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/index.ts @@ -0,0 +1,11 @@ +import { CollectionFlowProcessTracker } from '@/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/collection-flow.process-tracker'; +import { MerchantMonitoringProcessTracker } from '@/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/merchant-monitoring.process-tracker'; +import { ThirdPartyProcessTracker } from '@/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/third-party.proces-tracker'; +import { UBOFlowsProcessTracker } from '@/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/ubo-flows.process-tracker'; + +export const processTrackersMap = { + 'collection-flow': CollectionFlowProcessTracker, + ubos: UBOFlowsProcessTracker, + 'third-party': ThirdPartyProcessTracker, + 'merchant-monitoring': MerchantMonitoringProcessTracker, +} as const; diff --git a/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/merchant-monitoring.process-tracker.ts b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/merchant-monitoring.process-tracker.ts new file mode 100644 index 0000000000..7b35040527 --- /dev/null +++ b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/merchant-monitoring.process-tracker.ts @@ -0,0 +1,44 @@ +import { Icon, tagToIcon } from '@/common/components/molecules/ProcessTracker/constants'; +import { + IProcessTracker, + ProcessTrackerItem, +} from '@/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/process-tracker.abstract'; +import { TWorkflowById } from '@/domains/workflows/fetchers'; +import { StateTag } from '@ballerine/common'; + +export class MerchantMonitoringProcessTracker implements IProcessTracker { + PROCESS_NAME = 'merchant-monitoring'; + + constructor(readonly workflow: TWorkflowById) {} + + buildItems(): ProcessTrackerItem[] { + return [ + { + text: this.resolveTitleToTags(this.workflow?.tags || []), + leftIcon: this.getIconKeyByState(this.workflow?.tags || []), + }, + ]; + } + + getReadableName(): string { + return 'Merchant Monitoring'; + } + + private resolveTitleToTags(tags?: string[]) { + if (tags?.includes(StateTag.PENDING_PROCESS)) return 'Risk Analysis'; + + if (tags?.includes(StateTag.FAILURE)) return 'Process failed.'; + + if (tags?.includes(StateTag.MANUAL_REVIEW)) return 'Manual Review'; + + if (tags?.includes(StateTag.REJECTED)) return 'Rejected'; + + if (tags?.includes(StateTag.APPROVED)) return 'Approved'; + } + + private getIconKeyByState(tags: string[]): JSX.Element { + return tagToIcon[tags[0] as keyof typeof tagToIcon] + ? tagToIcon[tags[0] as keyof typeof tagToIcon] + : Icon.INDICATOR; + } +} diff --git a/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/process-tracker.abstract.ts b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/process-tracker.abstract.ts new file mode 100644 index 0000000000..b01d1fc1c1 --- /dev/null +++ b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/process-tracker.abstract.ts @@ -0,0 +1,17 @@ +import { TPlugin } from '@/domains/workflow-definitions/fetchers'; +import { TWorkflowById } from '@/domains/workflows/fetchers'; + +export interface ProcessTrackerItem { + text: string | JSX.Element | undefined; + leftIcon: JSX.Element | undefined; +} + +export abstract class IProcessTracker { + abstract readonly PROCESS_NAME: string; + + constructor(readonly workflow: TWorkflowById, readonly plugins?: TPlugin[]) {} + + abstract buildItems(): ProcessTrackerItem[]; + + abstract getReadableName(): string; +} diff --git a/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/third-party.proces-tracker.tsx b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/third-party.proces-tracker.tsx new file mode 100644 index 0000000000..00fb82a00b --- /dev/null +++ b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/third-party.proces-tracker.tsx @@ -0,0 +1,55 @@ +import { + pluginsWhiteList, + processStatusToIcon, +} from '@/common/components/molecules/ProcessTracker/constants'; +import { + IProcessTracker, + ProcessTrackerItem, +} from '@/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/process-tracker.abstract'; +import { TPlugin } from '@/domains/workflow-definitions/fetchers'; +import { TWorkflowById } from '@/domains/workflows/fetchers'; +import { ProcessStatus } from '@ballerine/common'; + +export class ThirdPartyProcessTracker implements IProcessTracker { + PROCESS_NAME = 'third-party'; + + constructor(readonly workflow: TWorkflowById, readonly plugins?: TPlugin[]) {} + + buildItems(): ProcessTrackerItem[] { + return ( + this.plugins + ?.filter(({ name }) => pluginsWhiteList.includes(name as (typeof pluginsWhiteList)[number])) + ?.map(({ displayName, name }) => { + const pluginStatus = this.getPluginByName(name)?.status ?? ProcessStatus.DEFAULT; + + return { + text: + pluginStatus === ProcessStatus.CANCELED ? ( + {displayName} + ) : ( + displayName + ), + leftIcon: processStatusToIcon[pluginStatus as keyof typeof processStatusToIcon], + }; + }) || [] + ); + } + + getReadableName(): string { + return '3rd party processes'; + } + + private getPluginByName(name: string) { + let plugin: NonNullable[string]; + + Object.keys(this.workflow?.context?.pluginsOutput ?? {})?.forEach(key => { + if (this.workflow?.context?.pluginsOutput?.[key]?.name !== name) { + return; + } + + plugin = this.workflow?.context?.pluginsOutput?.[key]; + }); + + return plugin; + } +} diff --git a/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/ubo-flows.process-tracker.ts b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/ubo-flows.process-tracker.ts new file mode 100644 index 0000000000..50c9b8dff9 --- /dev/null +++ b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/ubo-flows.process-tracker.ts @@ -0,0 +1,42 @@ +import { tagToIcon } from '@/common/components/molecules/ProcessTracker/constants'; +import { + IProcessTracker, + ProcessTrackerItem, +} from '@/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/process-tracker.abstract'; +import { valueOrNA } from '@/common/utils/value-or-na/value-or-na'; +import { TWorkflowById } from '@/domains/workflows/fetchers'; + +export class UBOFlowsProcessTracker implements IProcessTracker { + PROCESS_NAME = 'ubos'; + + constructor(readonly workflow: TWorkflowById) {} + + buildItems(): ProcessTrackerItem[] { + return this.getChildWorkflows().map(({ context, tags }) => { + return { + text: `${valueOrNA(context?.entity?.data?.firstName)} ${valueOrNA( + context?.entity?.data?.lastName, + )}`, + leftIcon: this.getUboFlowStatus(tags), + }; + }); + } + + getReadableName(): string { + return 'UBO flows'; + } + + private getUboFlowStatus(tags: TWorkflowById['tags']) { + const tag = tags?.find(tag => tagToIcon[tag as keyof typeof tagToIcon]); + + if (!tag) { + return tagToIcon.DEFAULT; + } + + return tagToIcon[tag as keyof typeof tagToIcon]; + } + + private getChildWorkflows() { + return this.workflow?.childWorkflows || []; + } +} diff --git a/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/useProcessTrackerLogic.tsx b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/useProcessTrackerLogic.tsx index fa558fbf26..a5af16a6b5 100644 --- a/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/useProcessTrackerLogic.tsx +++ b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/useProcessTrackerLogic.tsx @@ -1,141 +1,61 @@ -import { useCallback, useEffect, useMemo, useState } from 'react'; -import { - pluginsWhiteList, - processStatusToIcon, - tagToAccordionCardItem, - tagToIcon, -} from '@/common/components/molecules/ProcessTracker/constants'; -import { titleCase } from 'string-ts'; -import { TWorkflowById } from '@/domains/workflows/fetchers'; -import { valueOrNA } from '@/common/utils/value-or-na/value-or-na'; -import { ProcessStatus } from '@ballerine/common'; +import { tagToAccordionCardItem } from '@/common/components/molecules/ProcessTracker/constants'; import { IUseProcessTrackerLogicParams } from '@/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/interfaces'; +import { processTrackersMap } from '@/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters'; +import { IProcessTracker } from '@/common/components/molecules/ProcessTracker/hooks/useProcessTrackerLogic/process-tracker-adapters/process-tracker.abstract'; +import { useCallback, useEffect, useMemo, useState } from 'react'; + +const defaultProcesses = ['collection-flow', 'third-party', 'ubos']; export const useProcessTrackerLogic = ({ - tags, plugins, - context, - childWorkflows, + workflow, + processes = defaultProcesses, }: IUseProcessTrackerLogicParams) => { - const [uncollapsedItemValue, setUncollapsedItemValue] = useState(); - const onValueChange = useCallback((value: string) => { - setUncollapsedItemValue(value); - }, []); - - const kycChildWorkflows = useMemo(() => { - return childWorkflows?.filter( - childWorkflow => childWorkflow?.context?.entity?.type === 'individual', - ); - }, [childWorkflows]); - + const tags = useMemo(() => workflow?.tags || [], [workflow]); const tag = useMemo( () => tags?.find(tag => tagToAccordionCardItem[tag as keyof typeof tagToAccordionCardItem]), [tags], ); - const steps = useMemo(() => { - return Object.keys(context?.flowConfig?.stepsProgress ?? {})?.sort((a, b) => { - return ( - (context?.flowConfig?.stepsProgress?.[a]?.number ?? 0) - - (context?.flowConfig?.stepsProgress?.[b]?.number ?? 0) - ); - }); - }, [context?.flowConfig?.stepsProgress]); - - const getCollectionFlowStatus = useCallback( - (step: string) => { - if (context?.flowConfig?.stepsProgress?.[step]?.isCompleted) { - return processStatusToIcon[ProcessStatus.SUCCESS]; - } - - return processStatusToIcon[ProcessStatus.IDLE]; - }, - [context?.flowConfig?.stepsProgress], - ); - - const getPluginByName = useCallback( - (name: string) => { - let plugin: NonNullable[string]; - - Object.keys(context?.pluginsOutput ?? {})?.forEach(key => { - if (context?.pluginsOutput?.[key]?.name !== name) { - return; - } - - plugin = context?.pluginsOutput?.[key]; - }); - - return plugin; - }, - [context?.pluginsOutput], - ); - - const getUboFlowStatus = useCallback((tags: TWorkflowById['tags']) => { - const tag = tags?.find(tag => tagToIcon[tag as keyof typeof tagToIcon]); - - if (!tag) { - return tagToIcon.DEFAULT; - } - - return tagToIcon[tag as keyof typeof tagToIcon]; + const [uncollapsedItemValue, setUncollapsedItemValue] = useState(); + const onValueChange = useCallback((value: string) => { + setUncollapsedItemValue(value); }, []); - const collectionFlowSubitems = useMemo(() => { - return steps?.map(step => { - return { - text: titleCase(step), - leftIcon: getCollectionFlowStatus(step), - }; - }); - }, [getCollectionFlowStatus, steps]); - - const thirdPartyProcessesSubitems = useMemo(() => { - return plugins - ?.filter(({ name }) => pluginsWhiteList.includes(name as (typeof pluginsWhiteList)[number])) - ?.map(({ displayName, name }) => { - const plugin = getPluginByName(name); + const processTrackers = useMemo( + () => + processes.reduce((list, processName) => { + const ProcessTracker = processTrackersMap[processName as keyof typeof processTrackersMap]; - if (plugin?.isRequestTimedOut) { - return { - text: {displayName}, - leftIcon: processStatusToIcon[ProcessStatus.CANCELED], - }; + if (!ProcessTracker) { + console.warn(`${processName} is unsupported.`); + return list; } - const pluginStatus = plugin?.status ?? ProcessStatus.DEFAULT; + list.push(new ProcessTracker(workflow, plugins)); - return { - text: - pluginStatus === ProcessStatus.CANCELED ? ( - {displayName} - ) : ( - displayName - ), - leftIcon: processStatusToIcon[pluginStatus as keyof typeof processStatusToIcon], - }; - }); - }, [getPluginByName, plugins]); + return list; + }, [] as IProcessTracker[]), + [workflow, plugins, processes], + ); - const uboFlowsSubitems = useMemo(() => { - return kycChildWorkflows?.map(({ context, tags }) => { + const trackedProcesses = useMemo(() => { + return processTrackers.map(processTracker => { return { - text: `${valueOrNA(context?.entity?.data?.firstName)} ${valueOrNA( - context?.entity?.data?.lastName, - )}`, - leftIcon: getUboFlowStatus(tags), + title: processTracker.getReadableName(), + name: processTracker.PROCESS_NAME, + subitems: processTracker.buildItems(), }; }); - }, [getUboFlowStatus, kycChildWorkflows]); + }, [processTrackers]); useEffect(() => { onValueChange(tagToAccordionCardItem[tag as keyof typeof tagToAccordionCardItem]); }, [onValueChange, tag]); return { + trackedProcesses, uncollapsedItemValue, onValueChange, - thirdPartyProcessesSubitems, - collectionFlowSubitems, - uboFlowsSubitems, }; }; diff --git a/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/interfaces.ts b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/interfaces.ts index 6d8ce20bd4..d68fd52b95 100644 --- a/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/interfaces.ts +++ b/apps/backoffice-v2/src/common/components/molecules/ProcessTracker/interfaces.ts @@ -1,8 +1,8 @@ -import { TWorkflowById } from '@/domains/workflows/fetchers'; import { TWorkflowDefinitionById } from '@/domains/workflow-definitions/fetchers'; +import { TWorkflowById } from '@/domains/workflows/fetchers'; export interface IProcessTrackerProps { - tags: TWorkflowById['tags']; + workflow: TWorkflowById; plugins: Array< | NonNullable['apiPlugins']>[number] | NonNullable< @@ -10,6 +10,5 @@ export interface IProcessTrackerProps { >[number] | NonNullable['commonPlugins']>[number] >; - context: TWorkflowById['context']; - childWorkflows: TWorkflowById['childWorkflows']; + processes?: string[]; } diff --git a/apps/backoffice-v2/src/lib/blocks/components/PDFViewerCell/PDFViewer.tsx b/apps/backoffice-v2/src/lib/blocks/components/PDFViewerCell/PDFViewer.tsx new file mode 100644 index 0000000000..092eccab04 --- /dev/null +++ b/apps/backoffice-v2/src/lib/blocks/components/PDFViewerCell/PDFViewer.tsx @@ -0,0 +1,10 @@ +import { TPDFViewerCell } from '@/lib/blocks/components/PDFViewerCell/interfaces'; +import { FunctionComponent } from 'react'; + +export const PDFViewerCell: FunctionComponent = ({ props, value }) => { + const { width, height } = props; + + return value ? ( +