react-admin: custom user filters at list component - admin-on-rest

My backend work with filters is like this (for example) :
filters = {
"groupOp": "AND",
"rules": [
{
"field": "id",
"op": "equal",
"data": 6
},
{
"field": "partnerId",
"op": "equal",
"data": 446
}
],
"groups": [
{
"groupOp": "AND",
"rules": [
{
"field": "username",
"op": "startswith",
"data": "Alex"
}
],
"groups": []
}
]
}
It's working fine with persistence filters, but it's not working with user filters that are passed to the list component. For example:
export const OrdersFilter = (props) => (
<Filter {...props}>
<TextInput label="username" source="username" />
<TextInput label="partnerId" source="partnerId" />
</Filter>
);
Because it is a key-value filter and I can't understand how I can add additional fields to the user filter field.
Or how I can wrap url changes ('##router/LOCATION_CHANGE') after action ##redux-form/CHANGE to modify the original filter which is passed to the url with the filtred field name :
filter=%7B%22partnerId%22%3A%226%22%7D&order=DESC&page=1&perPage=10'
to
filter={"field": "partnerId","op": "equal","data": 6}&order=DESC&page=1&perPage=10

You should simplify (flatten) the client side filters for react-admin and "translate" them in the shape expected by your backend in your dataProvider

You can choose a custom attribute in the filter and through the backend you can apply the filter.
const UserFilter = (props) => (
<Filter {...props}>
<TextInput label="Username" source="q" alwaysOn />
</Filter>
);
Backend: Loopback4 for example:
async find(#param.filter(User) filter?: Filter<User>): Promise<User[]> {
if(filter && filter.where){
const where = filter.where as any;
if(where["q"]){
where.username = { ilike: '%'+where["q"]+'%' };
filter.where = where;
}
}
const response = await this.userRepository.find(filter);
this.response.set("X-Total-Count", ""+response.length);
this.response.set("access-control-expose-headers", "X-Total-Count");
return response;
}

Related

Gatsby GraphQL not getting images data from Strapi

I'm using Strapi v.4 and Gatsby v.4.23.0
I use gatsby-source-strapi v.2
My gatsby-config.js looks like this
const strapiConfig = {
apiURL: process.env.STRAPI_API_URL,
accessToken: process.env.STRAPI_TOKEN,
collectionTypes: [
{
singularName: 'article',
queryParams: {
// Populate media and relations
// Make sure to not specify the fields key so the api always returns the updatedAt
populate: {
'articleSection': {
image: {
populate: {
data: "*"
}
},
images: "*",
},
'categories': "*"
},
},
},
{
singularName: 'category',
},
],
singleTypes: [],
}
In Strapi, the Article data model is like this:
When I explore Strapi GraphQL I can see images data, but the same data are not available in Gatsby GraphQL explorer. I see something like the following:
As you can see there are no images.
How can I get image data?
Solved with this config
const strapiConfig = {
apiURL: process.env.STRAPI_API_URL,
accessToken: process.env.STRAPI_TOKEN,
collectionTypes: [
{
singularName: 'article',
queryParams: {
// Populate media and relations
// Make sure to not specify the fields key so the api always returns the updatedAt
populate: {
'articleSection': {
populate: "*"
},
'categories': "*"
},
},
},
{
singularName: 'category',
},
],
singleTypes: [],
}

Filter Criteria in Lambda Function

