xmpp : How to read nested array data from xml using stanza.io - xmpp

I am receiving a stanza like this:
<message xmlns='jabber:client' to='1' from='2' type='chat' id='50c1d830-283c-11e8-9dcf' xmlns='jabber:client'>
<system xmlns='urn:xmpp:type' layout='layout1' default='true' subType='alert'>
<title>First User</title>
<email>support#abc.com</email>
<action_label>Contact us</action_label>
<deeplinks>
<deeplink>
<label>My deals</label>
<link>/home</link>
</deeplink>
<deeplink>
<label>New deals</label>
<link>/page</link>
</deeplink>
</deeplinks>
</system>
<body>[This is a system message]</body>
</message>
From this, I can read the type as system and its attribute like title, email, action_label, layout, subType, default attributes
const system = stanzas.define({
name: 'system',
element: 'system',
topLevel: true,
namespace: 'urn:xmpp:type',
fields: {
layout: stanzas.utils.attribute('layout'),
default: stanzas.utils.attribute('default'),
subType: stanzas.utils.attribute('subType'),
email: stanzas.utils.textSub('urn:xmpp:type', 'email'),
actionLabel: stanzas.utils.textSub('urn:xmpp:type', 'action_label'),
title: stanzas.utils.textSub('urn:xmpp:type', 'title')
}
});
stanzas.withMessage(Message => {
stanzas.extend(Message, system);
});
But I am not able to read the nested deeplink stanza.
Any suggestions how I can parse that data?

Related

React-Admin: <ReferenceField> is stuck in loading state, even though data fetch succeeds

