Skip to content

Commit

Permalink
feat: added support for custom handler functions in commonControls
Browse files Browse the repository at this point in the history
  • Loading branch information
Govinda Raju authored and Shreyas-vgr committed Oct 10, 2020
1 parent 58d7f45 commit 6ab3414
Show file tree
Hide file tree
Showing 8 changed files with 273 additions and 24 deletions.
36 changes: 31 additions & 5 deletions src/commonControls/DateControl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { Intent, IntentRequest } from 'ask-sdk-model';
import i18next from 'i18next';
import _ from 'lodash';
import { Strings as $ } from '../constants/Strings';
import { Control, ControlProps, ControlState } from '../controls/Control';
import { Control, ControlInputHandlingProps, ControlProps, ControlState } from '../controls/Control';
import { ControlInput } from '../controls/ControlInput';
import { ControlResultBuilder } from '../controls/ControlResult';
import { InteractionModelContributor } from '../controls/mixins/InteractionModelContributor';
Expand Down Expand Up @@ -108,6 +108,12 @@ export interface DateControlProps extends ControlProps {
* interaction model.
*/
interactionModel?: DateControlInteractionModelProps;

/**
* Props to customize the input handling functions to handle
* non standard inputs.
*/
inputHandling?: ControlInputHandlingProps;
}

/**
Expand Down Expand Up @@ -406,6 +412,9 @@ export class DateControl extends Control implements InteractionModelContributor
},
targets: [$.Target.Date, $.Target.It],
},
inputHandling: {
customHandlingFuncs: [],
},
validation: [],
confirmationRequired: false,
required: true,
Expand All @@ -416,15 +425,32 @@ export class DateControl extends Control implements InteractionModelContributor

// tsDoc - see Control
canHandle(input: ControlInput): boolean {
return (
const customHandleFuncs = this.props.inputHandling.customHandlingFuncs;
let customCanHandle: boolean = false;

for (const customHandler of customHandleFuncs) {
if (customHandler[0](input) === true) {
this.handleFunc = customHandler[1];
customCanHandle = true;
}
}

const builtInCanHandle: boolean =
this.isSetWithValue(input) ||
this.isSetWithoutValue(input) ||
this.isChangeWithValue(input) ||
this.isChangeWithoutValue(input) ||
this.isBareValue(input) ||
this.isConfirmationAffirmed(input) ||
this.isConfirmationDisaffirmed(input)
);
this.isConfirmationDisaffirmed(input);

if (customCanHandle && builtInCanHandle) {
log.warn(
'Custom canHandle function and built-in canHandle function both returned true. Turn on debug logging for more information',
);
}

return customCanHandle || builtInCanHandle;
}

private isSetWithValue(input: ControlInput): boolean {
Expand Down Expand Up @@ -658,7 +684,7 @@ export class DateControl extends Control implements InteractionModelContributor
}
}

private validateAndAddActs(
validateAndAddActs(
input: ControlInput,
resultBuilder: ControlResultBuilder,
elicitationAction: string,
Expand Down
34 changes: 31 additions & 3 deletions src/commonControls/NumberControl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
unpackSingleValueControlIntent,
} from '..';
import { Strings as $ } from '../constants/Strings';
import { Control, ControlProps, ControlState } from '../controls/Control';
import { Control, ControlInputHandlingProps, ControlProps, ControlState } from '../controls/Control';
import { ControlInput } from '../controls/ControlInput';
import { ControlResultBuilder } from '../controls/ControlResult';
import { InteractionModelContributor } from '../controls/mixins/InteractionModelContributor';
Expand Down Expand Up @@ -113,6 +113,12 @@ export interface NumberControlProps extends ControlProps {
* interaction model.
*/
interactionModel?: NumberControlInteractionModelProps;

/**
* Props to customize the input handling functions to handle
* non standard inputs.
*/
inputHandling?: ControlInputHandlingProps;
}

