-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
eec5041
commit d0f5f75
Showing
22 changed files
with
451 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
apps/builder/src/features/theme/components/general/ProgressBarForm.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import { ColorPicker } from '@/components/ColorPicker' | ||
import { DropdownList } from '@/components/DropdownList' | ||
import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSettings' | ||
import { NumberInput } from '@/components/inputs' | ||
import { HStack, Text } from '@chakra-ui/react' | ||
import { ProgressBar } from '@typebot.io/schemas' | ||
import { | ||
defaultTheme, | ||
progressBarPlacements, | ||
progressBarPositions, | ||
} from '@typebot.io/schemas/features/typebot/theme/constants' | ||
|
||
type Props = { | ||
progressBar: ProgressBar | ||
onProgressBarChange: (progressBar: ProgressBar) => void | ||
} | ||
|
||
export const ProgressBarForm = ({ | ||
progressBar, | ||
onProgressBarChange, | ||
}: Props) => { | ||
const updateEnabled = (isEnabled: boolean) => | ||
onProgressBarChange({ ...progressBar, isEnabled }) | ||
|
||
const updateColor = (color: string) => | ||
onProgressBarChange({ ...progressBar, color }) | ||
|
||
const updateBackgroundColor = (backgroundColor: string) => | ||
onProgressBarChange({ ...progressBar, backgroundColor }) | ||
|
||
const updatePlacement = (placement: (typeof progressBarPlacements)[number]) => | ||
onProgressBarChange({ ...progressBar, placement }) | ||
|
||
const updatePosition = (position: (typeof progressBarPositions)[number]) => | ||
onProgressBarChange({ ...progressBar, position }) | ||
|
||
const updateThickness = (thickness?: number) => | ||
onProgressBarChange({ ...progressBar, thickness }) | ||
|
||
return ( | ||
<SwitchWithRelatedSettings | ||
label={'Enable progress bar?'} | ||
initialValue={ | ||
progressBar.isEnabled ?? defaultTheme.general.progressBar.isEnabled | ||
} | ||
onCheckChange={updateEnabled} | ||
> | ||
<DropdownList | ||
size="sm" | ||
direction="row" | ||
label="Placement:" | ||
currentItem={ | ||
progressBar.placement ?? defaultTheme.general.progressBar.placement | ||
} | ||
onItemSelect={updatePlacement} | ||
items={progressBarPlacements} | ||
/> | ||
<DropdownList | ||
size="sm" | ||
direction="row" | ||
label="Position when embedded:" | ||
moreInfoTooltip='Select "fixed" to always position the progress bar at the top of the window even though your bot is embedded. Select "absolute" to position the progress bar at the top of the chat container.' | ||
currentItem={ | ||
progressBar.position ?? defaultTheme.general.progressBar.position | ||
} | ||
onItemSelect={updatePosition} | ||
items={progressBarPositions} | ||
/> | ||
<HStack justifyContent="space-between"> | ||
<Text>Color:</Text> | ||
<ColorPicker | ||
defaultValue={ | ||
progressBar.color ?? defaultTheme.general.progressBar.color | ||
} | ||
onColorChange={updateColor} | ||
/> | ||
</HStack> | ||
<HStack justifyContent="space-between"> | ||
<Text>Background color:</Text> | ||
<ColorPicker | ||
defaultValue={ | ||
progressBar.backgroundColor ?? | ||
defaultTheme.general.progressBar.backgroundColor | ||
} | ||
onColorChange={updateBackgroundColor} | ||
/> | ||
</HStack> | ||
<HStack justifyContent="space-between"> | ||
<Text>Thickness:</Text> | ||
<NumberInput | ||
withVariableButton={false} | ||
defaultValue={ | ||
progressBar.thickness ?? defaultTheme.general.progressBar.thickness | ||
} | ||
onValueChange={updateThickness} | ||
size="sm" | ||
/> | ||
</HStack> | ||
</SwitchWithRelatedSettings> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
import { blockHasItems, isDefined, isInputBlock, byId } from '@typebot.io/lib' | ||
import { getBlockById } from '@typebot.io/lib/getBlockById' | ||
import { Block, SessionState } from '@typebot.io/schemas' | ||
|
||
type Props = { | ||
typebotsQueue: SessionState['typebotsQueue'] | ||
progressMetadata: NonNullable<SessionState['progressMetadata']> | ||
currentInputBlockId: string | ||
} | ||
|
||
export const computeCurrentProgress = ({ | ||
typebotsQueue, | ||
progressMetadata, | ||
currentInputBlockId, | ||
}: Props) => { | ||
if (progressMetadata.totalAnswers === 0) return 0 | ||
const paths = computePossibleNextInputBlocks({ | ||
typebotsQueue: typebotsQueue, | ||
blockId: currentInputBlockId, | ||
visitedBlocks: { | ||
[typebotsQueue[0].typebot.id]: [], | ||
}, | ||
currentPath: [], | ||
}) | ||
|
||
return ( | ||
(progressMetadata.totalAnswers / | ||
(Math.max(...paths.map((b) => b.length)) + | ||
progressMetadata.totalAnswers)) * | ||
100 | ||
) | ||
} | ||
|
||
const computePossibleNextInputBlocks = ({ | ||
currentPath, | ||
typebotsQueue, | ||
blockId, | ||
visitedBlocks, | ||
}: { | ||
currentPath: string[] | ||
typebotsQueue: SessionState['typebotsQueue'] | ||
blockId: string | ||
visitedBlocks: { | ||
[key: string]: string[] | ||
} | ||
}): string[][] => { | ||
if (visitedBlocks[typebotsQueue[0].typebot.id].includes(blockId)) return [] | ||
visitedBlocks[typebotsQueue[0].typebot.id].push(blockId) | ||
|
||
const possibleNextInputBlocks: string[][] = [] | ||
|
||
const { block, group, blockIndex } = getBlockById( | ||
blockId, | ||
typebotsQueue[0].typebot.groups | ||
) | ||
|
||
if (isInputBlock(block)) currentPath.push(block.id) | ||
|
||
const outgoingEdgeIds = getBlockOutgoingEdgeIds(block) | ||
|
||
for (const outgoingEdgeId of outgoingEdgeIds) { | ||
const to = typebotsQueue[0].typebot.edges.find( | ||
(e) => e.id === outgoingEdgeId | ||
)?.to | ||
if (!to) continue | ||
const blockId = | ||
to.blockId ?? | ||
typebotsQueue[0].typebot.groups.find((g) => g.id === to.groupId) | ||
?.blocks[0].id | ||
if (!blockId) continue | ||
possibleNextInputBlocks.push( | ||
...computePossibleNextInputBlocks({ | ||
typebotsQueue, | ||
blockId, | ||
visitedBlocks, | ||
currentPath, | ||
}) | ||
) | ||
} | ||
|
||
for (const block of group.blocks.slice(blockIndex + 1)) { | ||
possibleNextInputBlocks.push( | ||
...computePossibleNextInputBlocks({ | ||
typebotsQueue, | ||
blockId: block.id, | ||
visitedBlocks, | ||
currentPath, | ||
}) | ||
) | ||
} | ||
|
||
if (outgoingEdgeIds.length > 0 || group.blocks.length !== blockIndex + 1) | ||
return possibleNextInputBlocks | ||
|
||
if (typebotsQueue.length > 1) { | ||
const nextEdgeId = typebotsQueue[0].edgeIdToTriggerWhenDone | ||
const to = typebotsQueue[1].typebot.edges.find(byId(nextEdgeId))?.to | ||
if (!to) return possibleNextInputBlocks | ||
const blockId = | ||
to.blockId ?? | ||
typebotsQueue[0].typebot.groups.find((g) => g.id === to.groupId) | ||
?.blocks[0].id | ||
if (blockId) { | ||
possibleNextInputBlocks.push( | ||
...computePossibleNextInputBlocks({ | ||
typebotsQueue: typebotsQueue.slice(1), | ||
blockId, | ||
visitedBlocks: { | ||
...visitedBlocks, | ||
[typebotsQueue[1].typebot.id]: [], | ||
}, | ||
currentPath, | ||
}) | ||
) | ||
} | ||
} | ||
|
||
possibleNextInputBlocks.push(currentPath) | ||
|
||
return possibleNextInputBlocks | ||
} | ||
|
||
const getBlockOutgoingEdgeIds = (block: Block) => { | ||
const edgeIds: string[] = [] | ||
if (blockHasItems(block)) { | ||
edgeIds.push(...block.items.map((i) => i.outgoingEdgeId).filter(isDefined)) | ||
} | ||
if (block.outgoingEdgeId) edgeIds.push(block.outgoingEdgeId) | ||
return edgeIds | ||
} |
Oops, something went wrong.