Skip to content

Commit 222d8e5

Browse files
shreraju-amznShreyas-vgr
authored andcommitted
feat: Introduced a new optional prop in apl renderComponent to customize the APL component returned by a control
refactor: Changed the renderAPLComponent API signature. feat: Created new classes on control APL built-ins namespace for few default implementations of APL component mode. refactor: Removed the renderStyle concept in favour of above props and built-ins provided.
1 parent 2fd688a commit 222d8e5

File tree

8 files changed

+516
-249
lines changed

8 files changed

+516
-249
lines changed

demo/ComponentModeAPL/src/index.ts

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { SkillBuilders } from 'ask-sdk-core';
22
import { ControlInput, ControlResponseBuilder, ControlResult, NumberControl } from '../../../src';
33
import { MultiValueListControl } from '../../../src/commonControls/multiValueListControl/MultiValueListControl';
4+
import { MultiValueListControlComponentAPLBuiltIns } from '../../../src/commonControls/multiValueListControl/MultiValueListControlAPL';
45
import { ComponentModeControlManager } from '../../../src/controls/ComponentModeControlManager';
56
import { Control } from '../../../src/controls/Control';
67
import { ControlHandler } from '../../../src/runtime/ControlHandler';
@@ -60,6 +61,9 @@ export namespace ComponentModeDemo {
6061
interactionModel: {
6162
targets: ['builtin_choice', 'builtin_it', 'theme'],
6263
},
64+
apl: {
65+
renderComponent: MultiValueListControlComponentAPLBuiltIns.CheckBoxRenderer.default,
66+
},
6367
})),
6468
);
6569

