2
0

(setVariable) Add timezone option for dates

Closes #1251
This commit is contained in:
Baptiste Arnaud
2024-02-16 10:07:29 +01:00
parent 07240e6d4b
commit 3e0d3e7724
9 changed files with 250 additions and 33 deletions

View File

@ -200,14 +200,24 @@ const SetVariableValue = ({
</Alert> </Alert>
) )
} }
case 'Now':
case 'Yesterday':
case 'Tomorrow': {
return (
<TextInput
direction="row"
label="Timezone"
onChange={(timeZone) => onOptionsChange({ ...options, timeZone })}
defaultValue={options.timeZone}
placeholder="Europe/Paris"
/>
)
}
case 'Contact name': case 'Contact name':
case 'Phone number': case 'Phone number':
case 'Random ID': case 'Random ID':
case 'Now':
case 'Today':
case 'Tomorrow':
case 'User ID': case 'User ID':
case 'Yesterday': case 'Today':
case 'Empty': case 'Empty':
return null return null
} }

View File

@ -554,10 +554,32 @@
"type": { "type": {
"type": "string", "type": "string",
"enum": [ "enum": [
"Today",
"Now", "Now",
"Yesterday", "Yesterday",
"Tomorrow", "Tomorrow"
]
},
"timeZone": {
"type": "string"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"variableId": {
"type": "string"
},
"isExecutedOnClient": {
"type": "boolean"
},
"type": {
"type": "string",
"enum": [
"Today",
"Moment of the day", "Moment of the day",
"Empty", "Empty",
"Environment name", "Environment name",
@ -4926,10 +4948,32 @@
"type": { "type": {
"type": "string", "type": "string",
"enum": [ "enum": [
"Today",
"Now", "Now",
"Yesterday", "Yesterday",
"Tomorrow", "Tomorrow"
]
},
"timeZone": {
"type": "string"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"variableId": {
"type": "string"
},
"isExecutedOnClient": {
"type": "boolean"
},
"type": {
"type": "string",
"enum": [
"Today",
"Moment of the day", "Moment of the day",
"Empty", "Empty",
"Environment name", "Environment name",
@ -8349,10 +8393,32 @@
"type": { "type": {
"type": "string", "type": "string",
"enum": [ "enum": [
"Today",
"Now", "Now",
"Yesterday", "Yesterday",
"Tomorrow", "Tomorrow"
]
},
"timeZone": {
"type": "string"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"variableId": {
"type": "string"
},
"isExecutedOnClient": {
"type": "boolean"
},
"type": {
"type": "string",
"enum": [
"Today",
"Moment of the day", "Moment of the day",
"Empty", "Empty",
"Environment name", "Environment name",
@ -16835,10 +16901,32 @@
"type": { "type": {
"type": "string", "type": "string",
"enum": [ "enum": [
"Today",
"Now", "Now",
"Yesterday", "Yesterday",
"Tomorrow", "Tomorrow"
]
},
"timeZone": {
"type": "string"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"variableId": {
"type": "string"
},
"isExecutedOnClient": {
"type": "boolean"
},
"type": {
"type": "string",
"enum": [
"Today",
"Moment of the day", "Moment of the day",
"Empty", "Empty",
"Environment name", "Environment name",
@ -20325,10 +20413,32 @@
"type": { "type": {
"type": "string", "type": "string",
"enum": [ "enum": [
"Today",
"Now", "Now",
"Yesterday", "Yesterday",
"Tomorrow", "Tomorrow"
]
},
"timeZone": {
"type": "string"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"variableId": {
"type": "string"
},
"isExecutedOnClient": {
"type": "boolean"
},
"type": {
"type": "string",
"enum": [
"Today",
"Moment of the day", "Moment of the day",
"Empty", "Empty",
"Environment name", "Environment name",
@ -23122,10 +23232,32 @@
"type": { "type": {
"type": "string", "type": "string",
"enum": [ "enum": [
"Today",
"Now", "Now",
"Yesterday", "Yesterday",
"Tomorrow", "Tomorrow"
]
},
"timeZone": {
"type": "string"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"variableId": {
"type": "string"
},
"isExecutedOnClient": {
"type": "boolean"
},
"type": {
"type": "string",
"enum": [
"Today",
"Moment of the day", "Moment of the day",
"Empty", "Empty",
"Environment name", "Environment name",

View File

@ -3621,10 +3621,32 @@
"type": { "type": {
"type": "string", "type": "string",
"enum": [ "enum": [
"Today",
"Now", "Now",
"Yesterday", "Yesterday",
"Tomorrow", "Tomorrow"
]
},
"timeZone": {
"type": "string"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"variableId": {
"type": "string"
},
"isExecutedOnClient": {
"type": "boolean"
},
"type": {
"type": "string",
"enum": [
"Today",
"Moment of the day", "Moment of the day",
"Empty", "Empty",
"Environment name", "Environment name",
@ -7403,10 +7425,32 @@
"type": { "type": {
"type": "string", "type": "string",
"enum": [ "enum": [
"Today",
"Now", "Now",
"Yesterday", "Yesterday",
"Tomorrow", "Tomorrow"
]
},
"timeZone": {
"type": "string"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"variableId": {
"type": "string"
},
"isExecutedOnClient": {
"type": "boolean"
},
"type": {
"type": "string",
"enum": [
"Today",
"Moment of the day", "Moment of the day",
"Empty", "Empty",
"Environment name", "Environment name",

View File

@ -1,11 +1,12 @@
import { SessionState, SetVariableBlock, Variable } from '@typebot.io/schemas' import { SessionState, SetVariableBlock, Variable } from '@typebot.io/schemas'
import { byId } from '@typebot.io/lib' import { byId, isEmpty } from '@typebot.io/lib'
import { ExecuteLogicResponse } from '../../../types' import { ExecuteLogicResponse } from '../../../types'
import { parseScriptToExecuteClientSideAction } from '../script/executeScript' import { parseScriptToExecuteClientSideAction } from '../script/executeScript'
import { parseGuessedValueType } from '@typebot.io/variables/parseGuessedValueType' import { parseGuessedValueType } from '@typebot.io/variables/parseGuessedValueType'
import { parseVariables } from '@typebot.io/variables/parseVariables' import { parseVariables } from '@typebot.io/variables/parseVariables'
import { updateVariablesInSession } from '@typebot.io/variables/updateVariablesInSession' import { updateVariablesInSession } from '@typebot.io/variables/updateVariablesInSession'
import { createId } from '@paralleldrive/cuid2' import { createId } from '@paralleldrive/cuid2'
import { utcToZonedTime, format as tzFormat } from 'date-fns-tz'
export const executeSetVariable = ( export const executeSetVariable = (
state: SessionState, state: SessionState,
@ -87,13 +88,19 @@ const getExpressionToEvaluate =
return phoneNumber ? `"${state.whatsApp?.contact.phoneNumber}"` : null return phoneNumber ? `"${state.whatsApp?.contact.phoneNumber}"` : null
} }
case 'Now': case 'Now':
if (isEmpty(options.timeZone)) return 'new Date().toISOString()'
return toISOWithTz(new Date(), options.timeZone)
case 'Today': case 'Today':
return 'new Date().toISOString()' return 'new Date().toISOString()'
case 'Tomorrow': { case 'Tomorrow': {
return 'new Date(Date.now() + 86400000).toISOString()' if (isEmpty(options.timeZone))
return 'new Date(Date.now() + 86400000).toISOString()'
return toISOWithTz(new Date(Date.now() + 86400000), options.timeZone)
} }
case 'Yesterday': { case 'Yesterday': {
return 'new Date(Date.now() - 86400000).toISOString()' if (isEmpty(options.timeZone))
return 'new Date(Date.now() - 86400000).toISOString()'
return toISOWithTz(new Date(Date.now() - 86400000), options.timeZone)
} }
case 'Random ID': { case 'Random ID': {
return `"${createId()}"` return `"${createId()}"`
@ -130,3 +137,8 @@ const getExpressionToEvaluate =
} }
} }
} }
const toISOWithTz = (date: Date, timeZone: string) => {
const zonedDate = utcToZonedTime(date, timeZone)
return tzFormat(zonedDate, "yyyy-MM-dd'T'HH:mm:ssXXX", { timeZone })
}

View File

@ -477,7 +477,11 @@ const parseReply =
? { status: 'fail' } ? { status: 'fail' }
: { status: 'skip' } : { status: 'skip' }
const urls = reply.split(', ') const urls = reply.split(', ')
const status = urls.some((url) => isURL(url)) ? 'success' : 'fail' const status = urls.some((url) =>
isURL(url, { require_tld: env.S3_ENDPOINT !== 'localhost' })
)
? 'success'
: 'fail'
return { status, reply: reply } return { status, reply: reply }
} }
case InputBlockType.PAYMENT: { case InputBlockType.PAYMENT: {

View File

@ -19,8 +19,9 @@
"@typebot.io/variables": "workspace:*", "@typebot.io/variables": "workspace:*",
"@udecode/plate-common": "21.1.5", "@udecode/plate-common": "21.1.5",
"ai": "2.2.33", "ai": "2.2.33",
"chrono-node": "2.7.0", "chrono-node": "2.7.5",
"date-fns": "2.30.0", "date-fns": "2.30.0",
"date-fns-tz": "2.0.0",
"google-auth-library": "8.9.0", "google-auth-library": "8.9.0",
"google-spreadsheet": "4.1.1", "google-spreadsheet": "4.1.1",
"got": "12.6.0", "got": "12.6.0",

View File

@ -10,7 +10,7 @@ const extractBaseUrl = (val: string | undefined) => {
export const auth = { export const auth = {
type: 'encryptedCredentials', type: 'encryptedCredentials',
name: 'Dify.AI account', name: 'Dify.AI assistant',
schema: option.object({ schema: option.object({
apiEndpoint: option.string apiEndpoint: option.string
.layout({ .layout({

View File

@ -13,9 +13,6 @@ const baseOptions = z.object({
const basicSetVariableOptionsSchema = baseOptions.extend({ const basicSetVariableOptionsSchema = baseOptions.extend({
type: z.enum([ type: z.enum([
'Today', 'Today',
'Now',
'Yesterday',
'Tomorrow',
'Moment of the day', 'Moment of the day',
'Empty', 'Empty',
'Environment name', 'Environment name',
@ -26,6 +23,11 @@ const basicSetVariableOptionsSchema = baseOptions.extend({
]), ]),
}) })
const dateSetVariableOptionsSchema = baseOptions.extend({
type: z.enum(['Now', 'Yesterday', 'Tomorrow']),
timeZone: z.string().optional(),
})
const initialSetVariableOptionsSchema = baseOptions.extend({ const initialSetVariableOptionsSchema = baseOptions.extend({
type: z.undefined().openapi({ type: 'string' }), type: z.undefined().openapi({ type: 'string' }),
expressionToEvaluate: z.string().optional(), expressionToEvaluate: z.string().optional(),
@ -56,6 +58,7 @@ const appendItemToListOptionsSchema = baseOptions.extend({
export const setVariableOptionsSchema = z.discriminatedUnion('type', [ export const setVariableOptionsSchema = z.discriminatedUnion('type', [
initialSetVariableOptionsSchema, initialSetVariableOptionsSchema,
dateSetVariableOptionsSchema,
basicSetVariableOptionsSchema, basicSetVariableOptionsSchema,
customSetVariableOptionsSchema, customSetVariableOptionsSchema,
mapListItemsOptionsSchema, mapListItemsOptionsSchema,

19
pnpm-lock.yaml generated
View File

@ -660,11 +660,14 @@ importers:
specifier: 2.2.33 specifier: 2.2.33
version: 2.2.33(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.9)(vue@3.4.15) version: 2.2.33(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.9)(vue@3.4.15)
chrono-node: chrono-node:
specifier: 2.7.0 specifier: 2.7.5
version: 2.7.0 version: 2.7.5
date-fns: date-fns:
specifier: 2.30.0 specifier: 2.30.0
version: 2.30.0 version: 2.30.0
date-fns-tz:
specifier: 2.0.0
version: 2.0.0(date-fns@2.30.0)
google-auth-library: google-auth-library:
specifier: 8.9.0 specifier: 8.9.0
version: 8.9.0 version: 8.9.0
@ -12563,8 +12566,8 @@ packages:
engines: {node: '>=6.0'} engines: {node: '>=6.0'}
dev: false dev: false
/chrono-node@2.7.0: /chrono-node@2.7.5:
resolution: {integrity: sha512-0s2vv89LmsbgoibV0AIVgNnGqlU8N5yCCVZXvc3mRCjnmlG/gJw1hCYOmNwjB+AIuwZQdKTXfwvsHDRTs6pwcg==} resolution: {integrity: sha512-VJWqFN5rWmXVvXAxOD4i0jX8Tb4cLswaslyaAFhxM45zNXPsZleygPbgiaYBD7ORb9fj07zBgJb0Q6eKL+0iJg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies: dependencies:
dayjs: 1.11.10 dayjs: 1.11.10
@ -13245,6 +13248,14 @@ packages:
whatwg-url: 11.0.0 whatwg-url: 11.0.0
dev: true dev: true
/date-fns-tz@2.0.0(date-fns@2.30.0):
resolution: {integrity: sha512-OAtcLdB9vxSXTWHdT8b398ARImVwQMyjfYGkKD2zaGpHseG2UPHbHjXELReErZFxWdSLph3c2zOaaTyHfOhERQ==}
peerDependencies:
date-fns: '>=2.0.0'
dependencies:
date-fns: 2.30.0
dev: false
/date-fns@2.30.0: /date-fns@2.30.0:
resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
engines: {node: '>=0.11'} engines: {node: '>=0.11'}