Skip to content

Commit

Permalink
feat(engine): ✨ Add Rating input
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Jun 8, 2022
1 parent 3010976 commit b1aecf8
Show file tree
Hide file tree
Showing 19 changed files with 455 additions and 28 deletions.
6 changes: 6 additions & 0 deletions apps/builder/assets/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -457,3 +457,9 @@ export const PlayIcon = (props: IconProps) => (
<polygon points="5 3 19 12 5 21 5 3"></polygon>
</Icon>
)

export const StarIcon = (props: IconProps) => (
<Icon viewBox="0 0 24 24" {...featherIconsBaseProps} {...props}>
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
</Icon>
)
5 changes: 3 additions & 2 deletions apps/builder/components/editor/StepsSideBar/StepIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
NumberIcon,
PhoneIcon,
SendEmailIcon,
StarIcon,
TextIcon,
WebhookIcon,
} from 'assets/icons'
Expand Down Expand Up @@ -65,6 +66,8 @@ export const StepIcon = ({ type, ...props }: StepIconProps) => {
return <CheckSquareIcon color="orange.500" {...props} />
case InputStepType.PAYMENT:
return <CreditCardIcon color="orange.500" {...props} />
case InputStepType.RATING:
return <StarIcon color="orange.500" {...props} />
case LogicStepType.SET_VARIABLE:
return <EditIcon color="purple.500" {...props} />
case LogicStepType.CONDITION:
Expand All @@ -91,7 +94,5 @@ export const StepIcon = ({ type, ...props }: StepIconProps) => {
return <SendEmailIcon {...props} />
case 'start':
return <FlagIcon {...props} />
default:
return <></>
}
}
8 changes: 5 additions & 3 deletions apps/builder/components/editor/StepsSideBar/StepTypeLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import React from 'react'

type Props = { type: StepType }