/**
Expand Down Expand Up @@ -382,13 +388,35 @@ export class NumberControl extends Control implements InteractionModelContributo
[19, 90],
], // TODO: generalize the default. in english it should suggest (113 <-> 130) etc.
required: true,
inputHandling: {
customHandlingFuncs: [],
},
};
return _.merge(defaults, props);
}

// tsDoc - see Control
canHandle(input: ControlInput): boolean {
return this.canHandleForEmptyStateValue(input) || this.canHandleForExistingStateValue(input);
const customHandleFuncs = this.props.inputHandling.customHandlingFuncs;
let customCanHandle: boolean = false;

for (const customHandler of customHandleFuncs) {
if (customHandler[0](input) === true) {
this.handleFunc = customHandler[1];
customCanHandle = true;
}
}

const builtInCanHandle: boolean =
this.canHandleForEmptyStateValue(input) || this.canHandleForExistingStateValue(input);

if (customCanHandle && builtInCanHandle) {
log.warn(
'Custom canHandle function and built-in canHandle function both returned true. Turn on debug logging for more information',
);
}

return customCanHandle || builtInCanHandle;
}

// tsDoc - see Control
Expand Down Expand Up @@ -952,7 +980,7 @@ export class NumberControl extends Control implements InteractionModelContributo
resultBuilder.addAct(new RequestValueAct(this));
}

private commonHandlerWhenValueChanged(
commonHandlerWhenValueChanged(
action: string,
input: ControlInput,
resultBuilder: ControlResultBuilder,
Expand Down
34 changes: 30 additions & 4 deletions src/commonControls/ValueControl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { Intent, IntentRequest } from 'ask-sdk-model';
import i18next from 'i18next';
import _ from 'lodash';
import { Strings as $ } from '../constants/Strings';
import { Control, ControlProps, ControlState } from '../controls/Control';
import { Control, ControlInputHandlingProps, ControlProps, ControlState } from '../controls/Control';
import { ControlInput } from '../controls/ControlInput';
import { ControlResultBuilder } from '../controls/ControlResult';
import { ControlStateDiagramming } from '../controls/mixins/ControlStateDiagramming';
Expand Down Expand Up @@ -114,6 +114,12 @@ export interface ValueControlProps extends ControlProps {
* interaction model.
*/
interactionModel?: ValueControlInteractionModelProps;

/**
* Props to customize the input handling functions to handle
* non standard inputs.
*/
inputHandling?: ControlInputHandlingProps;
}

/**
Expand Down Expand Up @@ -368,22 +374,42 @@ export class ValueControl extends Control implements InteractionModelContributor
requestValue: () => i18next.t('VALUE_CONTROL_DEFAULT_REPROMPT_REQUEST_VALUE'),
requestChangedValue: () => i18next.t('VALUE_CONTROL_DEFAULT_REPROMPT_REQUEST_CHANGED_VALUE'),
},
inputHandling: {
customHandlingFuncs: [],
},
};

return _.merge(defaults, props);
}

// tsDoc - see Control
canHandle(input: ControlInput): boolean {
return (
const customHandleFuncs = this.props.inputHandling.customHandlingFuncs;
let customCanHandle: boolean = false;

for (const customHandler of customHandleFuncs) {
if (customHandler[0](input) === true) {
this.handleFunc = customHandler[1];
customCanHandle = true;
}
}

const builtInCanHandle: boolean =
this.isSetWithValue(input) ||
this.isChangeWithValue(input) ||
this.isSetWithoutValue(input) ||
this.isChangeWithoutValue(input) ||
this.isBareValue(input) ||
this.isConfirmationAffirmed(input) ||
this.isConfirmationDisaffirmed(input)
);
this.isConfirmationDisaffirmed(input);

if (customCanHandle && builtInCanHandle) {
log.warn(
'Custom canHandle function and built-in canHandle function both returned true. Turn on debug logging for more information',
);
}

return customCanHandle || builtInCanHandle;
}

// tsDoc - see Control
Expand Down
36 changes: 32 additions & 4 deletions src/commonControls/dateRangeControl/DateRangeControl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import { IntentRequest } from 'ask-sdk-model';
import i18next from 'i18next';
import _ from 'lodash';
import { InputUtil, SingleValueControlIntent, StringOrList } from '../..';
import { ControlInputHandlingProps, InputUtil, SingleValueControlIntent, StringOrList } from '../..';
import { Strings as $ } from '../../constants/Strings';
import {
ContainerControl,
Expand Down Expand Up @@ -157,6 +157,12 @@ export interface DateRangeControlProps extends ContainerControlProps {
* interaction model.
*/
interactionModel?: DateRangeControlInteractionModelProps;

/**
* Props to customize the input handling functions to handle
* non standard inputs.
*/
inputHandling?: ControlInputHandlingProps;
}

