How to make ReferenceManyField to match childs from a url? - spring-rest

I'm building an application with react-admin and Spring REST as data API. I'm in the typical situation of having a Product object with relative comments.
In the element that shows the product I added ReferenceManyField in order to show the comments for that product. But here is the problem: according to the reference documentation, this component fetches the comments calling the comments list and finding comments that have the id of the father:
https://marmelab.com/react-admin/Fields.html#referencemanyfield
But since my Spring REST produces something similar for one specific product:
{
"id" : 1,
"description" : "Description of Product 1",
"price" : 50045.0,
"title" : "Title of product 1",
"additionaldata" : [ ],
"pimages" : [ ],
"_links" : {
"self" : {
"href" : "http://localhost:8080/products/1"
},
"product" : {
"href" : "http://localhost:8080/products/1"
},
"pcomments" : {
"href" : "http://localhost:8080/products/1/pcomments"
},
"vendor" : {
"href" : "http://localhost:8080/products/1/vendor"
}
}
}
The logic is inverse, we find the URI to call to find the list of comments for that particular product.
How can I make ReferenceManyField to call http://localhost:8080/products/1/pcomments to fetch comments for that product?

Try to do the following:
<ReferenceManyField source="your_source" target="_links['pcomments']['href']" reference="products"/>

You can wrap your search url in the filter prop of ReferenceManyField, then in your dataProvider get the filter from GET_MANY_REFERENCE(switch case). then you can do whatever you want

Related

I need to capture jsonapi response before node is created by JSONAPI through custom code

In Drupal 8/9. Need to capture data including 'attributes', 'type' and custom created group 'translate' when other party using jsonapi POST menthod to create articles in my site. This should be captured in custom module.
For Example here is the payload:
{
"data": {
"type": "node--cars",
"attributes": {
"title": "Test article flow 1"
"body": "This is custom body"
},
"relationships": {
},
"translate": {
"custom_field1": "Text 1",
"custom_field2": "Text 2"
}
}
}
API point fo this is "/jsonapi/node/cars". So actually before the 'cars' node is created need to capture "custom_field1" and "custom_field2" in "translate" so that need to write custom validation from custom module. Tried creating normalizer "TypedDataNormalizer" and "ContentEntityNormalizer" and in "normalize" class getting data. But its empty and its not calling this normalizer. Can someone please help me in this case how to achieve this. Thanks in advance

Telegram Bot Api : multi level Quiz

I want to develop a telegram Bot with multiple options, for example at first I show 3 buttons : button 1 , button 2 , button 3
and when user click on each, again, I show three other buttons : button 1 , button 2 , button 3
and after step 2, I want to show user first and second button he clicked, for example :
he first click on button 3 and then click on button 1, so, I want to show :
31
how can I know which button at he clicked first ? is there anyway to get chat history from bot ? or I should save his clicks on a database ? or what is your solution ?
*I am using c# and telegram.bot , but just give me a solution, language is not important.
First you can use inline keyboard that gives you the user updates with data. That means you can obtain Ids for any question and when user click you get the question Id.
Using InlineKeyboardMarkup with question key as data.
I suggest you to save a question tree to the database and save current state of each user.
Then when user clicked a button; you get the question key and find it in the tree and ask the next question or find where it comes from (previous questions).
If you want to run any method related to each question you can simply store each question method name in tree and when user arrives fire that method with Reflection.
You should save the chat_id and buttons clicked in a database. Chat history for bots is short lived and may not be reliable for your purpose.
You can use inline buttons. Solution with JavaScript:
var options = {
reply_markup: JSON.stringify({
inline_keyboard: [
[
{text: 'button 1', callback_data: '1'},
{text: 'button 2', callback_data: '2'},
{text: 'button 3', callback_data: '3'},
],
]
})
};
bot.sendMessage(chatId, 'Pick action:', options);
See, you can pass any callback data. So I would save current path in this callback_data property. Format is not important, can be array, string, whatever. But it will represent the stack.
For example, path a2.a1.a3 means that you clicked on button number 2, then on number 1, and then on number 3. And data structure can be similar to this:
{
q: 'Which path you wanna go?',
a1: { ... },
a2: {
value: 'right',
q: 'You're going right. You see the wall, what will you do?',
a1: {
a1: { ... },
a2: { ... }
a3: {
value: 'go back',
q: 'You\'re going back and you see the tiger, what will you do?',
a1: { ... },
a2: { ... }
}
},
a2: { ... },
a3: { ... }
},
a3: { ... }
}
And it's also easy to go pack. Just pop one value from the stack and you're on previous menu.

How to get google tag manger variable value in custom HTML

