Pagination with "cursors" using Admin-on-rest - pagination

My back-end API supports cursor based pagination for the GET_LIST operations.
API: {apiUrl}/{resource}?fltr={limit:100}
Response:
{
data: [],
next: {reference_url_to_the_next_paginated_data_set}
}
What is the best way to supported this sort of pagination with the existing AOR pagination infrastructure ?

I ended up achieving this using a Custom Saga, Action creator and Reducer.
Have a custom Saga take every GET_LIST_SUCCESS and dispatch a custom "UPDATE_PAGINATION" action for that resource.
Handle that action using a Custom Pagination Reducer. The reducer creates and maintains the "pagination" state for each resource, page-wise in the redux store
A Connected Pagination Component that is subscribed to the pagination state of that resource, that has a "next" and "previous" button and a "currentPage" state. On-Click of "Next" or "Previous" buttons, fetch the "nextUrl" or the "previousUrl" for the "currentPage" and use AOR's fetch-meta to update the "data" state of that resource.
Use this custom Pagination component in your data-grid like so
<List resource="myResource" pagination={<CustomPagination />} />

You need to write a custom Rest client to handle your response and request type. You need your API to set the X-Total-Count header when your client makes a GET_LIST type request.
https://marmelab.com/admin-on-rest/RestClients.html

Related

How to tell the webhook the 'unpublish()' order comes from the API, not the Contentful console?