/**
Expand Down Expand Up @@ -670,6 +676,9 @@ export class DateRangeControl extends ContainerControl implements InteractionMod
value: act.payload.value,
}),
},
inputHandling: {
customHandlingFuncs: [],
},
};

return _.mergeWith(defaults, props);
Expand Down Expand Up @@ -704,7 +713,26 @@ export class DateRangeControl extends ContainerControl implements InteractionMod

// tsDoc - see Control
async canHandle(input: ControlInput): Promise<boolean> {
return (await this.canHandleForFocus(input)) || this.canHandleForNoFocus(input);
const customHandleFuncs = this.props.inputHandling.customHandlingFuncs;
let customCanHandle: boolean = false;

for (const customHandler of customHandleFuncs) {
if (customHandler[0](input) === true) {
this.handleFunc = customHandler[1];
customCanHandle = true;
}
}

const builtInCanHandle: boolean | Promise<boolean> =
(await this.canHandleForFocus(input)) || this.canHandleForNoFocus(input);

if (customCanHandle && builtInCanHandle === true) {
log.warn(
'Custom canHandle function and built-in canHandle function both returned true. Turn on debug logging for more information',
);
}

return customCanHandle || builtInCanHandle;
}

// tsDoc - see Control
Expand Down Expand Up @@ -1057,7 +1085,7 @@ export class DateRangeControl extends ContainerControl implements InteractionMod
}
}

private isConfirmationAffirmed(input: ControlInput): any {
private isConfirmationAffirmed(input: ControlInput): boolean {
try {
okIf(InputUtil.isBareYes(input));
okIf(this.state.isConfirmingRange);
Expand Down Expand Up @@ -1087,7 +1115,7 @@ export class DateRangeControl extends ContainerControl implements InteractionMod
this.ackDateRangeValueChanged(resultBuilder);
}

private isConfirmationDisAffirmed(input: ControlInput): any {
private isConfirmationDisAffirmed(input: ControlInput): boolean {
try {
okIf(InputUtil.isBareNo(input));
okIf(this.state.isConfirmingRange === true);
Expand Down
36 changes: 31 additions & 5 deletions src/commonControls/listControl/ListControl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { Intent, IntentRequest, interfaces } from 'ask-sdk-model';
import i18next from 'i18next';
import _ from 'lodash';
import { Strings as $ } from '../../constants/Strings';
import { Control, ControlProps, ControlState } from '../../controls/Control';
import { Control, ControlInputHandlingProps, ControlProps, ControlState } from '../../controls/Control';
import { ControlInput } from '../../controls/ControlInput';
import { ControlResultBuilder } from '../../controls/ControlResult';
import { InteractionModelContributor } from '../../controls/mixins/InteractionModelContributor';
Expand Down Expand Up @@ -136,6 +136,12 @@ export interface ListControlProps extends ControlProps {
*/
interactionModel?: ListControlInteractionModelProps;

/**
* Props to customize the input handling functions to handle
* non standard inputs.
*/
inputHandling?: ControlInputHandlingProps;

/**
* Props to customize the APL generated by this control.
*/
Expand Down Expand Up @@ -523,14 +529,27 @@ export class ListControl extends Control implements InteractionModelContributor
enabled: true,
requestAPLDocument: generateTextListDocumentForListControl(),
},
inputHandling: {
customHandlingFuncs: [],
},
};

return _.merge(defaults, props);
}

// tsDoc - see Control
canHandle(input: ControlInput): boolean {
return (
const customHandleFuncs = this.props.inputHandling.customHandlingFuncs;
let customCanHandle: boolean = false;

for (const customHandler of customHandleFuncs) {
if (customHandler[0](input) === true) {
this.handleFunc = customHandler[1];
customCanHandle = true;
}
}

const builtInCanHandle: boolean =
this.isSetWithValue(input) ||
this.isChangeWithValue(input) ||
this.isSetWithoutValue(input) ||
Expand All @@ -540,8 +559,15 @@ export class ListControl extends Control implements InteractionModelContributor
this.isConfirmationAffirmed(input) ||
this.isConfirmationDisaffirmed(input) ||
this.isOrdinalScreenEvent(input) ||
this.isOrdinalSelection(input)
);
this.isOrdinalSelection(input);

if (customCanHandle && builtInCanHandle) {
log.warn(
'Custom canHandle function and built-in canHandle function both returned true. Turn on debug logging for more information',
);
}

return customCanHandle || builtInCanHandle;
}

// tsDoc - see Control
Expand Down Expand Up @@ -903,7 +929,7 @@ export class ListControl extends Control implements InteractionModelContributor
this.askElicitationQuestion(input, resultBuilder, $.Action.Set);
}

private validateAndAddActs(
validateAndAddActs(
input: ControlInput,
resultBuilder: ControlResultBuilder,
elicitationAction: string,
Expand Down
12 changes: 12 additions & 0 deletions src/controls/Control.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ export interface ControlState {
value?: any; //TODO: make mandatory to tighten the convention.
}

/**
* Base type for the customHandling Functions of a Control
*/
export interface ControlInputHandlingProps {
customHandlingFuncs?: Array<
[
(input: ControlInput) => boolean | Promise<boolean>,
(input: ControlInput, resultBuilder: ControlResultBuilder) => void | Promise<void>,
]
>;
}

/**
* Abstract base class for Controls.
*
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export {
ContainerControlProps,
ContainerControlState,
} from './controls/ContainerControl';
export { Control, ControlProps } from './controls/Control';
export { Control, ControlProps, ControlInputHandlingProps } from './controls/Control';
export { ControlInput } from './controls/ControlInput';
export { ControlManager, renderActsInSequence } from './controls/ControlManager';
export { ControlResult, ControlResultBuilder } from './controls/ControlResult';
Expand Down
Loading

0 comments on commit 6ab3414

Please sign in to comment.