Skip to content

Commit 331811c

Browse files
authored
copy changes for for-each (#1223)
## TL;DR * What's new * Copy changes for: * link to guide * message for suggestions when variable dropdown is empty ## Screenshots <img width="636" height="721" alt="Screenshot 2025-09-22 at 5 42 40 PM" src="https://github.com/user-attachments/assets/84775815-579d-44a4-b109-343e76bbda66" /> <img width="1146" height="350" alt="Screenshot 2025-09-22 at 5 43 03 PM" src="https://github.com/user-attachments/assets/e0174f67-fe64-436c-8e56-86a37b91699c" />
1 parent ae21fc1 commit 331811c

File tree

11 files changed

+98
-5
lines changed

11 files changed

+98
-5
lines changed

packages/backend/src/apps/toolbox/actions/for-each/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,21 @@ const action: IRawAction = {
2626
description: 'Repeat actions for each item',
2727
groupsLaterSteps: true,
2828
isNew: true,
29+
linkToGuide:
30+
'https://guide.plumber.gov.sg/user-guides/actions/for-each-item-coming-soon',
2931
arguments: [
3032
{
3133
label: 'Choose items',
3234
description:
33-
'Supported items include rows in Tiles/M365 Excel and FormSG checkboxes',
35+
'Items you can choose from: Find multiple rows, Find multiple table rows, or checkboxes/table from your form.',
3436
key: 'items',
3537
type: 'string' as const,
3638
required: true,
3739
variables: true,
3840
variableTypes: ['array', 'table'],
3941
singleVariableSelection: true,
42+
noVariablesMessage:
43+
' No variables available - add/check one of the following steps above: Find multiple rows, Find multiple table rows, or include a checkbox/table field in your FormSG.',
4044
},
4145
],
4246

packages/backend/src/graphql/schema.graphql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ type Action {
167167
groupsLaterSteps: Boolean
168168
setupMessage: SetupMessage
169169
isNew: Boolean
170+
linkToGuide: String
170171
substeps: [ActionSubstep]
171172
}
172173

@@ -206,6 +207,7 @@ type ActionSubstepArgument {
206207
hiddenIf: FieldVisibilityCondition
207208
addRowButtonText: String
208209
tooltipText: String
210+
noVariablesMessage: String
209211

210212
# Only for string and multiline
211213
singleVariableSelection: Boolean
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { IAction, ITrigger } from '@plumber/types'
2+
3+
import { MdLightbulbOutline, MdOpenInNew } from 'react-icons/md'
4+
import { Flex, HStack, Icon, Link, Text } from '@chakra-ui/react'
5+
import { Infobox } from '@opengovsg/design-system-react'
6+
7+
interface LearnFromGuideInfoboxProps {
8+
selectedActionOrTrigger: IAction | ITrigger | undefined
9+
}
10+
11+
export default function LearnFromGuideInfobox(
12+
props: LearnFromGuideInfoboxProps,
13+
) {
14+
const { selectedActionOrTrigger } = props
15+
const { linkToGuide } = selectedActionOrTrigger || {}
16+
17+
if (!linkToGuide) {
18+
return null
19+
}
20+
21+
return (
22+
<>
23+
<Infobox
24+
icon={<Icon as={MdLightbulbOutline} color="primary.500" />}
25+
style={{
26+
borderRadius: '0.25rem',
27+
backgroundColor: '#FEF8FB',
28+
marginBottom: '1rem',
29+
}}
30+
>
31+
<Flex flexDir={{ base: 'column', md: 'row' }} gap={2} flex={1}>
32+
Learn how to set this up!{' '}
33+
<Link href={linkToGuide} isExternal>
34+
<HStack spacing={1}>
35+
<Text>Read our guide</Text>
36+
<Icon as={MdOpenInNew} boxSize={4} />
37+
</HStack>
38+
</Link>
39+
</Flex>
40+
</Infobox>
41+
</>
42+
)
43+
}

packages/frontend/src/components/EditorRightDrawer/Step.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import { useStepMetadata } from '@/hooks/useStepMetadata'
1414

1515
import FlowStepConfigurationModal from '../FlowStepConfigurationModal'
1616

17+
import LearnFromGuideInfobox from './LearnFromGuideInfobox'
18+
1719
type StepProps = {
1820
step: IStep
1921
isLastStep: boolean
@@ -72,6 +74,9 @@ export default function Step(props: StepProps): React.ReactElement | null {
7274
onSubmit={handleSubmit}
7375
resolver={stepValidationSchema}
7476
>
77+
<LearnFromGuideInfobox
78+
selectedActionOrTrigger={selectedActionOrTrigger}
79+
/>
7580
{/* Place ChooseConnectionSubstep outside the accordion structure */}
7681
{hasConnection && app && (
7782
<ChooseConnectionSubstep

packages/frontend/src/components/InputCreator/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export default function InputCreator(props: InputCreatorProps): JSX.Element {
4343
type,
4444
placeholder,
4545
tooltipText,
46+
noVariablesMessage,
4647
} = schema
4748

4849
const computedName = namePrefix ? `${namePrefix}.${name}` : name
@@ -119,6 +120,7 @@ export default function InputCreator(props: InputCreatorProps): JSX.Element {
119120
placeholder={placeholder}
120121
variablesEnabled={variables}
121122
isRich
123+
noVariablesMessage={noVariablesMessage}
122124
/>
123125
)
124126
}
@@ -139,6 +141,7 @@ export default function InputCreator(props: InputCreatorProps): JSX.Element {
139141
parentType={parentType}
140142
autoFocus={autoFocus}
141143
singleVariableSelection={schema.singleVariableSelection}
144+
noVariablesMessage={noVariablesMessage}
142145
/>
143146
)
144147
}

packages/frontend/src/components/NewsDrawer/NewsItemList.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import dedent from 'dedent'
22

33
import * as URLS from '@/config/urls'
44

5+
import ForEachAnimation from './assets/For-EachGraphic.json'
56
import IfThenAnimation from './assets/If-ThenGraphic.json'
67
import { NewsItemProps } from './NewsItem'
78
import { NEW_ENHANCEMENT_TAG, NEW_FEATURE_TAG } from './NewsItemTag'
@@ -10,15 +11,30 @@ const IF_THEN_EXTERNAL_LINK =
1011
'https://guide.plumber.gov.sg/user-guides/actions/toolbox'
1112

1213
export const NEWS_ITEM_LIST: NewsItemProps[] = [
14+
{
15+
date: '2025-09-22',
16+
tag: NEW_FEATURE_TAG,
17+
title: `For each item — automate reminders for events, tasks and more!`,
18+
details: dedent`
19+
This action is used to repeat actions on multiple items at a time. Items can be rows in your tiles table/M365 tables or FormSG checkboxes/table rows. Example use case shown below: Send individualised emails to a list of event attendees to remind them about an upcoming event.
20+
21+
Get started instantly:
22+
* Try our **Schedule reminders to a list of emails** template
23+
* Read our [guide](https://guide.plumber.gov.sg/user-guides/actions/for-each-item-coming-soon)
24+
`,
25+
multimedia: {
26+
animationData: ForEachAnimation,
27+
},
28+
},
1329
{
1430
date: '2025-06-25',
1531
tag: NEW_ENHANCEMENT_TAG,
1632
title: `We've made FormSG integration a lil' better`,
1733
details: dedent`
18-
👓 **Clearer variable names**
34+
👓 **Clearer variable names**
1935
FormSG variables now reflect the actual question text, making them easier to recognise at a glance.
2036
21-
🧹 **Less clutter, fewer mistakes**
37+
🧹 **Less clutter, fewer mistakes**
2238
Question text variables are now hidden by default to reduce visual noise and prevent accidental clicks.
2339
2440
🔄 **Easier data switching**

packages/frontend/src/components/NewsDrawer/assets/For-EachGraphic.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

packages/frontend/src/components/RichTextEditor/Suggestions.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ import SuggestionsWrapper from '../SuggestionsWrapper'
99
interface SuggestionsProps {
1010
data: StepWithVariables[]
1111
onSuggestionClick: (variable: Variable) => void
12+
noVariablesMessage?: string
1213
}
1314

1415
function Suggestions(props: SuggestionsProps) {
15-
const { data, onSuggestionClick = () => null } = props
16+
const { data, onSuggestionClick = () => null, noVariablesMessage } = props
1617
const [current, setCurrent] = useState<number>(0)
1718

1819
const isEmpty = data.reduce(
@@ -23,7 +24,8 @@ function Suggestions(props: SuggestionsProps) {
2324
if (isEmpty) {
2425
return (
2526
<Text p={4} opacity={0.5} textStyle="body-1" color="base.content.medium">
26-
No variables available - complete earlier steps to use them here
27+
{noVariablesMessage ??
28+
'No variables available - complete earlier steps to use them here'}
2729
</Text>
2830
)
2931
}

packages/frontend/src/components/RichTextEditor/index.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ interface EditorProps {
9999
parentType?: string
100100
autoFocus?: boolean
101101
singleVariableSelection?: boolean
102+
noVariablesMessage?: string
102103
}
103104
const Editor = ({
104105
onChange,
@@ -112,6 +113,7 @@ const Editor = ({
112113
parentType,
113114
singleVariableSelection,
114115
autoFocus = false,
116+
noVariablesMessage,
115117
}: EditorProps) => {
116118
const { priorExecutionSteps } = useContext(StepExecutionsContext)
117119
const { allApps } = useContext(EditorContext)
@@ -319,6 +321,7 @@ const Editor = ({
319321
<Suggestions
320322
data={stepsWithVariables}
321323
onSuggestionClick={(v) => editable && handleVariableClick(v)}
324+
noVariablesMessage={noVariablesMessage}
322325
/>
323326
</PopoverContent>
324327
</Portal>
@@ -344,6 +347,7 @@ interface RichTextEditorProps {
344347
parentType?: string
345348
autoFocus?: boolean
346349
singleVariableSelection?: boolean
350+
noVariablesMessage?: string
347351
}
348352
const RichTextEditor = ({
349353
required,
@@ -360,6 +364,7 @@ const RichTextEditor = ({
360364
parentType,
361365
autoFocus,
362366
singleVariableSelection,
367+
noVariablesMessage,
363368
}: RichTextEditorProps) => {
364369
const { readOnly } = useContext(EditorContext)
365370
const { control, getValues } = useFormContext()
@@ -407,6 +412,7 @@ const RichTextEditor = ({
407412
parentType={parentType}
408413
autoFocus={shouldAutoFocus}
409414
singleVariableSelection={singleVariableSelection}
415+
noVariablesMessage={noVariablesMessage}
410416
/>
411417
)}
412418
/>

packages/frontend/src/graphql/queries/get-apps.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ export const GET_APPS = gql`
175175
}
176176
groupsLaterSteps
177177
isNew
178+
linkToGuide
178179
substeps {
179180
key
180181
name
@@ -194,6 +195,7 @@ export const GET_APPS = gql`
194195
customStyle
195196
tooltipText
196197
value
198+
noVariablesMessage
197199
options {
198200
label
199201
description

0 commit comments

Comments
 (0)