I use this trick (thanks #Robban) to publish a Contentful entry through the API, without triggering the webhook.
However, I could not figure out how to UNpublish an entry through the API without triggering the webhook.
According to the Contentful documentation, to unpublish an entry through the API, it goes like this:
client.getSpace('<space_id>')
.then((space) => space.getEntry('<entry_id>'))
.then((entry) => entry.unpublish())
As <entry_id> is the only payload, how could I indicate to the webhook it should not proceed as usual, as it was an API call?
There is unfortunately, again, no difference between a call from the API directly or from the web app. The web app does exactly this call under the hood.
Further more, in the case of an unpublish the only thing your webhook would recieve is a deletion object which does not contain any fields. This means that the trick shown in the previous answer does not apply here.
The only way I can think of solving this would be to make another call to some data store (could be Contentful) and put the entry id and perhaps also some timestamp in there. Your webhook could then upon recieving an unpublish event query this datastore and see if processing should continue or if it seems the unpublish was made through the web app.
Basically something like this:
client.getSpace('<space_id>')
.then((space) => space.getEntry('<entry_id>'))
.then((entry) => {
otherService.SetUnpublishedThroughManualAPICall(entry.sys.id);
entry.unpublish();
})
Then in your webhook with some pseudo code:
function HandleUnpublish(object entry) {
if(OtherService.CheckIfManualUnpublish(entry.sys.id)){
//Do some processing...
}
}
You could opt to use a field in Contentful as your store for this. In that case you would just before unpublishing set this field. Something like this:
client.getSpace('<space_id>')
.then((space) => space.getEntry('<entry_id>'))
.then((entry) => {
entry.fields['en-US'].unpublishedTroughApi = true;
entry.update();
})
.then((entry) => entry.unpublish())
Then in your webhook you would have to fetch the entry again via the management API and inspect the field. Keep in mind that this would result in a number of extra API calls to Contentful.

Which AMP extensions can fetch a response from an endpoint?

What AMP extensions can be used to get a response from the server in the form of variable that can be used later, such as in a template or as a parameter to an attribute?
amp-access
The authorization endpoint of amp-access can return "a free-form JSON object":
Here’s a small list of possible ideas for properties that can be returned from the Authorization endpoint:
Metering info: maximum allowed number of views and current number of views.
Whether the Reader is logged in or a subscriber.
A more detailed type of the subscription: basic, premium
Geo: country, region, custom publication region
amp-form
amp-form "allows publishers to render the responses using Extended Templates". The response is expected to be a valid JSON Object. Try the "Hiding input fields after success" demo in the amp-form sample to see it in action.
amp-list
amp-list fetches "content dynamically from a CORS JSON endpoint and renders it using a supplied template". The response must be a JSON object that contains an array property "items".
In addition to {{variable}} substitutions in Mustache templates, you can also use AUTHDATA(variable) elsewhere.
amp-live-list (not quite)
amp-live-list is a "wrapper and minimal UI for content that updates live in the client instance as new content is available in the source document". The page will re-fetch itself, giving the server a change to send new content. If new content is found, AMP will populate a <div items> element with the new (HTML) items. You can't use that as a variable.
It's name doesn't really suggest it, but I think you want AMP-list
https://github.com/ampproject/amphtml/blob/master/extensions/amp-list/amp-list.md
Fetches content dynamically from a CORS JSON endpoint and renders it using a supplied template.

Jersey2 ContainerRequestFilter not executing before autentication

I am trying to get security working with my jersey2 web app.
I register RolesAllowedDynamicFeature and my Request filter with AUTHENTICATION priority in my ResourceConfig
packages("example.jersey");
register(MyRequestFilter.class, Priorities.AUTHENTICATION);
register(RolesAllowedDynamicFeature.class);
I added #RolesAllowed to the method
#RolesAllowed("quinn")
#GET
#Path("/")
public Response getIt(#Context UriInfo uriInfo) {
return Response.ok().entity(service.get()).build();
}
In my request filter I set my security context
SecurityContext securityContext = containerRequestContext.getSecurityContext();
containerRequestContext.setSecurityContext(new MySecurityContext("gary", securityContext));
When I call the method from postman I get a 403 - Forbidden
I added logging to my request filter to see when it is called. It is NOT called.
If I remove the #RolesAllowed from the web method it does call the request filter.
It seems the Priorities.AUTHENTICATION is not making a difference.
Is there anything I'm missing?
Your filter is implemented as a post-matching filter. It means that the filters would be applied only after a suitable resource method has been selected to process the actual request i.e. after request matching happens. Request matching is the process of finding a resource method that should be executed based on the request path and other request parameters.
#RolesAllowed blocks the selection of the particular resource method giving you the 'not executing' behavior you mentioned.
You have two options... using #PreMatching as explained here.
Or, use custom annotations as explained on a similar question.

Handling parallel REST post requests

I have created my own REST service based on the examples from "Domino Sample REST Service Feature" from 901v00_11.20141217-1000 version of XPages Extension Library.
As far as I understand the design of the library each REST request will be run in its own thread on the server. This approach does not allow to handle parallel POST requests to the same document.
I have not found any examples in XPages Extension Library which would handle post requests as transactions on the server, i.e. which would block the server resource for the whole request processing time and would put put next requests in the queue?
Can anybody point to the source code of the service which would allow to handle parallel requests?
The skeleton for my post request processing function is this
#POST
#Path(PATH_SEPARATOR + MyURL)
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response myPost(
String requestEntity,
#Context final UriInfo uriInfo)
{
LogMgr.traceEntry(this, "myPost");
RestContext.verifyUserContext();
String myJson = ... // Process post
Response response = buildResponse(myJson);
LogMgr.traceExit(this, "myPost", "OK");
return response;
}
And I would like to implement something like this
// Start transaction
String myJson = ... // Process post
// Stop transaction
Is there a way to do it in Java?
I suppose you could use document locking in traditional Notes/Domino context - and synchronized in Java :-)
Have you tried any of these? I cannot see why they should not work.
/John
I agree with John. You can use document locking to prevent simultaneous updates to the same document. You might also want to consider some changes to the definition of your REST API.
First, you imply you are using POST to update an existing document. Usually, POST is used to create a new resource. Consider using PUT instead of POST.
Second, even with document locking, you still might want to check for version conflicts. For example, let's say a client reads version 2 of a document and then attempts to update it. Meanwhile, another client has already updated the document to version 3. Many REST APIs use HTTP ETags to handle such version conflicts.

Updating a wiki page with the REST API

How do you update a SharePoint 2013 wiki page using the REST API?
Three permutations:
Reading an existing page (content only)
Updating an existing page
Creating a new page
For reading an existing page, of course I can just to a "GET" of the correct URL, but this also brings down all the various decorations around the actual data on the wiki page-- rather than fish that out myself, it would be better if there was a way to just get the content if that is possible.
Are there special endpoints is the REST API that allow for any of these three operations on wiki pages?
As stated in GMasucci's post, there does not appear to be a clean or obvious way of instantiating pages through the REST API.
You can call the AddWikiPage method from the SOAP service at http://[site]/_vti_bin/Lists.asmx. This is an out of the box service that will be accessible unless it has been specifically locked down for whatever reason.
To read the content of a wiki page through the REST API, you can use the following endpoint:
https://[siteurl]/_vti_bin/client.svc/Web/GetFileByServerRelativeUrl('/page/to/wikipage.aspx')/ListItemAllFields
The content is contained within the WikiContent field. You may want to add a select to that URL and return it as JSON to reduce the amount of data getting passed over if that is a concern.
As for updating the content of an existing wiki page, it is not something I have tried but I would imagine it's just like populating another field through the REST API. This is how I would expect to do it:
Do a HTTP POST to the same endpoint as above
Use the following HTTP headers:
Cookie = "yourauthcookie"
Content-Type = "application/json;odata=verbose"
X-RequestDigest = "yourformdigest"
X-HTTP-Method, "MERGE"
If-Match = "etag value from entry node, returned from a GET to the above endpoint"
Post the following JSON body
{
"__metadata": { "type": "SP.Data.SitePagesItem" },
"WikiField" : "HTML entity coded wiki content goes here"
}
The interim answer I have found is to not utilise REST, as it appears to not be
fully documented
fully featured
supported across Sharepoint 2013 and On-line in the same way
So my current recommendation would be to utilise the SOAP services to achieve the same, as these are more documented and easily accessible.

Resources