Related
this is my first time asking a question with stackoverflow, but I'm stuck on this problem for too many days.
My question, how can I change the initialConfig.editorState to the stringifiedEditorState that I just save in my database?
So far, I'm using Lexical, a Facebook text editor with React/Next.js. I was able to create an editor and save it to my mongodb database as a JSON string.
{
"root": {
"children": [
{
"children": [
{ "detail": 0, "format": 1, "mode": "normal", "style": "", "text": "Test", "type": "text", "version": 1 }
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "paragraph",
"version": 1
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "root",
"version": 1
}
}
I want to be able to read the Json value that I save to my mongodb database with a new read only lexical editor.
function onChange(editorState: any) {
editorState.read(() => {
const stringifiedEditorState = JSON.stringify(editorState.toJSON());
setValue(stringifiedEditorState);
});
}
const initialConfig = {
namespace: "editeurConfig",
theme: editeurTheme,
onError: onError,
nodes: [ListNode, ListItemNode, AutoLinkNode, LinkNode],
readOnly: true,
editorState: null
};
My question again, how can I change the initialConfig.editorState to the stringifiedEditorState that I just save in my database?
On editor initialization
You can simply pass the serialized string into the initial state of the editor via the editorState key.
For example:
// your config
const editorConfig = {
// the rest of your config...
editorState: editorStateJSONString,
};
// inside your return statement
<LexicalComposer initialConfig={editorConfig}>
{/* Your plugins */}
</LexicalComposer>
The caveat is that:
Note that Lexical uses initialConfig.editorState only once (when it's
being initialized) and passing different value later won't be
reflected in editor
From: https://lexical.dev/docs/concepts/editor-state
So it depends on the timing of initializing the editor and when you retrieve the database data.
After editor initialization
It appears you can use setEditorState to update state after initialization:
Another way to set state is setEditorState method, which replaces
current state with the one passed as an argument.
For example:
const editorState = editor.parseEditorState(editorStateJSONString);
editor.setEditorState(editorState);
From: https://lexical.dev/docs/concepts/editor-state#updating-state
For more details see: https://lexical.dev/docs/concepts/editor-state
I'm trying to create a slide show (2-3 images) using the Alexa authoring tool.I have managed to do this using the APL Pager which displays a series of components one at a time. The thing is that in order to switch from image A to image B..C I have to touch the screen and swipe left/right.
i want to make this happen automatically and have alexa swicth the images within a certain time, and it seems that this can be achieved using APL autopage but for some reason this is not working 😩
What I've done
Set up the APL using the APL pager
Added the auto page to the APL document
Component Id
duration
delay
After trying the simulation and directly in an echo show 5 it still only triggers when the display is touched.
Also tried:
Adding the standard command (auto pager) directly in the handler of alexa but same response.
Some doubts
Does it matter if i put the commands in the APLdocument.json[1] file or directly in the handler when i call .addDirective[2]..the only difference i see if i want the content or duration to be dynamic i should put it directly in the backend code(index.js) right?
[1]
{
"type": "APL",
"version": "1.4",
"settings": {},
"theme": "light",
"import": [],
"resources": [],
"styles": {},
"onMount": [],
"graphics": {},
"commands": [
{
"type": "AutoPage",
"componentId": "fisrtpager",
"duration": 1000,
"delay": 500
}
],
[2]
handlerInput.responseBuilder.addDirective({
type: 'Alexa.Presentation.APL.RenderDocument',
token:'arrugas',
document: physiolift,
commands: [{
"type": "AutoPage",
"componentId": "fisrtpager",
"duration": 1000,
"delay": 500
}]
});
}
Expected outPut
Have Alexa (echo show 5) to display a series of images like a carousel (without the need to touch the screen)
My code
APL Document
{
"type":"APL",
"version":"1.4",
"settings":{
},
"theme":"light",
"import":[
],
"resources":[
],
"styles":{
},
"onMount":[
],
"graphics":{
},
"commands":[
{
"type":"AutoPage",
"componentId":"fisrtpager",
"duration":1000,
"delay":500
}
],
"layouts":{
},
"mainTemplate":{
"parameters":[
"payload"
],
"items":[
{
"type":"Pager",
"id":"fisrtpager",
"width":"100%",
"height":"100%",
"items":[
{
"type":"Image",
"width":"100%",
"height":"100%",
"scale":"best-fill",
"source":"https://dyl80ryjxr1ke.cloudfront.net/external_assets/hero_examples/hair_beach_v1785392215/original.jpeg",
"align":"center"
},
{
"type":"Image",
"width":"100%",
"height":"100%",
"source":"https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg",
"scale":"best-fill"
},
{
"type":"Text",
"text":"Just text content shown on page #3",
"textAlign":"center"
}
],
"navigation":"wrap"
}
]
}
}
index.js
// somewhere inside the intent im invoking
if (Alexa.getSupportedInterfaces(handlerInput.requestEnvelope)['Alexa.Presentation.APL']) {
// Create Render Directive.
handlerInput.responseBuilder.addDirective({
type: 'Alexa.Presentation.APL.RenderDocument',
token:'arrugas',
document: require('./documents/ImageTest.json')
});
}
speakOutput += ' just saying somthing'
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt('just saying something else')
.getResponse();
Just add the command in the "onMount" event handler. Here is the modified code which does exactly what you need:
{
"type": "APL",
"version": "1.4",
"settings": {},
"theme": "light",
"import": [],
"resources": [],
"styles": {},
"onMount": [],
"graphics": {},
"layouts": {},
"mainTemplate": {
"parameters": [
"payload"
],
"items": [
{
"type": "Pager",
"id": "fisrtpager",
"width": "100%",
"height": "100%",
"items": [
{
"type": "Image",
"width": "100%",
"height": "100%",
"scale": "best-fill",
"source": "https://dyl80ryjxr1ke.cloudfront.net/external_assets/hero_examples/hair_beach_v1785392215/original.jpeg",
"align": "center"
},
{
"type": "Image",
"width": "100%",
"height": "100%",
"source": "https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg",
"scale": "best-fill"
},
{
"type": "Text",
"text": "Just text content shown on page #3",
"textAlign": "center"
}
],
"navigation": "none",
"onMount": [{
"type": "AutoPage",
"componentId": "fisrtpager",
"duration": 1000,
"delay": 500
}]
}
]
}
}
to update dynamically this feature from your backend code you can do the following:
// check if device supports APL
if (Alexa.getSupportedInterfaces(handlerInput.requestEnvelope)['Alexa.Presentation.APL']) {
// Create Render Directive.
handlerInput.responseBuilder.addDirective({
type: 'Alexa.Presentation.APL.RenderDocument',
token: "dialogManagementPagerDoc",
document: require('./PATH-TO/YOUR-APL-FILE.json')
})
.addDirective({
type: "Alexa.Presentation.APL.ExecuteCommands",
token: "dialogManagementPagerDoc",
commands: [
{
type: "AutoPage",
componentId: "YOUR_PAGER_ID",
delay: 1000,
duration: 5000
}
]
});
}
I am able to read this JSON file but I am not able to read object URI JSON file. How can I use Object URI JSON File?
And this is the way I tried to read Uri json object
componentDidMount(){
const { match: { params } } = this.props;
axios.get(params.uri).then((res)=>{
const question = res.data;
console.log(question);
this.setState({ question });
})
}
This is JSON file where Object URI contains a JSON file so how to read
[
{
"id": 59413,
"thumbnail": {
"id": "60255",
"title": "dornoch-castle-whisky-bar",
"alt": "dornoch-castle-whisky-bar",
"url": "https://media-magazine.trivago.com/wp-content/uploads/2019/01/23144800/dornoch-castle-whisky-bar.jpg",
"courtesy": "",
"position": "center"
},
"thumbnail_url": "https://media-magazine.trivago.com/wp-content/uploads/2019/01/23144800/dornoch-castle-whisky-bar.jpg",
"slug": "dornoch-castle-scotland-whisky",
"uri": "http://trivago-magazine-work-sample-server.s3-website.eu-central-1.amazonaws.com/dornoch-castle-scotland-whisky.json",
"title": "Dornoch Castle: A Whisky Tasting at One of the World's Most Popular Hotel Bars",
"card_title": "Whisky Tasting at Dornoch Castle in the Scottish Highlands",
"show_publish_date": false,
"date": "January 29th, 2019",
"newsletter_popup": false,
"newsletter_popup_header_image": false,
"taxonomies": {
"destinations": [
{
"name": "Europe",
"uri": "/destination/international/europe",
"slug": "europe",
"term_id": 1384
}
],
"themes": [],
"types": [
{
"name": "Nature",
"uri": "/type/nature",
"slug": "nature",
"term_id": 1380
}
]
},
"excerpt": "Dornoch Castle has amassed a whisky collection unlike most any other in the world. trivago Magazine Editor, Joe Baur, signs up for their whisky tasting. Video below."
},
In your specific case, it's an array of objects. so res.data[0] would be the first element, res.data[0]['uri'] would be the url of the json object. If you want to get that JSON from that URL, you'll just need to pass that value into axios to load the JSON.
axios.get(res.data[0]['uri']).then((res)=>{...})
Not sure on your use case, but that should give you access to the information in the res variable in the callback.
I am working on setting up my site authentication settings to use the AAD provider. Most of the template is respected. However, the unauthenticatedClientAction and allowedAudiences is not being properly assigned. I observe 'allow anonymous' and no 'allowed audiences' being assigned.
Please note that I was working with the ARM Template API 2018-02-01. This problem may still exist due to the documentation, if you provide an answer, please note the ARM Template version it addresses.
Additionally, create an issue for the ARM documentation team to correct any issues.
Here is my template segment for these settings. It is nested under resources in my website template.
root > Microsoft.Web/Site > Resources
{
"type": "config",
"name": "web",
"apiVersion": "2016-08-01",
"location": "[parameters('app-location')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('web-site-name'))]"
],
"properties": {
"siteAuthEnabled": true,
"siteAuthSettings": {
"enabled": true,
"unauthenticatedClientAction": "RedirectToLoginPage",
"tokenStoreEnabled": true,
"defaultProvider": "AzureActiveDirectory",
"clientId": "[parameters('web-aad-client-id')]",
"issuer": "[concat('https://sts.windows.net/', parameters('web-aad-tenant'))]",
"allowedAudiences": [
"[concat('https://', variables('web-site-name'), '.azurewebsites.net')]"
]
}
}
}
Template Validates
Deployment does not output any errors
Issues:
unauthenticatedClientAction is assigned allow anonymous not RedirectToLoginPage
allowedAudiences is not assigned any sites
What could be causing these issues? What could I have missed?
I got my answer after working with the fine people at Azure Support.
Please note that this solution targets API 2018-02-01 which was the current version at the time of this post.
This sub-resource is no longer a valid solution, while the endpoint may still recognize some of its fields, this is deprecated.
The new solution is to add the siteAuthSettings object to the main 'Microsoft.Web/site' properties and the siteAuthEnabled is no longer needed as siteAuthSettings.enable duplicates this functionality.
Updated ARM Template (removed other settings for brevity)
{
"name": "[variables('app-service-name')]",
"type": "Microsoft.Web/sites",
"location": "[parameters('app-location')]",
"apiVersion": "2016-08-01",
"dependsOn": [
"[variables('app-plan-name')]"
],
"properties": {
//... other app service settings
"siteAuthSettings": {
"enabled": true,
"unauthenticatedClientAction": "RedirectToLoginPage",
"tokenStoreEnabled": true,
"defaultProvider": "AzureActiveDirectory",
"clientId": "[parameters('web-aad-client-id')]",
"issuer": "[concat('https://sts.windows.net/', parameters('web-aad-tenant'))]",
"allowedAudiences": [
"[concat('https://', variables('web-site-name'), '.azurewebsites.net')]"
]
}
}
}
As suggested by #Michael, the siteAuthSettings object must be added to the siteConfig object, not just under the root properties object.
{
"apiVersion": "2019-08-01",
"name": "[variables('webAppName')]",
"type": "Microsoft.Web/sites",
"kind": "app",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('appServiceName'))]"
],
"properties": {
...
"siteConfig": {
"siteAuthSettings": {
"enabled": true,
"unauthenticatedClientAction": "RedirectToLoginPage",
"tokenStoreEnabled": true,
"defaultProvider": "AzureActiveDirectory",
"clientId": "[parameters('clientId')]",
"issuer": "[concat('https://sts.windows.net/', parameters('tenantId'), '/')]"
}
}
}
}
The other solutions given only apply when using the classic authentication experience (Authentication (Classic)). If you would like to use the new authentication experience, use below configuration:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"apiVersion": "2019-08-01",
"name": "[variables('webAppName')]",
"type": "Microsoft.Web/sites",
"kind": "app",
"location": "[resourceGroup().location]",
"resources": [
{
"type": "config",
"apiVersion": "2020-12-01",
"name": "authsettingsV2",
"location": "[resourceGroup().location]",
"dependsOn": [
"[concat('Microsoft.Web/sites/', variables('webAppName'))]"
],
"properties": {
"platform": {
"enabled": true,
"runtimeVersion": "~1"
},
"identityProviders": {
"azureActiveDirectory": {
"isAutoProvisioned": false,
"registration": {
"clientId": "[parameters('clientId')]",
"clientSecret": "[variables('clientSecret')]",
"openIdIssuer": "[concat('https://sts.windows.net/', parameters('tenantId'), '/v2.0')]"
},
"validation": {
"allowedAudiences": [
"https://management.core.windows.net/"
]
}
}
},
"login": {
"routes": {},
"tokenStore": {
"enabled": true,
"tokenRefreshExtensionHours": 72,
"fileSystem": {},
"azureBlobStorage": {}
},
"preserveUrlFragmentsForLogins": false,
"allowedExternalRedirectUrls": [],
"cookieExpiration": {
"convention": "FixedTime",
"timeToExpiration": "08:00:00"
},
"nonce": {
"validateNonce": true,
"nonceExpirationInterval": "00:05:00"
}
},
"globalValidation": {
"redirectToProvider": "azureactivedirectory",
"unauthenticatedClientAction": "RedirectToLoginPage"
},
"httpSettings": {
"requireHttps": true,
"routes": {
"apiPrefix": "/.auth"
},
"forwardProxy": {
"convention": "NoProxy"
}
}
}
}
]
}
]
}
Is it possible to create a react element object manually without using react.createElement.
The idea is to create nested react elements tree while streaming from html. The problem is I am unaware of nested children during streaming.
My objective is to be able to create a react element from a nested object. ie:
{
   "tag": "div",
   "attribs": {},
   "children": [
      {
         "tag": "p",
         "attribs": {},
         "children": [],
         "text": "test"
      },
      {
         "tag": "div",
         "attribs": {},
         "children": [
            {
               "tag": "p",
               "attribs": {},
               "children": [],
               "text": "hi"
            }
         ]
      }
   ]
}
You can also create nested components by using React.createElement, but you need to follow a special syntax to achieve that.
tag needs to be type and attribs need to be props, but you may iterate over your object and rename those keys if needed, so that's not the problem.
Now having something like this:
var data = {
"type": "div",
"props": {anyProp: true},
"children": [
{
"type": "p",
"props": {},
"children": [],
"text": "test"
},
{
"type": "div",
"props": {},
"children": [
{
"type": "p",
"props": {},
"children": [],
"text": "hi"
}
]
}
]
}
You can just use React.createElement(data.type, data.props, data.children); to create a component including all children, properties et cetera.