@@ -136,13 +140,7 @@ export namespace ComponentModeDemo {
136140
left: '50px',
137141
width: '200px',
138142
height: '100px',
139-
items: [
140-
this.ageControl.renderAPLComponent(
141-
{ renderStyle: 'modalKeypad' },
142-
input,
143-
controlResponseBuilder,
144-
),
145-
],
143+
items: [this.ageControl.renderAPLComponent(input, controlResponseBuilder)],
146144
},
147145
{
148146
id: 'label2',
@@ -164,13 +162,7 @@ export namespace ComponentModeDemo {
164162
left: '50px',
165163
width: '200px',
166164
height: '100px',
167-
items: [
168-
this.guestsControl.renderAPLComponent(
169-
{ renderStyle: 'modalKeypad' },
170-
input,
171-
controlResponseBuilder,
172-
),
173-
],
165+
items: [this.guestsControl.renderAPLComponent(input, controlResponseBuilder)],
174166
},
175167
{
176168
id: 'label3',
@@ -193,11 +185,7 @@ export namespace ComponentModeDemo {
193185
width: '700px',
194186
height: '360px',
195187
items: [
196-
this.partyThemeControl.renderAPLComponent(
197-
{ renderStyle: 'aggregateDuplicates' },
198-
input,
199-
controlResponseBuilder,
200-
),
188+
this.partyThemeControl.renderAPLComponent(input, controlResponseBuilder),
201189
],
202190
},
203191

src/commonControls/listControl/ListControl.ts

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import _ from 'lodash';
1717
import { ModelData } from '../..';
1818
import { Strings as $ } from '../../constants/Strings';
1919
import {
20-
APLComponentProps,
2120
Control,
2221
ControlInputHandler,
2322
ControlInputHandlingProps,
@@ -62,7 +61,7 @@ import { DeepRequired } from '../../utils/DeepRequired';
6261
import { InputUtil } from '../../utils/InputUtil';
6362
import { defaultIntentToValueMapper } from '../../utils/IntentUtils';
6463
import { falseIfGuardFailed, okIf, StateConsistencyError } from '../../utils/Predicates';
65-
import { ListControlAPLPropsBuiltIns, ListControlComponentAPLBuiltIns, ListStyles } from './ListControlAPL';
64+
import { ListControlAPLPropsBuiltIns, ListControlComponentAPLBuiltIns } from './ListControlAPL';
6665

6766
// TODO: feature: support "what are my choices"
6867
// TODO: feature: voice pagination of choices.
@@ -369,7 +368,12 @@ export class ListControlPromptProps {
369368
export type AplContent = { document: { [key: string]: any }; dataSource: { [key: string]: any } };
370369
export type AplContentFunc = (control: ListControl, input: ControlInput) => AplContent;
371370
export type AplDocumentPropNewStyle = AplContent | AplContentFunc;
372-
371+
export type AplRenderComponentFunc = (
372+
control: ListControl,
373+
props: ListAPLComponentProps,
374+
input: ControlInput,
375+
resultBuilder: ControlResponseBuilder,
376+
) => { [key: string]: any };
373377
/**
374378
* Props associated with the APL produced by ListControl.
375379
*/
@@ -386,6 +390,23 @@ export class ListControlAPLProps {
386390
*/
387391
requestValue?: AplDocumentPropNewStyle;
388392
requestChangedValue?: AplDocumentPropNewStyle;
393+
394+
/**
395+
* Determines the APL Component rendering mode.
396+
*
397+
* Usage:
398+
*
399+
* 1) Use pre-defined built-ins under ListControlComponentAPLBuiltIns.* namespace which provides both default
400+
* implementations and customization of props(ListAPLComponentProps) to render an APL component.
401+
*
402+
* e.g renderComponent: ListControlComponentAPLBuiltIns.ImageListRenderer.default --- Default Implementation
403+
* renderComponent: ListControlComponentAPLBuiltIns.ImageListRenderer.of(props: ListAPLComponentProps) --- Override few properties
404+
*
405+
* 2) Provide a custom function which returns an APL component.
406+
*
407+
* Default: ListControlComponentAPLBuiltIns.TextListRenderer.default
408+
*/
409+
renderComponent?: AplRenderComponentFunc;
389410
}
390411

391412
/**
@@ -401,12 +422,7 @@ interface LastInitiativeState {
401422
/**
402423
* Props to customize ListControl APLComponent rendering.
403424
*/
404-
export interface ListAPLComponentProps extends APLComponentProps {
405-
/**
406-
* Defines the render style of APL component produced by the control.
407-
*/
408-
renderStyle: ListStyles;
409-
425+
export interface ListAPLComponentProps {
410426
/**
411427
* Boolean to determine to highlight user selected choice from the
412428
* list of items.
@@ -633,6 +649,7 @@ export class ListControl extends Control implements InteractionModelContributor
633649
requestChangedValue: ListControlAPLPropsBuiltIns.defaultSelectValueAPLContent({
634650
valueRenderer: props.valueRenderer ?? ListControl.defaultValueRenderer(),
635651
}),
652+
renderComponent: ListControlComponentAPLBuiltIns.TextListRenderer.default,
636653
},
637654
};
638655

@@ -1303,17 +1320,12 @@ export class ListControl extends Control implements InteractionModelContributor
13031320
}
13041321
}
13051322

1306-
renderAPLComponent(
1307-
props: ListAPLComponentProps,
1308-
input: ControlInput,
1309-
resultBuilder: ControlResponseBuilder,
1310-
): { [key: string]: any } {
1311-
return ListControlComponentAPLBuiltIns.renderComponent(
1312-
this,
1313-
{ ...props, valueRenderer: this.props.valueRenderer },
1314-
input,
1315-
resultBuilder,
1316-
);
1323+
renderAPLComponent(input: ControlInput, resultBuilder: ControlResponseBuilder): { [key: string]: any } {
1324+
const aplRenderFunc = this.props.apl.renderComponent;
1325+
const defaultProps: ListAPLComponentProps = {
1326+
valueRenderer: this.props.valueRenderer,
1327+
};
1328+
return aplRenderFunc.call(this, this, defaultProps, input, resultBuilder);
13171329
}
13181330

13191331
private evaluateAPLPropNewStyle(prop: AplDocumentPropNewStyle, input: ControlInput): AplContent {

src/commonControls/listControl/ListControlAPL.ts

Lines changed: 103 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import i18next from 'i18next';
2+
import _ from 'lodash';
23
import { ControlResponseBuilder } from '../..';
34
import { ControlInput } from '../../controls/ControlInput';
45
import { AplContent, ListAPLComponentProps, ListControl, ListControlRenderedItem } from './ListControl';
@@ -117,24 +118,18 @@ export namespace ListControlAPLPropsBuiltIns {
117118
}
118119
}
119120

120-
export type ListStyles = 'textList' | 'imageList';
121-
121+
/**
122+
* Namespace which define built-in renderers for APL Component Mode.
123+
*/
122124
export namespace ListControlComponentAPLBuiltIns {
123-
export function renderComponent(
124-
control: ListControl,
125-
props: ListAPLComponentProps,
126-
input: ControlInput,
127-
resultBuilder: ControlResponseBuilder,
128-
) {
129-
if (props.renderStyle === 'textList') {
130-
return renderTextList(control, props, input, resultBuilder);
131-
} else if (props.renderStyle === 'imageList') {
132-
return renderImageList(control, props, input, resultBuilder);
133-
} else {
134-
throw new Error('Invalid render style');
135-
}
136-
}
137-
125+
/**
126+
* Function which returns an APL component using ImageListLayout.
127+
*
128+
* @param control - ListControl
129+
* @param props - Control context props e.g valueRenderer
130+
* @param input - Input
131+
* @param resultBuilder - Result builder
132+
*/
138133
export function renderImageList(
139134
control: ListControl,
140135
props: ListAPLComponentProps,
@@ -288,6 +283,14 @@ export namespace ListControlComponentAPLBuiltIns {
288283
};
289284
}
290285

286+
/**
287+
* Function which returns an APL component using TextListLayout.
288+
*
289+
* @param control - ListControl
290+
* @param props - Control context props e.g valueRenderer
291+
* @param input - Input
292+
* @param resultBuilder - Result builder
293+
*/
291294
export function renderTextList(
292295
control: ListControl,
293296
props: ListAPLComponentProps,
@@ -365,4 +368,87 @@ export namespace ListControlComponentAPLBuiltIns {
365368
listItems,
366369
};
367370
}
371+
372+
/**
373+
* Defines TextListRenderer for APLComponentMode.
374+
*/
375+
export class TextListRenderer {
376+
/**
377+
* Provides a default implementation of textList with default props.
378+
*
379+
* @param control - ListControl
380+
* @param defaultProps - props
381+
* @param input - Input
382+
* @param resultBuilder - Result builder
383+
*/
384+
static default = (
385+
control: ListControl,
386+
defaultProps: ListAPLComponentProps,
387+
input: ControlInput,
388+
resultBuilder: ControlResponseBuilder,
389+
) => renderTextList(control, defaultProps, input, resultBuilder);
390+
391+
/**
392+
* Provides customization over `renderTextList()` arguments where the input
393+
* props overrides the defaults.
394+
*
395+
* @param props - props
396+
*/
397+
static of(props: ListAPLComponentProps) {
398+
return (
399+
control: ListControl,
400+
defaultProps: ListAPLComponentProps,
401+
input: ControlInput,
402+
resultBuilder: ControlResponseBuilder,
403+
) => {
404+
// Merges the user-provided props with the default props.
405+
// Any property defined by the user-provided data overrides the defaults.
406+
const mergedProps = _.merge(defaultProps, props);
407+
return renderTextList(control, mergedProps, input, resultBuilder);
408+
};
409+
}
410+
}
411+
412+
/**
413+
* Defines ImageListRenderer for APLComponentMode.
414+
*/
415+
export class ImageListRenderer {
416+
/**
417+
* Provides a default implementation of imageList with default props.
418+
*
419+
* @param control - ListControl
420+
* @param defaultProps - props
421+
* @param input - Input
422+
* @param resultBuilder - Result builder
423+
*/
424+
static default = (
425+
control: ListControl,
426+
defaultProps: ListAPLComponentProps,
427+
input: ControlInput,
428+
resultBuilder: ControlResponseBuilder,
429+
) => renderImageList(control, { ...defaultProps, highlightSelected: true }, input, resultBuilder);
430+
431+
/**
432+
* Provides customization over `renderImageList()` arguments where the input
433+
* props overrides the defaults.
434+
*
435+
* @param props - props
436+
*/
437+
static of(props: ListAPLComponentProps) {
438+
return (
439+
control: ListControl,
440+
defaultProps: ListAPLComponentProps,
441+
input: ControlInput,
442+
resultBuilder: ControlResponseBuilder,
443+
) => {
444+
// Assign defaults to props.
445+
defaultProps.highlightSelected = true;
446+
447+
// Merges the user-provided props with the default props.
448+
// Any property defined by the user-provided data overrides the defaults.
449+
const mergedProps = _.merge(defaultProps, props);
450+
return renderImageList(control, mergedProps, input, resultBuilder);
451+
};
452+
}
453+
}
368454
}

0 commit comments

Comments
 (0)