I want to enable DynamoDB streams on my lambda using AWS CDK which I am able to do but I also want to enable the filter criteria on lambda
But I am getting this error:
Invalid filter pattern definition. (Service: AWSLambda; Status Code: 400; Error Code: InvalidParameterValueException
This is the event I am getting from DynamoDB streams:
{
"input": {
"Records": [
{
"eventID": "e92e0072a661a06df0e62e411f",
"eventName": "INSERT",
"eventVersion": "1.1",
"eventSource": "aws:dynamodb",
"awsRegion": "<region>",
"dynamodb": {
"ApproximateCreationDateTime": 1639500357,
"Keys": {
"service": {
"S": "service"
},
"key": {
"S": "key"
}
},
"NewImage": {
"service": {
"S": "service"
},
"channel": {
"S": "email"
},
"key": {
"S": "key"
}
},
"SequenceNumber": "711500000000015864417",
"SizeBytes": 168,
"StreamViewType": "NEW_IMAGE"
},
"eventSourceARN": "arn:aws:dynamodb:<region>:<account>:table/table-name/stream/2021-12-14T13:00:29.888"
}
]
},
"env": {
"lambdaContext": {
"callbackWaitsForEmptyEventLoop": true,
"functionVersion": "$LATEST",
"functionName": "functionName",
"memoryLimitInMB": "128",
"logGroupName": "/aws/lambda/functionName",
"logStreamName": "2021/12/14/[$LATEST]028531c7b489b8ec69bace700acc0",
"invokedFunctionArn": "arn:aws:lambda:<region>:<account>:function:functionName",
"awsRequestId": "c72e80252-4722-b9f0-a03b7f8b820e"
},
"region": "<region-name>"
}
}
The event source mapping code is:
const mapping = new lambda.CfnEventSourceMapping(this, 'event', {
functionName: "functionName,
batchSize: 1,
bisectBatchOnFunctionError: true,
startingPosition: lambda.StartingPosition.TRIM_HORIZON,
eventSourceArn: <stream-arn>,
filterCriteria: filter,
});
I want to get the eventName to be INSERT and the channel to be email here. What should be the value of the filter criteria? Its not working for me
<Edit> CDK filter helpers added in v2.42.0
The original workaround is no longer necessary. The CDK now has event-source filters for Lambda, Kinesis and SQS. Pass the filter to the L2 EventSourceMapping construct:
const source: EventSourceMapping = new lambda.EventSourceMapping(this, "EventSourceMapping",{
target: func,
eventSourceArn: table.tableStreamArn,
startingPosition: lambda.StartingPosition.TRIM_HORIZON,
filters: [
lambda.FilterCriteria.filter({
eventName: lambda.FilterRule.isEqual("INSERT"),
dynamodb: { NewImage: { channel: { S: lambda.FilterRule.isEqual("email") } },},
}),
],
}
);
</Edit>
Here's the DynamoDB streams filter Pattern syntax for new records with a channel of email:
`{ \"eventName\": [\"INSERT\"], \"dynamodb\": { \"NewImage\": {\"channel\": { \"S\" : [\"email\"]}} } }`
In other words, the Pattern is a stringified JSON filter rule with escaped quotes. The pattern is applied against each stream record.
Here is the full CDK syntax. The code starts with the usual L2 EventSourceMapping. It then uses escape hatch syntax to set FilterCriteria on the underlying L1 CfnEventSourceMapping:
// start with the L2 type - Note: the OP code starts with a L1 `CfnEventSourceMapping`
const source: EventSourceMapping = new lambda.EventSourceMapping(this, 'EventSourceMapping', {
target: func,
eventSourceArn: table.tableStreamArn,
startingPosition: lambda.StartingPosition.TRIM_HORIZON,
});
// escape hatch - get a L1 reference
const cfnSouce = source.node.defaultChild as lambda.CfnEventSourceMapping;
cfnSouce.addPropertyOverride('FilterCriteria', {
Filters: [
{
Pattern: `{ \"eventName\": [\"INSERT\"], \"dynamodb\": { \"NewImage\": {\"channel\": { \"S\" : [\"email\"]}} } }`,
},
],
});

How to populate only with content of getter

I have some problem in mongoose project.
I try to populate and use getter but not all data
But now all virtuals appear in document.
I'm using mongoose.Schema and mongoose.Model
Here is example of my test code
const GroupsSchema = schema({
title: String,
users: [{
type: schema.Types.ObjectId,
ref: 'Users'
}]
});
const UsersSchema = schema({
name: String,
avatar: String
}, {
toJSON: {
virtuals: true
}
});
class Users extends Model {
get name() {
return {
name: this.name
};
}
get avatar() {
return {
avatar: this.avatar
};
}
}
Populating document
const groups = await Groups.find({}).populate('users').exec();
My current result:
[
{
"_id": "5c9bb51626924f0a08aa8c3d",
"title": "GroupName"
"users": [
{
"_id": "5c8e37169fc1f9000f8c333b",
"name": "Jack",
"avatar": "avatar.jpg",
"name": {
"name": "Jack",
},
"avatar": {
"avatar": "avatar.jpg"
}
}
]
}
]
How can I populate document with content of only name getter?
Desired result:
[
{
"_id": "5c9bb51626924f0a08aa8c3d",
"title": "GroupName"
"users": [
{
"name": "Jack"
}
]
}
]

<ReferenceArrayInput /> not working with my custom data provider (prisma)

I'm currently building a data provider for prisma based on graphcool's one, and failed at succeeding to make <ReferenceArrayInput /> working.
The component successfully queries the values of the item and all the possibles values available, but it looks like it's failing when trying to match both. As a result, I get a label saying At least one of the associated references no longer appears to be available., with no values selected.
Here's the data returned by my data provider:
Returned by the GET_MANY request to grab actual choices:
[
{
"id": "cji4xk7ly00k3085444gszh6e",
"name": "value1",
"option.id": "cji4xk7lx00k20854ns2bersv",
"option": {
"id": "cji4xk7lx00k20854ns2bersv"
}
},
{
"id": "cji4xk7lz00k40854gp876vgn",
"name": "value2",
"option.id": "cji4xk7lx00k20854ns2bersv",
"option": {
"id": "cji4xk7lx00k20854ns2bersv"
}
}
]
And the data returned by the GET_LIST request to grab all possible values:
[
{
"id": "cji4xk7lz00k40854gp876vgn",
"name": "value2",
"option.id": "cji4xk7lx00k20854ns2bersv",
"option": {
"id": "cji4xk7lx00k20854ns2bersv"
}
},
{
"id": "cji4xk7ly00k3085444gszh6e",
"name": "value1",
"option.id": "cji4xk7lx00k20854ns2bersv",
"option": {
"id": "cji4xk7lx00k20854ns2bersv"
}
},
{
"id": "cjit6nvot00j80954n53vj6vt",
"name": "1x100ml",
"option.id": "cjit6dejm00bt0954ts5g2f5g",
"option": {
"id": "cjit6dejm00bt0954ts5g2f5g"
}
},
{
"id": "cjit6gu5o00d00954vzfuda0l",
"name": "19mg",
"option.id": "cjit6e66i00cb0954u1zlg1i3",
"option": {
"id": "cjit6e66i00cb0954u1zlg1i3"
}
}
]
On the JSX part, here's my code:
export const OptionEdit = props => (
<Edit title="Edit an option" {...props}>
<SimpleForm>
<DisabledInput source="id" />
<TextInput source="name" />
<ReferenceArrayInput source="values" reference="OptionValue" perPage={100}>
<SelectArrayInput optionText="name" />
</ReferenceArrayInput>
</SimpleForm>
</Edit>
);
I can try to setup something for you to reproduce my issue if needed, I'm hoping that this would be enough for you to help me. If it can help though, here's the repository containing my (very wip) data provider and the dashboard ra-data-prisma
Thanks a lot for you help.
Update:
Here's a codesandbox if you want to try: https://codesandbox.io/s/xvqm6mnyxz?expanddevtools=1&initialpath=App.js&module=%2Fsrc%2FApp.js
Just try to edit a User, and see the responses in the console along with the SelectArrayInput not being loaded with choices.
And here's the datamodel used for generating the Prisma API used in the codesanbox example:
type User {
id: ID! #unique
name: String!
addresses: [Address!]!
}
type Address {
id: ID! #unique
city: String!
user: User!
}
Got it. react-admin expects an array of ids to match the resources. All I needed to do was to set the <ReferenceArrayInput /> source prop to <resource>Ids. That fixed the issue.

How to filter on a array with graphql in Generic Mesh CMS?

Im trying to get just entrys which have in a specific value in a array (myArray: [String]).
Displaying of this Array is not Problem:
query ($lang: [String!], $filter: String!) {
nodes(lang: $lang, filter: {schema: {is: myObj}, fields: {myObj: {name: {regex: $filter}}}}) {
elements {
uuid
language
availableLanguages
fields {
... on module {
name
myArray
}
}
node {
language
fields {
... on module {
name
myArray
}
}
}
}
}
}
Result:
{
"data": {
"nodes": {
"elements": [
{
"uuid": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
"language": "de",
"availableLanguages": [
"de"
],
"fields": {
"name": "ASDF",
"myArray": [
"CAT_1",
"CAT_2"
]
},
"node": null
}
]
}
}
}
How can I filter on myArray? That I just et elements with the value uf $filter in the array myArray?
In the GraphiQL I can't find the myArray in the docs under the filter - fields.
GraphQL-Filtering for list types is not supported yet. In the GraphiQL docs you will only find supported fields for now.
See supported field types here: https://getmesh.io/docs/beta/graphql.html#_filtering_limitations
Here is the open issue on Github regarding this feature: https://github.com/gentics/mesh/issues/27

Resources