⚡ Remember result in either local or session storage (#514)
Closes #513
This commit is contained in:
@@ -8,7 +8,7 @@ export const SwitchWithRelatedSettings = ({ children, ...props }: Props) => (
|
||||
<Stack
|
||||
borderWidth={props.initialValue ? 1 : undefined}
|
||||
rounded="md"
|
||||
p={props.initialValue ? '4' : undefined}
|
||||
p={props.initialValue ? '3' : undefined}
|
||||
spacing={4}
|
||||
>
|
||||
<SwitchWithLabel {...props} />
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
import { Flex, FormLabel, Stack, Switch, useDisclosure } from '@chakra-ui/react'
|
||||
import {
|
||||
Flex,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
HStack,
|
||||
Stack,
|
||||
Switch,
|
||||
Tag,
|
||||
useDisclosure,
|
||||
Text,
|
||||
} from '@chakra-ui/react'
|
||||
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||
import { Plan } from '@typebot.io/prisma'
|
||||
import { GeneralSettings } from '@typebot.io/schemas'
|
||||
import { GeneralSettings, rememberUserStorages } from '@typebot.io/schemas'
|
||||
import React from 'react'
|
||||
import { isDefined } from '@typebot.io/lib'
|
||||
import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
|
||||
@@ -9,6 +19,9 @@ import { ChangePlanModal } from '@/features/billing/components/ChangePlanModal'
|
||||
import { LockTag } from '@/features/billing/components/LockTag'
|
||||
import { isFreePlan } from '@/features/billing/helpers/isFreePlan'
|
||||
import { useI18n } from '@/locales'
|
||||
import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSettings'
|
||||
import { DropdownList } from '@/components/DropdownList'
|
||||
import { MoreInfoTooltip } from '@/components/MoreInfoTooltip'
|
||||
|
||||
type Props = {
|
||||
generalSettings: GeneralSettings
|
||||
@@ -31,10 +44,13 @@ export const GeneralSettingsForm = ({
|
||||
})
|
||||
}
|
||||
|
||||
const handleNewResultOnRefreshChange = (isRememberSessionChecked: boolean) =>
|
||||
const toggleRememberUser = (isEnabled: boolean) =>
|
||||
onGeneralSettingsChange({
|
||||
...generalSettings,
|
||||
isNewResultOnRefreshEnabled: !isRememberSessionChecked,
|
||||
rememberUser: {
|
||||
...generalSettings.rememberUser,
|
||||
isEnabled,
|
||||
},
|
||||
})
|
||||
|
||||
const handleInputPrefillChange = (isInputPrefillEnabled: boolean) =>
|
||||
@@ -49,6 +65,17 @@ export const GeneralSettingsForm = ({
|
||||
isHideQueryParamsEnabled,
|
||||
})
|
||||
|
||||
const updateRememberUserStorage = (
|
||||
storage: NonNullable<GeneralSettings['rememberUser']>['storage']
|
||||
) =>
|
||||
onGeneralSettingsChange({
|
||||
...generalSettings,
|
||||
rememberUser: {
|
||||
...generalSettings.rememberUser,
|
||||
storage,
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<Stack spacing={6}>
|
||||
<ChangePlanModal
|
||||
@@ -77,22 +104,46 @@ export const GeneralSettingsForm = ({
|
||||
onCheckChange={handleInputPrefillChange}
|
||||
moreInfoContent="Inputs are automatically pre-filled whenever their associated variable has a value"
|
||||
/>
|
||||
<SwitchWithLabel
|
||||
label="Remember session"
|
||||
initialValue={
|
||||
isDefined(generalSettings.isNewResultOnRefreshEnabled)
|
||||
? !generalSettings.isNewResultOnRefreshEnabled
|
||||
: true
|
||||
}
|
||||
onCheckChange={handleNewResultOnRefreshChange}
|
||||
moreInfoContent="If the user refreshes the page or opens the typebot again during the same session, his previous variables will be prefilled and his new answers will override the previous ones."
|
||||
/>
|
||||
<SwitchWithLabel
|
||||
label="Hide query params on bot start"
|
||||
initialValue={generalSettings.isHideQueryParamsEnabled ?? true}
|
||||
onCheckChange={handleHideQueryParamsChange}
|
||||
moreInfoContent="If your URL contains query params, they will be automatically hidden when the bot starts."
|
||||
/>
|
||||
<SwitchWithRelatedSettings
|
||||
label={'Remember user'}
|
||||
moreInfoContent="If enabled, user previous variables will be prefilled and his new answers will override the previous ones."
|
||||
initialValue={
|
||||
generalSettings.rememberUser?.isEnabled ??
|
||||
(isDefined(generalSettings.isNewResultOnRefreshEnabled)
|
||||
? !generalSettings.isNewResultOnRefreshEnabled
|
||||
: false)
|
||||
}
|
||||
onCheckChange={toggleRememberUser}
|
||||
>
|
||||
<FormControl as={HStack} justifyContent="space-between">
|
||||
<FormLabel mb="0">
|
||||
Storage:
|
||||
<MoreInfoTooltip>
|
||||
<Stack>
|
||||
<Text>
|
||||
Choose <Tag size="sm">session</Tag> to remember the user as
|
||||
long as he does not closes the tab or the browser.
|
||||
</Text>
|
||||
<Text>
|
||||
Choose <Tag size="sm">local</Tag> to remember the user
|
||||
forever.
|
||||
</Text>
|
||||
</Stack>
|
||||
</MoreInfoTooltip>
|
||||
</FormLabel>
|
||||
<DropdownList
|
||||
currentItem={generalSettings.rememberUser?.storage ?? 'session'}
|
||||
onItemSelect={updateRememberUserStorage}
|
||||
items={rememberUserStorages}
|
||||
></DropdownList>
|
||||
</FormControl>
|
||||
</SwitchWithRelatedSettings>
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ The general settings represent the general behaviors of your typebot.
|
||||
|
||||
- **Typebot.io branding**: If enabled, will show a "Made with Typebot" badge displayed at the bottom of your bot.
|
||||
- **Prefill input**: If enabled, the inputs will be automatically pre-filled whenever their associated variable has a value.
|
||||
- **Remember session**: If enabled, when a user refreshes the page, its existing answers will be overwritten.
|
||||
- **Hide query params on bot start**: If enabled, the query params will be hidden when the bot starts.
|
||||
- **Remember user**: If enabled, user previous variables will be prefilled and his new answers will override the previous ones.
|
||||
|
||||
## Typing emulation
|
||||
|
||||
|
||||
@@ -124,8 +124,11 @@ const startSession = async (startParams?: StartParams, userId?: string) => {
|
||||
isPreview: startParams.isPreview || typeof startParams.typebot !== 'string',
|
||||
typebotId: typebot.id,
|
||||
prefilledVariables,
|
||||
isNewResultOnRefreshEnabled:
|
||||
typebot.settings.general.isNewResultOnRefreshEnabled ?? false,
|
||||
isRememberUserEnabled:
|
||||
typebot.settings.general.rememberUser?.isEnabled ??
|
||||
(isDefined(typebot.settings.general.isNewResultOnRefreshEnabled)
|
||||
? !typebot.settings.general.isNewResultOnRefreshEnabled
|
||||
: false),
|
||||
})
|
||||
|
||||
const startVariables =
|
||||
@@ -291,11 +294,11 @@ const getResult = async ({
|
||||
isPreview,
|
||||
resultId,
|
||||
prefilledVariables,
|
||||
isNewResultOnRefreshEnabled,
|
||||
isRememberUserEnabled,
|
||||
}: Pick<StartParams, 'isPreview' | 'resultId'> & {
|
||||
typebotId: string
|
||||
prefilledVariables: Variable[]
|
||||
isNewResultOnRefreshEnabled: boolean
|
||||
isRememberUserEnabled: boolean
|
||||
}) => {
|
||||
if (isPreview) return
|
||||
const select = {
|
||||
@@ -305,7 +308,7 @@ const getResult = async ({
|
||||
} satisfies Prisma.ResultSelect
|
||||
|
||||
const existingResult =
|
||||
resultId && !isNewResultOnRefreshEnabled
|
||||
resultId && isRememberUserEnabled
|
||||
? ((await prisma.result.findFirst({
|
||||
where: { id: resultId },
|
||||
select,
|
||||
|
||||
@@ -21,7 +21,10 @@ test('Result should be overwritten on page refresh', async ({ page }) => {
|
||||
...defaultSettings,
|
||||
general: {
|
||||
...defaultSettings.general,
|
||||
isNewResultOnRefreshEnabled: false,
|
||||
rememberUser: {
|
||||
isEnabled: true,
|
||||
storage: 'session',
|
||||
},
|
||||
},
|
||||
},
|
||||
...parseDefaultGroupWithBlock({
|
||||
|
||||
Reference in New Issue
Block a user