I am creating Alexa echo show skill, I have created one sample Alexa skill without lambda function that hits myserver api and I return response in Alexa accepted format like below:
{
"version": "1.0",
"sessionAttributes": {},
"response": {
"outputSpeech": {
"type": "PlainText",
"text": "My output speech"
},
"card": {
"type": "Simple",
"title": "hELLO",
"content": "Meetings"
},
"reprompt": {
"outputSpeech": {
"type": "PlainText",
"text": "Can I help you with anything else?"
}
},
"shouldEndSession": false
}
}
Till now my skill working fine, But now I want to show a template over the echo show that is possible with APL(Alexa Programming Language).
I am not getting APL examples without lambda function, I have tried to add some APL response json from the example that i got and put into above response json that is not working.
I am confused with APL, Should i just need to add some attribute only in the above response or need to use sdk at my server that is running with PHP whose sdk i did not find at the portal.
Please help me
If you want to send an APL document, you have to send a directive to the JSON
{
"body": {
"version": "1.0",
"response": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak>Hello world, change me</speak>"
},
"directives": [
{
"type": "Alexa.Presentation.APL.RenderDocument",
"token": "TemplateTypescript",
"document": {
"type": "APL",
"version": "1.7",
"license": "Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.\nSPDX-License-Identifier: LicenseRef-.amazon.com.-AmznSL-1.0\nLicensed under the Amazon Software License http://aws.amazon.com/asl/",
"theme": "dark",
"import": [
{
"name": "alexa-layouts",
"version": "1.4.0"
}
],
"resources": [
{
"description": "Default dimensions, numbers and strings for the AlexaHeadline.",
"dimensions": {
"primaryTextMaxWidth": "100%",
"secondaryTextMaxWidth": "100%",
"secondaryTextTopPadding": "#spacingXSmall",
"contentPaddingLeft": "#marginHorizontal"
},
"numbers": {
"headlinePrimaryTextMaxLines": 2
},
"strings": {
"textComponentAlign": "center"
}
},
{
"description": "Dimensions for the AlexaHeadline - hubLandscapeLarge.",
"when": "${#viewportProfile == #hubLandscapeLarge}",
"numbers": {
"headlinePrimaryTextMaxLines": 4
}
},
{
"description": "Dimensions for the AlexaHeadline - hubRound.",
"when": "${#viewportProfileCategory == #hubRound}",
"dimensions": {
"secondaryTextTopPadding": "#spacing3XSmall"
}
},
{
"description": "Dimensions for the AlexaHeadline - tvLandscapeOverlay/tvLandscapeXLarge.",
"when": "${#viewportProfile == #tvLandscapeXLarge || #viewportProfile == #tvLandscapeOverlay}",
"dimensions": {
"primaryTextMaxWidth": "560dp",
"secondaryTextMaxWidth": "560dp",
"secondaryTextTopPadding": "#spacing3XSmall"
}
},
{
"description": "Dimensions for the AlexaHeadline - tvLandscapeXLarge.",
"when": "${#viewportProfile == #tvLandscapeXLarge}",
"numbers": {
"headlinePrimaryTextMaxLines": 4
}
},
{
"description": "Dimensions, numbers and strings for the AlexaHeadline - tvPortraitOverlay.",
"when": "${#viewportProfile == #tvPortraitOverlay}",
"dimensions": {
"primaryTextMaxWidth": "220dp",
"secondaryTextMaxWidth": "220dp",
"contentPaddingLeft": "#spacing2XLarge"
},
"strings": {
"textComponentAlign": "left"
}
},
{
"description": "Dimensions, numbers and strings for the AlexaHeadline - mobileSmall portrait.",
"when": "${#viewportProfile == #mobileSmall && #viewportOrientation == #viewportOrientationPortrait}",
"numbers": {
"headlinePrimaryTextMaxLines": 4
}
},
{
"description": "Dimensions, numbers and strings for the AlexaHeadline - mobileMedium.",
"when": "${#viewportProfile == #mobileMedium}",
"dimensions": {
"primaryTextMaxWidth": "758dp"
},
"numbers": {
"headlinePrimaryTextMaxLines": 4
}
},
{
"description": "Dimensions, numbers and strings for the AlexaHeadline - mobileLarge.",
"when": "${#viewportProfile == #mobileLarge}",
"dimensions": {
"primaryTextMaxWidth": "1025dp"
},
"numbers": {
"headlinePrimaryTextMaxLines": 4
}
},
{
"description": "Dimensions, numbers and strings for the AlexaHeadline - hubPortraitMedium.",
"when": "${#viewportProfile == #hubPortraitMedium}",
"numbers": {
"headlinePrimaryTextMaxLines": 4
}
},
{
"description": "Dimensions, numbers and strings for the AlexaHeadline - hubLandscapeXLarge.",
"when": "${#viewportProfile == #hubLandscapeXLarge}",
"dimensions": {
"primaryTextMaxWidth": "1440dp"
},
"numbers": {
"headlinePrimaryTextMaxLines": 4
}
}
],
"styles": {
"primaryTextLight": {
"extends": "textStyleDisplay4",
"values": [
{
"color": "#colorTextReversed"
}
]
},
"secondaryTextLight": {
"extends": "textStyleCallout",
"values": [
{
"color": "#colorTextReversed"
}
]
}
},
"layouts": {
"AlexaHeadline": {
"parameters": [
{
"name": "theme",
"description": "Colors will be switched depending on the specified theme (light/dark). Default to dark theme",
"type": "string",
"default": "dark"
},
{
"name": "primaryText",
"description": "Primary message",
"type": "string"
},
{
"name": "secondaryText",
"description": "secondary message",
"type": "string"
},
{
"name": "headerAttributionOpacity",
"type": "number",
"default": "${#viewportProfileCategory == #hubRound ? 1 : #opacitySecondary}"
},
{
"name": "headerTitle",
"description": "Primary text to render in header.",
"type": "string"
},
{
"name": "headerSubtitle",
"description": "Secondary text to render in header.",
"type": "string"
},
{
"name": "headerAttributionText",
"description": "Attribution text to render in header. Only shown when no headerAttributionImage is provided, and when headerAttributionPrimacy is true, or on a device that shows Title/Subtitle and Attribution.",
"type": "string"
},
{
"name": "headerAttributionImage",
"description": "URL for attribution image source. Only shown when headerAttributionPrimacy is true, or on a device that shows Title/Subtitle and Attribution.",
"type": "string"
},
{
"name": "headerAttributionPrimacy",
"description": "On devices that can only display one element due to screen size, Attribution is prioritized. Setting False displays Title/Subtitle. Defaults to true.",
"type": "boolean",
"default": true
},
{
"name": "headerDivider",
"description": "Toggle to display the divider that appears at the bottom of header to help separate it from the content below. Default to false",
"type": "boolean",
"default": false
},
{
"name": "headerBackButton",
"description": "Toggle to display back button in header. Defaults to false.",
"type": "boolean",
"default": false
},
{
"name": "headerBackButtonAccessibilityLabel",
"description": "An accessibility label to describe the back button to customers who use a screen reader.",
"type": "string"
},
{
"name": "headerBackButtonCommand",
"description": "Command that is issued when back button is pressed.",
"type": "any",
"default": {
"type": "SendEvent",
"arguments": ["goBack"]
}
},
{
"name": "headerBackgroundColor",
"description": "Optional color value to use as background color for Header. Defaults to transparent.",
"type": "color",
"default": "transparent"
},
{
"name": "backgroundColor",
"description": "Color value to use as background color for layout.",
"type": "color"
},
{
"name": "backgroundImageSource",
"description": "URL for background image source.",
"type": "string"
},
{
"name": "backgroundVideoSource",
"description": "URL for background video source.",
"type": "any"
},
{
"name": "backgroundScale",
"description": "Image/video scale to apply to background image/video. Defaults to best-fill.",
"type": "string",
"default": "best-fill"
},
{
"name": "backgroundAlign",
"description": "Image/video alignment to apply to background image/video. Defaults to center.",
"type": "string",
"align": "center"
},
{
"name": "backgroundBlur",
"description": "Toggle to apply background blur. Defaults to false.",
"type": "boolean",
"default": false
},
{
"name": "backgroundColorOverlay",
"description": "Toggle to apply overlay scrim to background image/video. Defaults to false.",
"type": "boolean",
"default": false
},
{
"name": "backgroundOverlayGradient",
"description": "Toggle to apply gradient to background image/video. Defaults to false.",
"type": "boolean",
"default": false
},
{
"name": "backgroundVideoAutoPlay",
"description": "Toggle to autoplay background video(s). Defaults to false.",
"type": "boolean",
"default": false
},
{
"name": "backgroundVideoAudioTrack",
"description": "Audio track to play on. Defaults to foreground. EM can select foreground | background | none.",
"type": "string",
"default": "foreground"
},
{
"name": "footerHintText",
"type": "string",
"description": "Hint text to display in Footer."
},
{
"name": "entities",
"description": "Array of entity data bind to this layout",
"type": "any"
},
{
"name": "layoutDirection",
"description": "The layoutDirection of AlexaHeadline. It can be LTR or RTL. By default, it uses environment layoutDirection.",
"type": "string",
"default": "${environment.layoutDirection}"
},
{
"name": "lang",
"description": "The lang property of AlexaHeadline. Set the lang property to a BCP-47 string (e.g., en-US). By default, it uses environment lang.",
"type": "string",
"default": "${environment.lang}"
}
],
"items": [
{
"type": "Container",
"layoutDirection": "${layoutDirection}",
"height": "100vh",
"entities": "${entities}",
"items": [
{
"type": "AlexaBackground",
"backgroundColor": "${backgroundColor}",
"backgroundImageSource": "${backgroundImageSource}",
"backgroundVideoSource": "${backgroundVideoSource}",
"backgroundScale": "${backgroundScale}",
"backgroundAlign": "${backgroundAlign}",
"backgroundBlur": "${backgroundBlur}",
"colorOverlay": "${backgroundColorOverlay}",
"overlayGradient": "${backgroundOverlayGradient}",
"videoAutoPlay": "${backgroundVideoAutoPlay}",
"videoAudioTrack": "${backgroundVideoAudioTrack}"
},
{
"type": "Container",
"height": "100vh",
"width": "100vw",
"position": "absolute",
"items": [
{
"type": "Container",
"grow": 1,
"justifyContent": "center",
"paddingLeft": "#contentPaddingLeft",
"paddingRight": "#marginHorizontal",
"alignItems": "center",
"items": [
{
"when": "${primaryText && primaryText != ''}",
"type": "Text",
"style": "${theme == 'light' ? 'primaryTextLight' : 'textStyleDisplay4'}",
"text": "${primaryText}",
"opacity": 1,
"textAlign": "#textComponentAlign",
"maxWidth": "#primaryTextMaxWidth",
"maxLines": "#headlinePrimaryTextMaxLines"
},
{
"when": "${secondaryText && secondaryText != ''}",
"type": "Text",
"style": "${theme == 'light' ? 'secondaryTextLight' : 'textStyleCallout'}",
"text": "${secondaryText}",
"maxLines": 1,
"opacity": "#opacitySecondary",
"textAlign": "#textComponentAlign",
"maxWidth": "#secondaryTextMaxWidth",
"paddingTop": "#secondaryTextTopPadding"
}
]
},
{
"type": "AlexaHeader",
"theme": "${theme}",
"headerTitle": "${headerTitle}",
"layoutDirection": "${layoutDirection}",
"headerSubtitle": "${#viewportProfile != #tvLandscapeOverlay ? headerSubtitle : ''}",
"headerAttributionText": "${headerAttributionText}",
"headerAttributionImage": "${headerAttributionImage}",
"headerAttributionPrimacy": "${headerAttributionPrimacy}",
"headerDivider": "${headerDivider}",
"headerBackButton": "${headerBackButton}",
"headerBackButtonAccessibilityLabel": "${headerBackButtonAccessibilityLabel}",
"headerBackButtonCommand": "${headerBackButtonCommand}",
"headerBackgroundColor": "${headerBackgroundColor}",
"headerAttributionOpacity": "${headerAttributionOpacity}",
"position": "absolute",
"width": "100%",
"top": "0"
},
{
"when": "${#viewportProfileCategory != #hubRound && #viewportProfile != #tvLandscapeOverlay && footerHintText}",
"type": "AlexaFooter",
"hintText": "${footerHintText}",
"theme": "${theme}",
"lang": "${lang}",
"position": "absolute",
"width": "100%",
"bottom": "0"
}
]
}
]
}
]
}
},
"mainTemplate": {
"parameters": ["payload"],
"item": [
{
"type": "AlexaHeadline",
"id": "PlantHeadline",
"primaryText": "${payload.headlineTemplateData.properties.textContent.primaryText.text}",
"headerBackButton": false,
"headerAttributionImage": "${payload.headlineTemplateData.properties.logoUrl}",
"headerAttributionPrimacy": true,
"footerHintText": "${payload.headlineTemplateData.properties.hintText}",
"backgroundImageSource": "${payload.headlineTemplateData.properties.backgroundImage.sources[0].url}",
"backgroundColorOverlay": false,
"speech": "${payload.headlineTemplateData.properties.welcomeSpeech}",
"theme": "light"
}
]
},
"onMount": [
{
"type": "SpeakItem",
"componentId": "PlantHeadline"
}
]
},
"datasources": {
"headlineTemplateData": {
"type": "object",
"objectId": "headlineSample",
"properties": {
"backgroundImage": {
"sources": [
{
"url": "https://d2o906d8ln7ui1.cloudfront.net/images/templates_v3/headline/HeadlineBackground_Light.png",
"size": "large"
}
]
},
"textContent": {
"primaryText": {
"type": "PlainText",
"text": "Welcome to Template Typescript"
}
},
"logoUrl": "",
"hintText": ""
}
}
},
"timeoutType": "SHORT"
}
],
"reprompt": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak>Hello world, change me</speak>"
}
},
"shouldEndSession": false,
"type": "_DEFAULT_RESPONSE"
},
"sessionAttributes": {},
"userAgent": "ask-node/2.11.0 Node/v12.22.4"
}
}
You can use https://apl.ninja/ or within the developer console to help you get started quickly.
Related
For some reason vega is reading my data as 0 when the numbers range from 1-234.
I am attempting to show a visualisation of a chloropleth map of crypto-ownership by country.
The countries have been ranked 1-234 and that is meant to show on the tooltip however, this is being shown as 0 on the tooltip. How do I fix this.
Here is my code:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"title":{
"text": "Crypto Ownership Worldwide",
"subtitle": "Source: FILL",
"anchor": "start"
},
"width":500,
"height":400,
"data": {
"url": "https://raw.githubusercontent.com/tomiwav/tomiwav.github.io/main/custom.geo%20(3).json",
"format":{"property": "features"}
},
"projection":{"type": "mercator"},
"transform": [
{
"lookup":"properties.name",
"from":{
"key": "Country",
"fields": ["Rank"],
"data":{
"url": "https://raw.githubusercontent.com/tomiwav/tomiwav.github.io/main/datarank.csv",
"format":{"type":"csv"}
}
}
}
],
"mark":{
"type": "geoshape",
"fill":"lightgray",
"stroke":"black",
"strokeWidth":0.5
},
"encoding": {
"color": {
"field": "Rank",
"type": "quantitative",
"scale": {
"domain":[234,1],
"scheme": "oranges"
}
},
"tooltip":[
{"field":"properties.name", "title":"Country"},
{"field":"Rank","type":"quantitative","title":"Number of Crypto Owners","format":".2f"}
]
},
"config": {"mark": {"invalid": null}
}
}
Your lookup was failing. You need a lower case "c" on country.
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"title": {
"text": "Crypto Ownership Worldwide",
"subtitle": "Source: FILL",
"anchor": "start"
},
"width": 500,
"height": 400,
"data": {
"url": "https://raw.githubusercontent.com/tomiwav/tomiwav.github.io/main/custom.geo%20(3).json",
"format": {"property": "features"}
},
"projection": {"type": "mercator"},
"transform": [
{
"lookup": "properties.name",
"from": {
"key": "country",
"fields": ["Rank"],
"data": {
"url": "https://raw.githubusercontent.com/tomiwav/tomiwav.github.io/main/datarank.csv",
"format": {"type": "csv"}
} }
}
],
"mark": {
"type": "geoshape",
"fill": "lightgray",
"stroke": "black",
"strokeWidth": 0.5
},
"encoding": {
"color": {
"field": "Rank",
"type": "quantitative",
"scale": {"domain": [234, 1], "scheme": "oranges"}
},
"tooltip": [
{"field": "properties.name", "title": "Country"},
{
"field": "Rank",
"type": "quantitative",
"title": "Number of Crypto Owners",
"format": ".2f"
}
]
},
"config": {"mark": {"invalid": null}}
}
I have an Alexa audio and visual response that is returned on the first launch of an Alexa App. I use a transformer to embed the APLA document. Up until recently this was working.
This is the APL document:
{
"type": "APL",
"version": "2022.1",
"license": "Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.\nSPDX-License-Identifier: LicenseRef-.amazon.com.-AmznSL-1.0\nLicensed under the Amazon Software License http://aws.amazon.com/asl/",
"theme": "dark",
"import": [
{
"name": "alexa-layouts",
"version": "1.5.0"
}
],
"onMount": [
{
"type": "SpeakItem",
"componentId": "initialAPLAcomponent"
}
],
"resources": [
{
"description": "Default resource definitions for Video template",
"dimensions": {
"videoHeight": "55%",
"videoPaddingTop": "80dp",
"videoWidth": "70vw",
"videoControlPaddingBottom": "0dp",
"videoSliderPaddingBottom": "80dp"
}
},
{
"when": "${#viewportProfile == #hubLandscapeLarge}",
"dimensions": {
"videoHeight": "60%",
"videoPaddingTop": "110dp",
"videoControlPaddingBottom": "10dp",
"videoSliderPaddingBottom": "90dp"
}
},
{
"when": "${#viewportProfile == #hubLandscapeSmall || #viewportProfile == #hubRoundSmall}",
"dimensions": {
"videoHeight": "50%",
"videoPaddingTop": "70dp",
"videoControlPaddingBottom": "15dp"
}
}
],
"commands": {
"ToggleVideoOverlay": {
"parameters": [
"componentId",
"show"
],
"commands": [
{
"type": "Sequential",
"commands": [
{
"when": "${show}",
"type": "SetValue",
"componentId": "${componentId}",
"property": "display",
"value": "normal"
},
{
"type": "AnimateItem",
"easing": "ease-in-out",
"duration": 1000,
"componentId": "${componentId}",
"value": [
{
"property": "opacity",
"from": "${show ? 0 : 0.5}",
"to": "${show ? 0.5 : 0}"
}
]
},
{
"when": "${!show}",
"type": "SetValue",
"componentId": "${componentId}",
"property": "display",
"value": "none"
}
]
}
]
},
"ToggleVideoControls": {
"parameters": [
"componentId",
"direction",
"show"
],
"commands": [
{
"type": "Sequential",
"commands": [
{
"type": "AnimateItem",
"easing": "ease-in-out",
"duration": 1000,
"componentId": "${componentId}",
"value": [
{
"property": "opacity",
"from": "${show ? 0 : 1}",
"to": "${show ? 1 : 0}"
},
{
"property": "transform",
"from": [
{
"translateY": "${!show ? 0 : (direction == 'down' ? -50 : 50)}"
}
],
"to": [
{
"translateY": "${show ? 0 : (direction == 'down' ? 50 : -50)}"
}
]
}
]
},
{
"type": "SetValue",
"property": "videoControlsDisplay",
"value": "${show ? true : false}"
}
]
}
]
}
},
"layouts": {
"VideoPlayer": {
"parameters": [
{
"name": "backgroundImageSource",
"description": "URL for the background image source in fullscreen.",
"type": "string"
},
{
"name": "displayFullscreen",
"description": "Select to display video in fullscreen. Video controls will be displayed on tap.",
"type": "boolean",
"default": false
},
{
"name": "headerTitle",
"description": "Title text to render in the header.",
"type": "string"
},
{
"name": "headerSubtitle",
"description": "Subtitle Text to render in the header.",
"type": "string"
},
{
"name": "headerAttributionImage",
"description": "URL for attribution image or logo source (PNG/vector).",
"type": "string"
},
{
"name": "videoControlType",
"description": "The type of video control to use. Default is skip (foward and backwards).",
"type": "string",
"default": "skip"
},
{
"name": "videoSources",
"description": "Video single source or an array of sources. Videos will be in a playlist if multiple sources are provided.",
"type": "any"
},
{
"name": "sliderType",
"description": "Determinate for full control of the slider with transport control. Indeterminate is an ambient progress bar with animation.",
"type": "string",
"default": "determinate"
},
{
"name": "autoplay",
"type": "boolean",
"default": true,
"description": "Determines the starting state of the play/pause icon. This should match the autoplay state of the media playing component. Defaults to false. "
}
],
"item": {
"type": "Container",
"height": "100vh",
"width": "100vw",
"bind": [
{
"name": "sliderThumbPosition",
"type": "number",
"value": 0
},
{
"name": "sliderActive",
"type": "boolean",
"value": false
},
{
"name": "videoProgressValue",
"type": "number",
"value": 0
},
{
"name": "videoTotalValue",
"type": "number",
"value": 0
},
{
"name": "videoControlsDisplay",
"type": "boolean",
"value": false
}
],
"handleTick": [
{
"when": "${!sliderActive && displayFullscreen && videoControlsDisplay}",
"minimumDelay": 5000,
"description": "For video fullscreen view, hide video controls after 5 seconds of inactivity",
"commands": [
{
"type": "Parallel",
"sequencer": "ToggleVideoControlsSequencer",
"commands": [
{
"type": "ToggleVideoOverlay",
"componentId": "videoOverlay",
"show": false
},
{
"type": "ToggleVideoControls",
"componentId": "videoHeader",
"direction": "up",
"show": false
},
{
"type": "ToggleVideoControls",
"componentId": "videoControls",
"direction": "down",
"show": false
}
]
}
]
}
],
"items": [
{
"type": "AlexaBackground",
"id": "AlexaBackground",
"backgroundColor": "${backgroundColor}",
"backgroundImageSource": "${backgroundImageSource}"
},
{
"description": "Video container",
"type": "Container",
"height": "100%",
"width": "100%",
"position": "absolute",
"item": {
"type": "TouchWrapper",
"height": "100%",
"width": "100%",
"description": "Outer touch wrapper that brings up the controls",
"onPress": [
{
"when": "${displayFullscreen}",
"type": "Parallel",
"sequencer": "ToggleVideoControlsSequencer",
"commands": [
{
"type": "ToggleVideoOverlay",
"componentId": "videoOverlay",
"show": true
},
{
"type": "ToggleVideoControls",
"componentId": "videoHeader",
"direction": "down",
"show": true
},
{
"type": "ToggleVideoControls",
"componentId": "videoControls",
"direction": "up",
"show": true
}
]
}
],
"item": {
"type": "Container",
"height": "100%",
"width": "100%",
"alignItems": "center",
"item": {
"type": "Video",
"height": "${displayFullscreen ? '100%' : #videoHeight}",
"width": "${displayFullscreen ? '100%' : #videoWidth}",
"scale": "best-fill",
"autoplay": true,
"audioTrack": "foreground",
"id": "videoPlayerId",
"source": "${videoSources}",
"position": "absolute",
"top": "${displayFullscreen ? '0' : #videoPaddingTop}",
"onPlay": [
{
"type": "SetValue",
"property": "videoTotalValue",
"value": "${event.duration}"
},
{
"type": "SpeakItem",
"componentId": "initialAPLAcomponent"
}
],
"onTrackUpdate": [
{
"type": "SetValue",
"property": "videoTotalValue",
"value": "${event.duration}"
}
],
"onTimeUpdate": [
{
"type": "SetValue",
"property": "videoProgressValue",
"value": "${event.currentTime}"
},
{
"type": "SetValue",
"componentId": "slider",
"property": "progressValue",
"value": "${videoProgressValue}"
},
{
"type": "SetValue",
"property": "videoTotalValue",
"value": "${event.duration}"
}
],
"onTrackReady": [
{
"type": "SetValue",
"property": "videoTotalValue",
"value": "${event.duration}"
}
],
"onTrackFail": [
{
"type": "SetValue",
"property": "videoTotalValue",
"value": "0"
}
]
}
}
}
},
{
"description": "Header, slider, and controls container",
"type": "Container",
"height": "100%",
"width": "100%",
"items": [
{
"description": "Oveylay background for Video Controls",
"when": "${displayFullscreen}",
"type": "Frame",
"id": "videoOverlay",
"height": "100%",
"width": "100%",
"backgroundColor": "${viewport.theme == 'light' ? '#colorWhite' : '#colorBlack'}",
"position": "absolute",
"display": "none",
"opacity": 0
},
{
"when": "${#viewportProfileCategory != #hubRound}",
"type": "AlexaHeader",
"id": "videoHeader",
"opacity": "${displayFullscreen ? 0 : 1}",
"layoutDirection": "${environment.layoutDirection}",
"headerAttributionImage": "${headerAttributionImage}",
"headerTitle": "${headerTitle} ",
"headerSubtitle": "${headerSubtitle} ",
"headerAttributionPrimacy": true,
"width": "100%",
"theme": "${viewport.theme}"
},
{
"description": "Slider and controls",
"type": "Container",
"id": "videoControls",
"opacity": "${displayFullscreen ? 0 : 1}",
"width": "100%",
"position": "absolute",
"bottom": 0,
"items": [
{
"when": "${sliderType != 'indeterminate'}",
"type": "Container",
"alignItems": "center",
"item": [
{
"type": "AlexaSlider",
"id": "slider",
"progressValue": "${videoProgressValue}",
"totalValue": "${videoTotalValue}",
"positionPropertyName": "sliderThumbPosition",
"metadataDisplayed": true,
"metadataPosition": "above_right",
"width": "${#videoWidth + 5vw}",
"paddingBottom": "#videoSliderPaddingBottom",
"theme": "${viewport.theme}",
"onUpCommand": [
{
"type": "ControlMedia",
"componentId": "videoPlayerId",
"command": "seek",
"value": "${sliderThumbPosition - videoProgressValue}"
},
{
"delay": "1000",
"type": "SetValue",
"sequencer": "ToggleVideoControlsSequencer",
"property": "sliderActive",
"value": false
}
],
"onMoveCommand": [
{
"type": "SetValue",
"property": "sliderActive",
"value": true
}
],
"onDownCommand": [
{
"type": "SetValue",
"property": "sliderActive",
"value": true
}
]
},
{
"type": "AlexaTransportControls",
"mediaComponentId": "videoPlayerId",
"playPauseToggleButtonId": "playPauseToggleButtonId",
"primaryControlSize": "70dp",
"secondaryControls": "${videoControlType}",
"secondaryControlSize": "60dp",
"autoplay": true,
"position": "absolute",
"bottom": "#videoControlPaddingBottom",
"theme": "${viewport.theme}"
}
]
},
{
"when": "${sliderType == 'indeterminate'}",
"type": "Container",
"alignItems": "center",
"item": [
{
"type": "AlexaProgressBar",
"progressBarType": "indeterminate",
"width": "#videoWidth",
"paddingBottom": "#videoSliderPaddingBottom",
"theme": "${viewport.theme}"
}
]
}
]
}
]
}
]
}
},
"AudioTransform": {
"parameters": [
{
"name": "audioSource",
"type": "string"
}
],
"items": [
{
"type": "Container",
"items": [
{
"type": "Text",
"id": "initialAPLAcomponent",
"speech": "${audioSource}"
}
]
}
]
}
},
"mainTemplate": {
"parameters": [
"payload"
],
"items": [
{
"type": "VideoPlayer",
"backgroundImageSource": "${payload.videoPlayerTemplateData.properties.backgroundImage}",
"displayFullscreen": "${payload.videoPlayerTemplateData.properties.displayFullscreen}",
"headerAttributionImage": "${payload.videoPlayerTemplateData.properties.logoUrl}",
"headerTitle": "${payload.videoPlayerTemplateData.properties.headerTitle}",
"headerSubtitle": "${payload.videoPlayerTemplateData.properties.headerSubtitle}",
"videoControlType": "${payload.videoPlayerTemplateData.properties.videoControlType}",
"videoSources": "${payload.videoPlayerTemplateData.properties.videoSources}",
"sliderType": "${payload.videoPlayerTemplateData.properties.sliderType}"
},
{
"type": "AudioTransform",
"audioSource": "${payload.videoPlayerTemplateData.properties.outputAPLA.url}"
}
]
}
}
This is the datasource:
{
"videoPlayerTemplateData": {
"type": "object",
"properties": {
"backgroundImage": "",
"displayFullscreen": true,
"headerTitle": "",
"headerSubtitle": "",
"logoUrl": "https://my.png",
"videoControlType": "jump10",
"videoSources": [
"https://my.mp4"
],
"sliderType": "determinate"
},
"transformers": [
{
"template": "intialAPLA",
"outputName": "outputAPLA",
"transformer": "aplAudioToSpeech"
}
]
}
}
and this is the APLA source:
{
"intialAPLA": {
"type": "APLA",
"version": "0.91",
"mainTemplate": {
"parameters": [
"payload"
],
"item": [
{
"type": "Mixer",
"items": [
{
"type": "Sequencer",
"items": [
{
"type": "Audio",
"description": "sound from bank",
"source": "my.sound"
},
{
"type": "Speech",
"content": "myspeech "
}
]
},
{
"type": "Audio",
"source": "https://my.mp3",
"duration": "trimToParent",
"filter": [
{
"type": "Volume",
"amount": "50%"
},
{
"type": "FadeOut",
"duration": 2000
}
]
}
]
}
]
}
}
}
If I remove the video item from the main template the audio plays, so I know this is not an issue with the transformer. I've tried setting the speech attrbute of the video, in layouts, to be the transformer binding, and playing that onMount, but that doesn't work either.
It seems I can only play video or the audio, not both. This worked previously so I'm not sure what's changed.
Are you able to see why I can't return the video with the audio embedded?
I have created a form using below json configuration for react-jsonschema-form
{
"schema": {
"title": "Employee Detail",
"type": "object",
"required": ["name", "email", "country"],
"properties": {
"name": {
"type": "string",
"title": "Name",
"default": "",
"autoComplete": "off"
},
"email": {
"type": "string",
"title": "Email",
"default": ""
},
"registeredAddress": {
"type": "object",
"title": "Registered Address",
"properties": {
"line1": {
"type": "string",
"title": "Address Line1",
"default": ""
},
"line2": {
"type": "string",
"title": "Address Line2",
"default": ""
},
"city": {
"type": "string",
"title": "City",
"default": ""
},
"postal": {
"type": "string",
"title": "Postal",
"default": ""
},
"country": {
"type": "string",
"title": "Country",
"default": "",
"enum": ["IN", "PK", "CN"],
"enumNames": ["India", "Pakistan", "China"]
}
}
},
"isAddressDifferent": {
"type": "boolean",
"title": "Is Mailing Address different from Registered Address",
"default": false
},
"about": {
"type": "string",
"title": "About",
"default": "",
"autoComplete": "off"
}
},
"if": {
"properties": {
"isAddressDifferent": {
"const": true
}
}
},
"then": {
"properties": {
"mailingAddress": {
"type": "object",
"title": "Mailing Address",
"properties": {
"line1": {
"type": "string",
"title": "Address Line1",
"default": ""
}
}
}
}
}
}
}
I am hiding mailingAddress property on the basis of isAddressDifferent checkbox value, but I want to position mailingAddress on ui after that checkbox and above the about ui widget
Can anyone help me on this?
Below is the codesandbox url for code
https://codesandbox.io/s/rjfs-form-demo-mix96s?file=/src/custom-form/form-config.json
I've got this form with react-jsonschema-form
{
"type": "object",
"required": ["startDate", "endDate"],
"properties": {
"endDate": {
"type": "string",
"title": "Do",
"format": "date"
},
"startDate": {
"type": "string",
"title": "Od",
"format": "date"
},
"allDay": {
"type": "boolean",
"title": "All day",
"default": true
}
}
}
And I want to change the format of the fields based on the checkbox, something like this:
{
"type": "object",
"required": ["startDate", "endDate"],
"properties": {
"endDate": {
"type": "string",
"title": "Do",
"format": "date"
},
"startDate": {
"type": "string",
"title": "Od",
"format": "date"
},
"allDay": {
"type": "boolean",
"title": "All day",
"default": true
}
},
"allOf": [
{
"if": {
"properties": {
"allDay": false
}
},
"then": {
"properties": {
"endDate": {
"format": "date-time"
},
"startDate": {
"format": "date-time"
}
},
"required": ["startDate", "endDate"]
}
}
]
}
But it doesn't seem to work. I know that it can be done via a selectbox, but I want to use the checkbox.
Are there any possibilities to this problem?
I am working with MSW and OpenAPI-backend package.
I want to mock the booth browser server and test server.
I have OpenAPI definition available form with I generate generated.ts for RTK Query (out of scope for this question). I want to use OpenAPI spec to use it with OpenAPI Backend and generate MSW rest worker for browser and for test.
Setup is next:
index.tsx
import worker from './mocks/browser';
if (process.env.NODE_ENV === 'development') {
worker.start();
}
mock/browser.ts
import { setupWorker, rest } from 'msw';
import { OpenAPIBackend } from 'openapi-backend';
import type { Document } from 'openapi-backend';
import definition from './api.json';
// create our mock backend with openapi-backend
const api = new OpenAPIBackend({ definition: definition as Document });
api.register('notFound', (c, res, ctx) => res(ctx.status(404)));
api.registerHandler('notImplemented', async (c, req, res) => {
const { status, mock } = await api.mockResponseForOperation(
c.operation.operationId as string
);
return res.status(status).json(mock);
});
api.register('validationFail', (c, res, ctx) =>
res(ctx.status(400), ctx.json({ error: c.validation.errors }))
);
const worker = setupWorker(
rest.get('/*', (req) =>
api.handleRequest({
...req,
path: req.url.pathname,
headers: req.headers.all(),
method: req.method,
body: req.body,
})
)
);
export default worker;
api.JSON
{
"openapi": "3.0.1",
"info": {
"title": "Fetch API",
"description": "Source of truth for Fetch dashboard",
"version": "0.1.5"
},
"paths": {
"/config": {
"get": {
"tags": [
"Configuration"
],
"summary": "Retreive configuration object",
"description": "Returns configuration object (map) containing configuration parameters for UI (Map<String, String>)",
"responses": {
"200": {
"description": "successfull operation",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "Map serialized to json object.",
"example": {
"FA_COLOR": "red",
"FA_NAME": "fetch"
}
}
}
}
}
}
}
},
"/links": {
"get": {
"tags": [
"Notifications & Links",
"Walking Skeleton"
],
"summary": "List all defined links for hospital",
"description": "Retreives all defined links for hospital. Hospital ID is indirectly obtained from user identity.",
"responses": {
"200": {
"description": "successfull operation",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Link"
}
}
}
}
}
}
}
},
"/kpis": {
"get": {
"tags": [
"KPIS"
],
"summary": "List all KPIs for hospital(s) that current user is managing.",
"description": "Retreives all KPIs available for hospitals that current user is managing.",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/KPI"
}
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"KPI": {
"type": "object",
"properties": {
"id": {
"type": "string",
"enum": [
"revenue",
"labour"
]
},
"hospital_id": {
"type": "string",
"description": "id of hospital that this KPI describes"
},
"goal": {
"type": "number",
"description": "full month goal"
},
"actual": {
"type": "number",
"description": "actual result"
},
"mtd_goal": {
"type": "number",
"description": "month to date goal, so that we can track projected fulfillment of goal."
},
"details": {
"type": "object",
"description": "Semi-structured way of describing details of calculation. Every KPI will potentialiy be described differently."
}
},
"required": [
"id",
"hospital_id",
"goal",
"actual",
"mtd_goal"
]
},
"Link": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "unique id of link"
},
"hospital_id": {
"type": "string",
"description": "id of hospital that this Link is configured for"
},
"title": {
"type": "string",
"description": "human readable title for URL"
},
"description": {
"type": "string",
"description": "Description of current link (alt text , or tooltip)"
},
"url": {
"type": "string",
"description": "Location of external resource"
},
"urgent": {
"type": "boolean",
"description": "Is urgency of notification elevated?"
},
"count": {
"type": "number",
"description": "Actual notification value. How many 'tasks' are waiting manager in external system."
},
"updated_at": {
"type": "integer",
"description": "Date/time of last notification update",
"format": "int64"
},
"children": {
"type": "array",
"description": "Since notifications are possibly presented in hierarchy all children of this notification will be gathered here",
"items": {
"$ref": "#/components/schemas/Link"
}
}
},
"required": [
"id",
"hospital_id",
"title",
"url"
],
"example": [
{
"id": 1,
"hospital_id": "001",
"title": "Link1",
"description": "description of Link1",
"url": "https://www.example.com/link1",
"urgent": true,
"count": 1,
"updated_at": 1631113184221,
"children": [
{
"id": 2,
"hospital_id": "001",
"title": "Link2",
"description": "description of Link2",
"url": "https://www.example.com/link2",
"urgent": true,
"count": 1,
"updated_at": 1631113184221
}
]
},
{
"id": 3,
"hospital_id": "002",
"title": "Link3",
"description": "description of Link3",
"url": "https://www.example.com/link3",
"urgent": false,
"count": 2,
"updated_at": 1631113184221
}
]
}
}
}
}
component.tsx
const { data: links, error, isLoading } = useGetLinksQuery({});
Which is fethcing localhost:3000/links
Error I am getting is:
mockServiceWorker.js:222 [MSW] Uncaught exception in the request handler for "GET http://localhost:3000/links":
Error: Unknown operation
at OpenAPIValidator.validateRequest (http://localhost:3000/static/js/vendors~main.chunk.js:63911:13)
at OpenAPIBackend.<anonymous> (http://localhost:3000/static/js/vendors~main.chunk.js:54246:45)
at async OpenAPIBackend.handleRequest (http://localhost:3000/static/js/vendors~main.chunk.js:54152:22)
This exception has been gracefully handled as a 500 response, however, it's strongly recommended to resolve this error, as it indicates a mistake in your code. If you wish to mock an error response, please see this guide: https://mswjs.io/docs/recipes/mocking-error-responses
getResponse # mockServiceWorker.js:222
async function (async)
getResponse # mockServiceWorker.js:175
handleRequest # mockServiceWorker.js:113
async function (async)
handleRequest # mockServiceWorker.js:112
(anonymous) # mockServiceWorker.js:271
Network tabs give:
Request URL: http://localhost:3000/links
Request Method: GET
Status Code: 500 (from service worker)
Referrer Policy: strict-origin-when-cross-origin
All related to article: https://dev.to/epilot/testing-react-with-jest-and-openapi-mocks-8gc
and https://testing-library.com/docs/react-testing-library/example-intro/
Thank you.
In your OpenApi u don't have any operationId.
You need to setup a unique Id by route.
{
"openapi": "3.0.1",
"info": {
"title": "Fetch API",
"description": "Source of truth for Fetch dashboard",
"version": "0.1.5"
},
"paths": {
"/config": {
"get": {
"tags": [
"Configuration"
],
"operationId": "config",
"summary": "Retreive configuration object",
"description": "Returns configuration object (map) containing configuration parameters for UI (Map<String, String>)",
"responses": {
"200": {
"description": "successfull operation",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "Map serialized to json object.",
"example": {
"FA_COLOR": "red",
"FA_NAME": "fetch"
}
}
}
}
}
}
}
},
"/links": {
"get": {
"tags": [
"Notifications & Links",
"Walking Skeleton"
],
"operationId": "links",
"summary": "List all defined links for hospital",
"description": "Retreives all defined links for hospital. Hospital ID is indirectly obtained from user identity.",
"responses": {
"200": {
"description": "successfull operation",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Link"
}
}
}
}
}
}
}
},
"/kpis": {
"get": {
"tags": [
"KPIS"
],
"summary": "List all KPIs for hospital(s) that current user is managing.",
"description": "Retreives all KPIs available for hospitals that current user is managing.",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/KPI"
}
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"KPI": {
"type": "object",
"properties": {
"id": {
"type": "string",
"enum": [
"revenue",
"labour"
]
},
"hospital_id": {
"type": "string",
"description": "id of hospital that this KPI describes"
},
"goal": {
"type": "number",
"description": "full month goal"
},
"actual": {
"type": "number",
"description": "actual result"
},
"mtd_goal": {
"type": "number",
"description": "month to date goal, so that we can track projected fulfillment of goal."
},
"details": {
"type": "object",
"description": "Semi-structured way of describing details of calculation. Every KPI will potentialiy be described differently."
}
},
"required": [
"id",
"hospital_id",
"goal",
"actual",
"mtd_goal"
]
},
"Link": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "unique id of link"
},
"hospital_id": {
"type": "string",
"description": "id of hospital that this Link is configured for"
},
"title": {
"type": "string",
"description": "human readable title for URL"
},
"description": {
"type": "string",
"description": "Description of current link (alt text , or tooltip)"
},
"url": {
"type": "string",
"description": "Location of external resource"
},
"urgent": {
"type": "boolean",
"description": "Is urgency of notification elevated?"
},
"count": {
"type": "number",
"description": "Actual notification value. How many 'tasks' are waiting manager in external system."
},
"updated_at": {
"type": "integer",
"description": "Date/time of last notification update",
"format": "int64"
},
"children": {
"type": "array",
"description": "Since notifications are possibly presented in hierarchy all children of this notification will be gathered here",
"items": {
"$ref": "#/components/schemas/Link"
}
}
},
"required": [
"id",
"hospital_id",
"title",
"url"
],
"example": [
{
"id": 1,
"hospital_id": "001",
"title": "Link1",
"description": "description of Link1",
"url": "https://www.example.com/link1",
"urgent": true,
"count": 1,
"updated_at": 1631113184221,
"children": [
{
"id": 2,
"hospital_id": "001",
"title": "Link2",
"description": "description of Link2",
"url": "https://www.example.com/link2",
"urgent": true,
"count": 1,
"updated_at": 1631113184221
}
]
},
{
"id": 3,
"hospital_id": "002",
"title": "Link3",
"description": "description of Link3",
"url": "https://www.example.com/link3",
"urgent": false,
"count": 2,
"updated_at": 1631113184221
}
]
}
}
}
}