I have problem with <ReferenceField>.
On my <List> page, I have rows with UserId and ToolId that I need reference. I want to show user name and tool code.
But these two columns get stuck in loading state, even though the dataProvider, GET_MANY request succeeded for users and tools.
When I console.log(data), it the data is all there but somehow it's not rendered into <ReferenceField>. And It no error is logged at all.
Any idea what am I doing wrong? Or what's happening?
ReferenceFields still loading
EDIT:
I have updated react-admin and now its not displaying loading bar, but just display nothing.
Here is code of List:
export const B_toolList = props => (
<List {...props}>
<Datagrid rowClick="edit">
<TextField source="id" />
<NumberField source="active" />
<NumberField source="time" />
<DateField source="createdAt" />
<DateField source="updatedAt" />
<ReferenceField source="UserId" reference="Users">
<TextField source="name" />
</ReferenceField>
<ReferenceField source="ToolId" reference="Tools">
<TextField source="code" />
</ReferenceField>
</Datagrid>
</List>
);
I also find out that if i try to inspect ReferenceField element with react-dev-tool, There are no values but just "Loading..." note.
But I dont know why... It looks to me that API response is OK.
API res:
Btools fetch:
(2) [{…}, {…}]
0:
ToolId: 1
UserId: 1
active: 1
createdAt: "2020-04-08T16:00:03.000Z"
id: 1
time: 1
updatedAt: "2020-04-08T16:00:03.000Z"
__proto__: Object
1:
ToolId: 1
UserId: 2
active: 1
createdAt: "2020-04-08T16:00:03.000Z"
id: 2
time: 1
updatedAt: "2020-04-08T16:00:03.000Z"
__proto__: Object
length: 2
__proto__: Array(0)
Than Users and Tools fetch:
(2) [{…}, {…}]
0: {id: 1, name: "Tomáš Princ", email: "p***#seznam.cz", createdAt: "2020-04-08T15:59:54.000Z", updatedAt: "2020-04-08T15:59:54.000Z"}
1: {id: 2, name: "jhfgjhfg", email: "admin#admin.cz", createdAt: "2020-04-08T18:44:16.000Z", updatedAt: "2020-04-08T18:44:16.000Z"}
length: 2
__proto__: Array(0)
[{…}]
0: {id: 1, code: "guhf", name: "jhfh", state: "ghf", free: 1, …}
length: 1
__proto__: Array(0)
I log this json data in DataProvider and return it like data: json
switch (type) {
case GET_LIST:
case GET_MANY:
case GET_MANY_REFERENCE:
console.log(json)
console.log(type)
if (!headers.has('content-range')) {
throw new Error(
'The Content-Range header is missing in the HTTP Response. The simple REST data provider expects responses for lists of resources to contain this header with the total number of results to build the pagination. If you are using CORS, did you declare Content-Range in the Access-Control-Expose-Headers header?'
);
}
console.log((headers.get('content-range')))
return {
data: json,
total:
//json.length,
parseInt(
headers
.get('content-range')
.split('/')
.pop(),
10
),
};
So it look like app have all data it needs, but for some reason still loading and waiting for something.
EDIT 2:
I tried little workaround by creating custom element, that load userId and toolId and fetches classic query get user/tool by ID for every row. It works.
const ToolCode = ({ record = {} }) => {
const dataProvider = useDataProvider();
const [tool, setTool] = useState();
const [loading, setLoading] = useState(true);
const [error, setError] = useState();
useEffect(() => {
dataProvider.getOne('tools', { id: record.ToolId })
.then(({ data }) => {
setTool(data);
setLoading(false);
})
.catch(error => {
setError(error);
setLoading(false);
})
}, []);
if (loading) return <Loading />;
if (error) return <Error />;
if (!tool) return null;
console.log("fetch tools")
return (
tool.code
)
};
const UserName = ({ record = {} }) => {
const dataProvider = useDataProvider();
const [user, setUser] = useState();
const [loading, setLoading] = useState(true);
const [error, setError] = useState();
useEffect(() => {
dataProvider.getOne('users', { id: record.UserId })
.then(({ data }) => {
setUser(data);
setLoading(false);
})
.catch(error => {
setError(error);
setLoading(false);
})
}, []);
if (loading) return <Loading />;
if (error) return <Error />;
if (!user) return null;
return (
user.name
)
};
const B_toolFilter = (props) => (
<Filter {...props}>
<TextInput label="Search" source="q" alwaysOn />
<TextInput label="Title" source="title" defaultValue="Hello, World!" />
</Filter>
);
export const B_toolList = props => (
<List {...props}>
<Datagrid rowClick="edit">
<TextField source="id" />
<NumberField source="active" />
<NumberField source="time" />
<DateField source="createdAt" />
<DateField source="updatedAt" />
<UserName source="UserId" />
<ToolCode source="ToolId" />
</Datagrid>
</List>
);
Now I can get tool code and user name by IDs form B_Tools, but its much less efficient than GET_MANY method used by ReferenceField..
Nwm. Whole time it was just about capital letters of Tools and Users in
<ReferenceField source="UserId" reference="Users">
and
<ReferenceField source="ToolId" reference="Tools">
I changes it to
<ReferenceField source="UserId" reference="users">
and
<ReferenceField source="ToolId" reference="tools">
Now it works!
I just still dont get why it fetched right resources... It is like it is not capital sensitive when it fetches data, but it is capital sensitive when it renders. I dont know.
Anyway, I would expect some kind of error message with mistake like this... not just right response and empty render.

How can I add rows or delete row dynamically in Lightening data table

//component
<aura:component controller="LookupRelatedContactC"
implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" >
<aura:attribute name="selectedLookUpRecord" type="sObject" default="{}"/>
<aura:attribute name="data" type="Object"/>
<aura:attribute name="columns" type="List"/>
<aura:attribute name="selectedRows" type="List"/>
<aura:attribute name="rowIndex" type="String"/>
<aura:attribute name="options" type="List" default="[
{'label': 'Contacts', 'value': 'option1'},
{'label': 'Opportunities', 'value': 'option2'}]"/>
<aura:attribute name="value" type="String" default="option1"/>
<aura:handler name="change" value="{!v.selectedLookUpRecord}" action="{!c.selectedLookupChanged}"/>
<lightning:card title = 'Search by Account Name' >
<c:LookupReusable_Parent objectAPIName="account" IconName="standard:account"
selectedRecord="{!v.selectedLookUpRecord}"
label="Accounts"/>
<lightning:radioGroup name="radioGroup"
label="Select any one of these"
options="{! v.options }"
value="{! v.value }"
type="radio"/>
<br/><br/>
<lightning:datatable columns="{! v.columns }"
data="{! v.data }"
keyField="id"
hideCheckboxColumn="true"
onrowaction="{!c.removeRecord}"/><br></br>
<lightning:button variant="brand" label="Save" title="Brand action" onclick="{! c.handleClick}" />
<lightning:button variant="brand" label="Add Row" title="Brand action" onclick="{! c.handleClick}" />
</lightning:card>
</aura:component>
//js controller
({
selectedLookupChanged:function(component, event, helper) {
component.set('v.columns', [
{label: 'Contact Name',
fieldName: 'Name',
editable: true,
type: 'text'},
{label: 'Phone',
fieldName: 'Phone',
type: 'phone'},
{label: "Action",type: "button", typeAttributes: {
label: 'Delete',
name: 'delete',
title: 'Delete',
disabled: false,
value: 'delete',
iconPosition: 'left'
}},
]);
var aId = component.get("v.selectedLookUpRecord").Id;
var action=component.get('c.getCon');
action.setParams({accId : aId});
action.setCallback(this, function(response){
var state = response.getState();
if (state === "SUCCESS") {
var rows1 = response.getReturnValue();
component.set("v.data", rows1);
}
});
$A.enqueueAction(action);
}
})
//apex class
public class LookupRelatedContactC {
#AuraEnabled
public static List<Contact> getCon(List<String> accId) {
return [SELECT Id, Name, Phone FROM Contact WHERE AccountId =:accId];
}
}
In the above code I am stuck at the point where I am not able to add rows or delete any row dynamically in the lightning data table what I have found on the internet mostly people I have done with it aura iteration but not with data table. So when I press on delete it should fire js event or when I add row then it should fire js I dont want to call server side method again and again to add or delete. So, once I done with the delete or add row then after pressing Save button then it should fire server side method once and should save into the database Please help