export const StepTypeLabel = ({ type }: Props) => {
export const StepTypeLabel = ({ type }: Props): JSX.Element => {
switch (type) {
case 'start':
return <Text>Start</Text>
case BubbleStepType.TEXT:
case InputStepType.TEXT:
return <Text>Text</Text>
Expand Down Expand Up @@ -39,6 +41,8 @@ export const StepTypeLabel = ({ type }: Props) => {
return <Text>Button</Text>
case InputStepType.PAYMENT:
return <Text>Payment</Text>
case InputStepType.RATING:
return <Text>Rating</Text>
case LogicStepType.SET_VARIABLE:
return <Text>Set variable</Text>
case LogicStepType.CONDITION:
Expand Down Expand Up @@ -79,7 +83,5 @@ export const StepTypeLabel = ({ type }: Props) => {
return <Text>Pabbly</Text>
case IntegrationStepType.EMAIL:
return <Text>Email</Text>
default:
return <></>
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
LogicStepType,
Step,
StepOptions,
TextBubbleStep,
StepWithOptions,
Webhook,
} from 'models'
import { useRef } from 'react'
Expand All @@ -33,6 +33,7 @@ import { GoogleAnalyticsSettings } from './bodies/GoogleAnalyticsSettings'
import { GoogleSheetsSettingsBody } from './bodies/GoogleSheetsSettingsBody'
import { PaymentSettings } from './bodies/PaymentSettings'
import { PhoneNumberSettingsBody } from './bodies/PhoneNumberSettingsBody'
import { RatingInputSettings } from './bodies/RatingInputSettingsBody'
import { RedirectSettings } from './bodies/RedirectSettings'
import { SendEmailSettings } from './bodies/SendEmailSettings'
import { SetVariableSettings } from './bodies/SetVariableSettings'
Expand All @@ -41,7 +42,7 @@ import { WebhookSettings } from './bodies/WebhookSettings'
import { ZapierSettings } from './bodies/ZapierSettings'

type Props = {
step: Exclude<Step, TextBubbleStep>
step: StepWithOptions | ConditionStep
webhook?: Webhook
onExpandClick: () => void
onStepChange: (updates: Partial<Step>) => void
Expand Down Expand Up @@ -87,10 +88,10 @@ export const StepSettings = ({
step,
onStepChange,
}: {
step: Step
step: StepWithOptions | ConditionStep
webhook?: Webhook
onStepChange: (step: Partial<Step>) => void
}) => {
}): JSX.Element => {
const handleOptionsChange = (options: StepOptions) => {
onStepChange({ options } as Partial<Step>)
}
Expand Down Expand Up @@ -164,6 +165,14 @@ export const StepSettings = ({
/>
)
}
case InputStepType.RATING: {
return (
<RatingInputSettings
options={step.options}
onOptionsChange={handleOptionsChange}
/>
)
}
case LogicStepType.SET_VARIABLE: {
return (
<SetVariableSettings
Expand Down Expand Up @@ -258,8 +267,5 @@ export const StepSettings = ({
/>
)
}
default: {
return <></>
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { FormLabel, Stack } from '@chakra-ui/react'
import { DropdownList } from 'components/shared/DropdownList'
import { SwitchWithLabel } from 'components/shared/SwitchWithLabel'
import { Input } from 'components/shared/Textbox'
import { VariableSearchInput } from 'components/shared/VariableSearchInput'
import { RatingInputOptions, Variable } from 'models'
import React from 'react'

type RatingInputSettingsProps = {
options: RatingInputOptions
onOptionsChange: (options: RatingInputOptions) => void
}

export const RatingInputSettings = ({
options,
onOptionsChange,
}: RatingInputSettingsProps) => {
const handleLengthChange = (length: number) =>
onOptionsChange({ ...options, length })

const handleTypeChange = (buttonType: 'Icons' | 'Numbers') =>
onOptionsChange({ ...options, buttonType })

const handleCustomIconCheck = (isEnabled: boolean) =>
onOptionsChange({
...options,
customIcon: { ...options.customIcon, isEnabled },
})

const handleIconSvgChange = (svg: string) =>
onOptionsChange({ ...options, customIcon: { ...options.customIcon, svg } })

const handleLeftLabelChange = (left: string) =>
onOptionsChange({ ...options, labels: { ...options.labels, left } })

const handleMiddleLabelChange = (middle: string) =>
onOptionsChange({ ...options, labels: { ...options.labels, middle } })

const handleRightLabelChange = (right: string) =>
onOptionsChange({ ...options, labels: { ...options.labels, right } })

const handleButtonLabelChange = (button: string) =>
onOptionsChange({ ...options, labels: { ...options.labels, button } })

const handleVariableChange = (variable?: Variable) =>
onOptionsChange({ ...options, variableId: variable?.id })

return (
<Stack spacing={4}>
<Stack>
<FormLabel mb="0" htmlFor="button">
Maximum:
</FormLabel>
<DropdownList
onItemSelect={handleLengthChange}
items={[3, 4, 5, 6, 7, 8, 9, 10]}
currentItem={options.length}
/>
</Stack>

<Stack>
<FormLabel mb="0" htmlFor="button">
Type:
</FormLabel>
<DropdownList
onItemSelect={handleTypeChange}
items={['Icons', 'Numbers']}
currentItem={options.buttonType}
/>
</Stack>

{options.buttonType === 'Icons' && (
<SwitchWithLabel
id="switch"
label="Custom icon?"
initialValue={options.customIcon.isEnabled}
onCheckChange={handleCustomIconCheck}
/>
)}
{options.buttonType === 'Icons' && options.customIcon.isEnabled && (
<Stack>
<FormLabel mb="0" htmlFor="svg">
Icon SVG:
</FormLabel>
<Input
id="svg"
defaultValue={options.customIcon.svg}
onChange={handleIconSvgChange}
placeholder="<svg>...</svg>"
/>
</Stack>
)}
<Stack>
<FormLabel mb="0" htmlFor="button">
1 label:
</FormLabel>
<Input
id="button"
defaultValue={options.labels.left}
onChange={handleLeftLabelChange}
placeholder="Not likely at all"
/>
</Stack>
{options.length >= 4 && (
<Stack>
<FormLabel mb="0" htmlFor="button">
{Math.floor(options.length / 2)} label:
</FormLabel>
<Input
id="button"
defaultValue={options.labels.middle}
onChange={handleMiddleLabelChange}
placeholder="Neutral"
/>
</Stack>
)}
<Stack>
<FormLabel mb="0" htmlFor="button">
{options.length} label:
</FormLabel>
<Input
id="button"
defaultValue={options.labels.right}
onChange={handleRightLabelChange}
placeholder="Extremely likely"
/>
</Stack>
<Stack>
<FormLabel mb="0" htmlFor="button">
Button label:
</FormLabel>
<Input
id="button"
defaultValue={options.labels.button}
onChange={handleButtonLabelChange}
/>
</Stack>
<Stack>
<FormLabel mb="0" htmlFor="variable">
Save answer in a variable:
</FormLabel>
<VariableSearchInput
initialVariableId={options.variableId}
onSelectVariable={handleVariableChange}
/>
</Stack>
</Stack>
)
}
25 changes: 15 additions & 10 deletions apps/builder/components/shared/Graph/Nodes/StepNode/StepNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import React, { useEffect, useRef, useState } from 'react'
import {
BubbleStep,
BubbleStepContent,
ConditionStep,
DraggableStep,
Step,
StepWithOptions,
TextBubbleContent,
TextBubbleStep,
} from 'models'
Expand Down Expand Up @@ -210,29 +212,32 @@ export const StepNode = ({
</Flex>
</PopoverTrigger>
{hasSettingsPopover(step) && (
<SettingsPopoverContent
step={step}
onExpandClick={handleExpandClick}
onStepChange={handleStepUpdate}
/>
<>
<SettingsPopoverContent
step={step}
onExpandClick={handleExpandClick}
onStepChange={handleStepUpdate}
/>
<SettingsModal isOpen={isModalOpen} onClose={handleModalClose}>
<StepSettings step={step} onStepChange={handleStepUpdate} />
</SettingsModal>
</>
)}
{isMediaBubbleStep(step) && (
<MediaBubblePopoverContent
step={step}
onContentChange={handleContentChange}
/>
)}
<SettingsModal isOpen={isModalOpen} onClose={handleModalClose}>
<StepSettings step={step} onStepChange={handleStepUpdate} />
</SettingsModal>
</Popover>
)}
</ContextMenu>
)
}

const hasSettingsPopover = (step: Step): step is Exclude<Step, BubbleStep> =>
!isBubbleStep(step)
const hasSettingsPopover = (
step: Step
): step is StepWithOptions | ConditionStep => !isBubbleStep(step)

const isMediaBubbleStep = (
step: Step
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { ConfigureContent } from './contents/ConfigureContent'
import { ImageBubbleContent } from './contents/ImageBubbleContent'
import { PaymentInputContent } from './contents/PaymentInputContent'
import { PlaceholderContent } from './contents/PlaceholderContent'
import { RatingInputContent } from './contents/RatingInputContent'
import { SendEmailContent } from './contents/SendEmailContent'
import { TypebotLinkContent } from './contents/TypebotLinkContent'
import { ProviderWebhookContent } from './contents/ZapierContent'
Expand All @@ -30,7 +31,7 @@ type Props = {
step: Step | StartStep
indices: StepIndices
}
export const StepNodeContent = ({ step, indices }: Props) => {
export const StepNodeContent = ({ step, indices }: Props): JSX.Element => {
if (isInputStep(step) && !isChoiceInput(step) && step.options.variableId) {
return <WithVariableContent step={step} />
}
Expand Down Expand Up @@ -72,6 +73,9 @@ export const StepNodeContent = ({ step, indices }: Props) => {
case InputStepType.PAYMENT: {
return <PaymentInputContent step={step} />
}
case InputStepType.RATING: {
return <RatingInputContent step={step} />
}
case LogicStepType.SET_VARIABLE: {
return <SetVariableContent step={step} />
}
Expand Down Expand Up @@ -144,8 +148,5 @@ export const StepNodeContent = ({ step, indices }: Props) => {
case 'start': {
return <Text>Start</Text>
}
default: {
return <Text>No input</Text>
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Text } from '@chakra-ui/react'
import { RatingInputStep } from 'models'

type Props = {
step: RatingInputStep
}

export const RatingInputContent = ({ step }: Props) => (
<Text noOfLines={0} pr="6">
Rate from 1 to {step.options.length}
</Text>
)
Loading

5 comments on commit b1aecf8

@vercel
Copy link

@vercel vercel bot commented on b1aecf8 Jun 8, 2022

@vercel
Copy link

@vercel vercel bot commented on b1aecf8 Jun 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs – ./apps/docs

docs-typebot-io.vercel.app
docs-git-main-typebot-io.vercel.app
docs.typebot.io

@vercel
Copy link

@vercel vercel bot commented on b1aecf8 Jun 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on b1aecf8 Jun 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on b1aecf8 Jun 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

builder-v2 – ./apps/builder

builder-v2-git-main-typebot-io.vercel.app
app.typebot.io
builder-v2-typebot-io.vercel.app

Please sign in to comment.