I have dynamic values in my Datalayer which I want to access from my custom HTML in Google Tag Manager
Custom HTML in tag : {A pixel image for tracking orders}
<img src="https://httpool-secure.net/p.ashx?o=59&e=51&f=img&t={{transactionId}}&etc={{transactionTotal}}" width="1" height="1" border="0"
My DataLayer Object :
[{
"event": "ordersuccess",
"transactionId": 86886,
"transactionAffiliation": "Powai",
"transactionTotal": 158,
"transactionTax": 17.5,
"transactionProducts": [{
"sku": "2395",
"name": "Masala Calzone ",
"category": "OTHERS",
"price": "70",
"quantity": "2"
}]
}, {
"gtm.start": 1454584525056,
"event": "gtm.js"
}, {
"event": "gtm.dom"
}, {
"event": "gtm.load"
}]
Data Layer Variable transactionId
Data Layer Variable transactionTotal
Now when I publish my tag I get errors :
Unknown variable 'transactionTotal' found in a tag. Edit the tag and
remove the reference to the unknown variable.
Unknown variable 'transactionId' found in a tag. Edit the tag and
remove the reference to the unknown variable.
How to associate the variables to my tag ???
The top field sets the variable name in GTM Panel.
Please use that name as the variable name .
You should be using the name of the DataLayer Variables that you've named in this input box, and not the name of the dataLayer parameters themselves
I take no credit for this possible answer as it was already mentioned in comments (props to #EikePierstorff), but as a formality, here it is:
You should use the name of the DataLayer Variables that you've defined, and not the name of the dataLayer parameters themselves:
<img src="https://httpool-secure.net/p.ashx?o=59&e=51&f=img&t={{transaction_id}}&etc={{total transaction}}" ...
Even though the correct answer is already given, I really understood it until I saw the documentation in this repository:
https://github.com/BKWLD/data-layer-events
The key is part of the README.md file in the Setup section.
Basically you need to setup variables of type Data Layer Variable with the parameter name you're giving, in your case that would be transactionId, then the variable becomes available on the tags and it will match the JS parameters you are providing.
As some have mentioned, you need to use the variable's name when referencing it in HTML. For example: If I setup a variable named 'Order Total' but the Data Layer Variable Name is orderTotal you'll want to use 'Order Total' in your HTML as displayed below.
alert({{Order Total}});

How to create cascading drop down in alfresco

I have requirement where I have to create a cascading dropdown, means the value of the second dropdown will depends on the first one. The list are going to be hardcoded.
For e.g. The first dropdown of country and based on this value the second dropdown is of state corresponding to that country; I will have the list of state corresponding to each country.
Now I know how to apply constraint on the field using list but can that be extended to two level ??
I have also searched about datalist but I really don't want that as the list is going to be pan customer but datalist will make it customer specific and don't want customer to create the list themselves.
Any help will be highly appreciated.
Thanks
Alfresco does not have cascading dropdown lists out of the box.
Nevertheless, it will not be difficult to develop one.
Because your lists are hardcoded, there is a simple solution.
Generate the controls for the two dropdown lists. They can even be just an hidden field or an empty dropdown. If you are not familiar with the Alfresco form engine, it will be probably easier to use an hidden field like in the following example (snippet of the configuration in share-config-custom.xml):
<field id="dropdown1">
<control template="/org/alfresco/components/form/controls/hidden.ftl">
<control-param name="contextProperty">dropdown1</control-param>
</control>
</field>
<field id="dropdown2">
<control template="/org/alfresco/components/form/controls/hidden.ftl">
<control-param name="contextProperty">dropdown2</control-param>
</control>
</field>
In share-config-custom.xml, you can also add a new custom javascript and css:
<!-- Document Library client-side dependencies -->
<config evaluator="string-compare" condition="DocLibCustom">
<dependencies>
<js src="/js/cascading-dropdown.js" />
<css src="/css/cascading-dropdown.css" />
</dependencies>
</config>
The custom javascript and css can, using YUI, find the two controls and generate the necessary dropdown and event listeners. When the dropdown is updated, an event listener will update the cascading dropdown and will also update the hidden fields. The value of the hidden fields will be posted when the form is closed.
A better solution can be to use the custom javascript only to define a javascript library. You can then use this javascript library in a custom free marker template to use instead of "/org/alfresco/components/form/controls/hidden.ftl"
You can find hidden.ftl in:
/webapps/share/WEB-INF/classes/alfresco/site-webscripts/org/alfresco/components/form/controls/hidden.ftl
Do a copy of this ftl in the extension path and modify it to use your custom javascript.
If the lists are not hardcoded, simply use a webscript to generate the list and call it from the browser using ajax calls.
As you are with alfresco community edition 5.0.d, you can/should be using aikau for that sort of things, you can start learning and using aikau based on this tutorial for standalone aikau clients or this tutorial for new custom share pages.
Once you have your page setup (desc.xml, js and ftl), you should have something like this:
custom-page.get.desc.xml
<webscript>
<shortname>Test page 1</shortname>
<family>testing</family>
<url>/custom-uri</url>
</webscript>
custom-page.get.ftl
<#processJsonModel group="share"/>
and custom-page.get.js
model.jsonModel = {
services : [ "alfresco/services/NavigationService",
"alfresco/services/LogoutService",
// Add more services here !!!
],
widgets : [
// Add more widgets here
]
};
You need now to add two selects to your widgets array:
{
name : "alfresco/forms/Form",
config : {
scopeFormControls : false, // to avoid complex handling of
// pubSubScope
widgets : [ {
name : "alfresco/forms/controls/Select",
config : {
fieldId : "LEVEL_1",
label : "Level 1",
description : "Select an item from the list",
name : "level_1",
value : "1",
requirementConfig : {
initialValue : true
},
optionsConfig : {
fixed : [ {
label : "Item 1",
value : "1"
}, {
label : "Item 2",
value : "2"
}, {
label : "Item 3",
value : "3"
} ]
}
}
}, {
name : "alfresco/forms/controls/Select",
id : "LEVEL_2",
config : {
fieldId : "LEVEL_2",
label : "Level 2",
description : "Select an item from the list",
name : "level_2",
requirementConfig : {
initialValue : true
},
optionsConfig : {
fixed : [ {
label : "Item 1.1",
value : "1"
}, {
label : "Item 1.2",
value : "2"
}, {
label : "Item 1.3",
value : "3"
} ]
}
}
} ]
}
}
The next step would be to detect the change event in your first select then refresh the list of the second select with new items. In order to do so, you need either to define a new service or extend the select widget for your second select. I will go with option number 1:
CustomServiceForNestedSelects.js
define(
[ "dojo/_base/declare", "alfresco/core/Core", "dojo/_base/lang",
"alfresco/core/CoreXhr", "service/constants/Default" ],
function(declare, Core, lang, CoreXhr, AlfConstants) {
return declare(
[ Core, CoreXhr ],
{
pubSubScope : "",
levelOneFieldId : "LEVEL_1",
levelTwoFieldId : "LEVEL_2",
levelTwoItems : [ [ {
label : "Item 1.1",
value : "1"
}, {
label : "Item 1.2",
value : "2"
}, {
label : "Item 1.3",
value : "3"
} ], [ {
label : "Item 2.1",
value : "1"
}, {
label : "Item 2.2",
value : "2"
}, {
label : "Item 2.3",
value : "3"
} ], [ {
label : "Item 3.1",
value : "1"
}, {
label : "Item 3.2",
value : "2"
}, {
label : "Item 3.3",
value : "3"
} ] ],
constructor : function yreg_CustomServiceForNestedSelects__constructor(
args) {
lang.mixin(this, args);
this.alfSubscribe(this.pubSubScope
+ "_valueChangeOf_" + this.levelOneFieldId,
lang.hitch(this, this.levelOneChanged));
},
levelOneChanged : function yreg_CustomServiceForNestedSelects__levelOneChanged(
payload) {
var value = payload.value;
var levelTwo = dijit.byId(this.levelTwoFieldId);
if (levelTwo)
levelTwo
.setOptions(this.levelTwoItems[value - 1]);
},
});
});
And now, all that is left is to include your service in your page model
"<custom-package>/CustomServiceForNestedSelects"
Note:
You will need to register a custom package and place your service there, in order to learn how to do so, check this tutorial.
To test your page's content check http://127.0.0.1:8090/aikau-sample/page/na/ws/custom-uri in case you are trying this code in a stand alone aikau app, or http://127.0.0.1:8080/share/page/dp/ws/custom-uri, http://127.0.0.1:8080/share/page/hdp/ws/custom-uri for share custom pages
Aikau does actually provide cascading menus out-of-the-box, see the alfresco/menus/AlfCascadingMenu widget. There are examples of its use already present within Alfresco (for example the favourites list from under the sites menu in the main header in Share). If you already know the cascading contents then this can all be defined in your page WebScript. However, if you need to dynamically change the content of the cascaded menu then you should look at the implementation of alfresco/header/AlfSitesMenu or alfresco/documentlibrary/AlfCreateTemplateContentMenu (you can find the source in the Aikau GitHub project).
Some useful info: https://forums.alfresco.com/forum/developer-discussions/alfresco-share-development/cascading-dropdown-alfresco-share-03102011
Used that as a basis for my own cascading selects. Builds on the same concept as described by Marco Altieri

jsTree async with preloaded data

I am trying to make a tree view be async. When the page is rendered, there is default tree items displayed. jsTree tries to reload the root anyway.
I want the page to render (with jsTree init'ed) with default items rendered from browser, not the ajax call. Then we the user tries to go deeper, thats when I want to do do the ajax calls.
Any help is appreciated. Thanks!
From Documentation: If both data and ajax are set the initial tree is rendered from the data string. When opening a closed node (that has no loaded children) an AJAX request is made.
An example,
$(function () {
$("#demo4").jstree({
"json_data" : {
"data" : [
{
"data" : "A node",
"state" : "closed"
},
{
"attr" : { "id" : "li.node.id" },
"data" : {
"title" : "Long format demo",
"attr" : { "href" : "#" }
}
}
],
"ajax" : { "url" : "/static/v.1.0rc/_docs/_json_data.json" }
},
"plugins" : [ "themes", "json_data" ]
});
});

Resources