react-dom.development.js?61bb:530 Warning: Prop className did not match

react-dom.development.js?61bb:530 Warning: Prop className did not match.
Server: "MuiTypography-root makeStyles-root-32 makeStyles-root-47 makeStyles-darkest-27 makeStyles-bodySmall-43 makeStyles-noTextTransform-41 MuiTypography-body1"
Client: "MuiTypography-root makeStyles-root-32 makeStyles-root-48 makeStyles-darkest-27 makeStyles-bodySmall-43 makeStyles-noTextTransform-41 MuiTypography-body1"
I have tried the following so far to no avail:
configured runtime chunk in webpack, as we are code splitting at the route level,
optimization: {
runtimeChunk: {
name: 'app',
},
},
verified there is only one version of material-ui, the latest, 4.9.3
node environment is the same for both client and server
tried wrapping both the client and app in stylesprovider with a fresh createGenerateClassName:
server:
const sheets = new ServerStyleSheets();
const generateClassName = createGenerateClassName({
productionPrefix: 'tock',
});
const html = ReactDomServer.renderToString(
sheets.collect(
<Provider store={store}>
<StaticRouter location={req.url} context={routerContext}>
<StylesProvider generateClassName={generateClassName}>
<Application />
</StylesProvider>
</StaticRouter>
</Provider>
)
);
as well as ensuring that new ServerStyleSheets is created on every requuest.
client:
const generateClassName = createGenerateClassName({
productionPrefix: 'tock',
});
try {
(fullRender ? ReactDOM.render : ReactDOM.hydrate)(
<StrictMode>
<Provider store={store}>
<Router history={tockHistory}>
<StylesProvider generateClassName={generateClassName}>
<Routes />
</StylesProvider>
</Router>
</Provider>
</StrictMode>,
document.querySelector('#Root')
);
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
throw e;
}
followed the reference implementation:
https://material-ui.com/guides/server-rendering/
this seems to only be happening in development mode. If I bundle for production and run the app, it's working.
worked through:
https://material-ui.com/getting-started/faq/#my-app-doesnt-render-correctly-on-the-server
specifically, I was interested in this:
https://material-ui.com/getting-started/faq/#react-class-name-hydration-mismatch
Node: v13.8.0
Webpack: 4.41.6
Material-ui: 4.9.3
the component where we started seeing this issue, interestingly, uses some prop based styles:
export const useTypographyStyles = makeStyles((theme) => ({
root: {
marginBottom: ({ mb, paragraph }: TypographyProps) =>
paragraph ? theme.spacing(2) : theme.spacing(mb ?? 0),
},
which I notice generates 2 strings for the classes in the hook.
root: "makeStyles-root-32 makeStyles-root-232"
is what I get when I log the result of:
const classes = useTypographyStyles({ mb, paragraph });
but if I do a regular style there with just a value, I do not get the issue.
I know this isn't much help but changing the specific error triggering className worked for me. I had a class called EmojiWrapper and it was giving the error of client/server difference. So I renamed it and the problem went away. I think it has something to do with caching.

What format should I use for payload and headers in my chai REST-API test?

I am setting up REST-API test within my codecept testing framework which uses integrated Chai.
After checking the very basic documentation on the subject in CodeceptJS documentation I can't seem to get my test to work.
const expect = require('chai').expect;
Feature('Checkout');
Scenario('Create a customer', async I => {
const payload = ({
first_name: 'Dummy title',
last_name: 'Dummy description',
email: 'john#test.com',
locale: 'fr-CA',
billing_address[first_name]: 'John',
billing_address[last_name]: 'Doe',
billing_address[line1]: 'PO Box 9999',
billing_address[city]: 'Walnut',
billing_address[state]: 'California',
billing_address[zip]: '91789',
billing_address[country]: 'US'
})
const header = ({Content-Type: 'application/x-www-form-urlencoded'})
const res = await I.sendPostRequest('https://mytesturl-
api.com/api/',payload,header);
expect(res.code).eql(200);
});
I have put my payload and header in a variable for ease of use and readability.
But it doesn't work and keeps giving me Unexpected token [
I figured it out.
The way to format the payload was as a string (see example below)
const expect = require('chai').expect;
Feature('Checkout');
Scenario('Create a customer', async I => {
const payload = ({
first_name: 'Dummy title',
last_name: 'Dummy description',
email: 'john#test.com',
locale: 'fr-CA',
'billing_address[first_name]': 'John',
'billing_address[last_name]': 'Doe',
'billing_address[line1]': 'PO Box 9999',
'billing_address[city]': 'Walnut',
'billing_address[state]': 'California',
'billing_address[zip]': '91789',
'billing_address[country]': 'US'
})
const header = ({Content-Type: 'application/x-www-form-urlencoded'})
const res = await I.sendPostRequest('https://mytesturl-api.com/api/',payload,header);
expect(res.code).eql(200);
});

Struts 2 won't transfer params from ExtJS form to ActionSupport class

I am implementing a simple ExtJS form that submits to a Struts 2 ActionSupport class. The code for the various components is as follows:
MyAction.java:
//packaging and imports
public class MyAction extends ActionSupport {
private String aField;
private String anotherField;
public String execute() throws Exception {
System.out.println(afield + " " + anotherField); //just checking values, atm
return ActionSupport.SUCCESS;
}
public String getAField() {
return this.aField;
}
public void setAField(String aField) {
this.aField = aField;
}
public String getAnotherField() {
return this.anotherField;
}
public void setAnotherField(String anotherField) {
this.anotherField = anotherField;
}
}
myForm.js:
Ext.onReady(function() {
Ext.QuickTips.init();
// turn on validation errors beside the field globally
Ext.form.Field.prototype.msgTarget = 'side';
var myForm = new Ext.form.FormPanel({
id: 'myFormId',
url: 'submitMyForm.action',
defaults: {
xtype: 'textfield'
},
items: [
{
fieldLabel: 'A Field',
id: 'aField',
name: 'aField',
allowBlank: false
},
{
fieldLabel: 'Another Field',
id: 'anotherField',
name: 'anotherField',
allowBlank: false
}
],
renderTo: 'contentMain'
});
var submitButton = new Ext.Button({
text: 'SUBMIT',
handler: function(button, event) {
myForm.getForm().submit({
url: 'submitMyForm.action',
failure: function() {
Ext.Msg.alert('Error', 'Can not save data.');
}
});
}
});
});
struts.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="myPackage" namespace="/" extends="json-default">
<action name="submitMyForm" class="mycodepackage.MyAction">
<result name="*" type="json">
<param name="includeProperties">aField</param>
</result>
</action>
</package>
</struts>
When the submit button is pressed, my action executes properly, and in addition to standard debugging data prints out:
null null
The JSON result is sent back correctly, but of course is also null:
14:22:17,046DEBUG JSONResult:68 - Adding include property expression: aField
14:22:17,052DEBUG JSONWriter:68 - Ignoring property because of include rule: anotherField
14:22:17,053DEBUG JSONUtil:68 - [JSON]{"aField":null}
Now, it's my understanding that the values entered in the form should be inserted into the instance variables for my action class. Am I wrong in this? If not, what could be going wrong? If so, what can I do to ensure that the form data is sent to my action handler?
Thanks.
Any parameters sent will be placed into the similarly named setters. Why don't you first check that the form parameters are getting sent correctly with LiveHttpHeaders Firefox plugin.
Once we realized the form data was not being correctly passed into the http request, my coworker developed a form data interceptor, which we use to load the data in manually. For more information, look into the <interceptor>, <interceptor-stack>, and <interceptor-ref> tags.