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.
Related
I am new with Aws Amplify and GraphQL and I am trying to find the best way to handle the following:
I want to be able to edit my FAQ in the frontend. The frontend gets the data from the backend, i edit one field in the frontend and save it, it should be stored in the backend
I have created a simple amplify graphql schema:
type FAQ #model(timestamps: null) {
id: ID!
sectionTitle: String
questionAndAnswer: [QuestionAndAnswer!]!
}
type QuestionAndAnswer {
id: ID!
question: String
answer: String
}
Then I populated it so it contains the following data:
{
"data": {
"listFAQS": {
"items": [
{
"sectionTitle": "Title2",
"id": "22735682-2bab-4695-b93e-1e50642d4654",
"questionAndAnswer": [
{
"answer": "answer4",
"id": "4",
"question": "question4"
},
{
"answer": "answer5",
"id": "5",
"question": "question5"
},
{
"answer": "answer6",
"id": "6",
"question": "question6"
}
]
},
{
"sectionTitle": "Title1",
"id": "21be8234-69f2-47fe-b942-d3e655197c70",
"questionAndAnswer": [
{
"answer": "answer1",
"id": "1",
"question": "question1"
},
{
"answer": "answer2",
"id": "2",
"question": "question2"
},
{
"answer": "answer3",
"id": "3",
"question": "question3"
}
]
}
]
}
}
}
Is there an easy way I can only change for instance the question "question4" without having to send the whole FAQ "row"?
When I was experimenting with it it seemed that the whole array was reseted and only the new data was saved. Should both FAQ and QuestionAndAnswer be a #model each where I connect them with #connection and update them separately as needed?
The following seems to be an easy way, as you can update only "question4" if you need, by using its own unique ID with GraphQL mutation.
type FAQ #model(timestamps: null) {
id: ID!
sectionTitle: String
questionAndAnswer: [QuestionAndAnswer!]!
}
type QuestionAndAnswer #model {
id: ID!
question: Question
answer: Answer
}
type Question #model {
id: ID!
question: String
}
type Answer #model {
id: ID!
answer: String
}
I did not include #connections (they should be in QuestionAndAnswer model), but 'Yes' would be the answer to " Should both FAQ and QuestionAndAnswer be a #model each where I connect them with #connection and update them separately as needed?".
Assuming i have a class User and a class Profile
The profile class has a field called "sex" and a field called "user" which is a pointer to user class.
If i get the profile endpoint with : https://myapi.back4app.io/classes/Profile i can get the Profile object:
{
"results": [
{
"objectId": "sIE6lOZP7R",
"user": {
"__type": "Pointer",
"className": "_User",
"objectId": "asP3EFYSR4"
},
"sex": "male",
"createdAt": "2020-05-25T17:15:49.324Z",
"updatedAt": "2020-05-25T17:15:49.324Z"
}
]
}
and if i want to include the user of this profile, i can include with: https://myapi.back4app.io/classes/Perfil?include=user so i get:
{
"results": [
{
"objectId": "sIE6lOZP7R",
"user": {
"objectId": "asP3EFYSR4",
"username": "fabiojansen",
"createdAt": "2020-05-25T17:15:16.273Z",
"updatedAt": "2020-05-25T17:15:16.273Z",
"ACL": {
"*": {
"read": true
},
"asP3EFYSR4": {
"read": true,
"write": true
}
},
"__type": "Object",
"className": "_User"
},
"sex": "male",
"createdAt": "2020-05-25T17:15:49.324Z",
"updatedAt": "2020-05-25T17:15:49.324Z"
}
]
}
Its ok, but if i want to get all the users, with the profile information in one query? Its possible? In my User class, i dont have any pointer to Profile class, only in profile class.
Is there any way?
Thanks
You have several options:
1) You can use an aggregate pipeline and $lookup the user in the Perfil class which performs a LEFT JOIN. However, this will not return an array of Parse.Object, you'd have to parse the results manually. From the docs:
{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}
2) You can do 2 requests by first getting all the users and then getting all their profiles by user IDs.
3) You can change your data model and add a pointer to Perfil in your User class. If you are running this query at scale it may be beneficial.
Hi all i have been trying out various combination in the last few days to pinpoint how to create schema validator. Meaning a collection wont just take any input but will accept only what is given in the validator.
I created below collection via mongo-repository in spring.
Can you please provide the validator for the same. And also give links which will do complex mongodb collections to java pojo mapping. It would be of great help. All i found was simple validators or java to mongo collection not vice versa
{
"_id": {
"$numberInt": "1"
},
"listOfItems": [
{
"itemid": {
"$numberInt": "1"
},
"qty": {
"$numberInt": "10"
},
"qty_type": "kg",
"cost": "20",
"currency": "INR"
},
{
"itemid": {
"$numberInt": "2"
},
"qty": {
"$numberInt": "10"
},
"qty_type": "kg",
"cost": "20",
"currency": "INR"
},
{
"itemid": {
"$numberInt": "3"
},
"qty": {
"$numberInt": "10"
},
"qty_type": "kg",
"cost": "20",
"currency": "INR"
}
],
"_class": "com.daily.essential.cartservice.model.Cart"
}
//this should answer your question
const mongoose = require('mongoose');
const productSchema = mongoose.Schema({
//mongoose generates a new rando unique Id for the product
_id: mongoose.Schema.Types.ObjectId,
//mongoose makes sure that the name input by the user is a string and mongoose makes the /name field required that means the user must not leave the field empty.
name: {type: String, required: true},
//mongoose makes sure that the price input by the user is a a Number and mongoose makes //the price field required that means the user must not leave the field empty.
price: {type: Number, required: true}
});
module.exports = mongoose.model('Product', productSchema);
I'm working on a call to readQuery. I'm getting an error message:
modules.js?hash=2d0033b4773d9cb6f118946043f7a3d4385825fe:25847
Error: Can't find field resolutions({"id":"Resolution:DHSzPa8bvPCDjuAac"})
on object (ROOT_QUERY) {
"resolutions": [
{
"type": "id",
"id": "Resolution:AepgCCio9KWGkwyMC",
"generated": false
},
{
"type": "id",
"id": "Resolution:DHSzPa8bvPCDjuAac", // <==ID I'M SEEKING
"generated": false
}
],
"user": {
"type": "id",
"id": "User:WWv57KsvqWeAoBNHY",
"generated": false
}
}.
The object with that id appears to be plainly visible as the second entry in the list of resolutions.
Here's my query:
const GET_CURRENT_RESOLUTION_AND_GOALS = gql`
query Resolutions($id: String!) {
resolutions(id: $id) {
_id
name
completed
goals {
_id
name
completed
}
}
}
`;
...and here's how I'm calling it:
<Mutation
mutation={CREATE_GOAL}
update={(cache, {data: {createGoal}}) => {
let id = 'Resolution:' + resolutionId;
const {resolutions} = cache.readQuery({
query: GET_CURRENT_RESOLUTION_AND_GOALS,
variables: {
id
},
});
}}
>
What am I missing?
Update
Per the GraphQL Dev Tools extension for Chrome, here's the whole GraphQL data store:
{
"data": {
"resolutions": [
{
"_id": "AepgCCio9KWGkwyMC",
"name": "testing 123",
"completed": false,
"goals": [
{
"_id": "TXq4nvukpLcqQhMRL",
"name": "test goal abc",
"completed": false,
"__typename": "Goal"
},
],
"__typename": "Resolution"
},
{
"_id": "DHSzPa8bvPCDjuAac",
"name": "testing 345",
"completed": false,
"goals": [
{
"_id": "PEkg5oEEi2tJ6i8LH",
"name": "goal abc",
"completed": false,
"__typename": "Goal"
},
{
"_id": "X4H4dFzGm5gkq5bPE",
"name": "goal bcd",
"completed": false,
"__typename": "Goal"
},
{
"_id": "hYunrXsMq7Gme7Xck",
"name": "goal cde",
"completed": false,
"__typename": "Goal"
}
"__typename": "Resolution"
}
],
"user": {
"_id": "WWv57KsvqWeAoBNHY",
"__typename": "User"
}
}
}
Posted as answer for fellow apollo users with similar problems:
Remove the prefix of Resolution:, the query should only take the id.
Then the question arises how is your datastore filled?
To read a query from cache, the query needs to have been called with exactly the same arguments on the remote API before. This way apollo knows what the result for a field is with specific arguments. If you never called the remote endpoint with the arguments you want to use but know what the result would be, you can circumvent that and resolve the query locally by implementing a cache resolver. Have a look at the example in the documentation. Here the store contains a list of books (in your case resultions) and the query for a single book by id can be resolved with a simple cache lookup.
I don't know how to handle nested data with admin on rest.
My GET request returns the full object without additional calls for filters and thumbnails (see below).
Example object:
{
"id": "58bd633e4b77c718e63bf931",
"title": "Project A",
"description": "Blabla",
"image": "https://placeholdit.imgix.net/~text?txtsize=33&txt=350%C3%97150&w=350&h=150",
"disable": false,
"filters": [
{
"id": "58c662aa4ea73e3d4373dad7",
"filterValue": {
"label": "Filter value",
"color": "#0094d8",
"id": "58c7999162700623b4aac559"
},
"isMain": true
}
],
"thumbnails": [
{
"id": "58bfeac780021c56cc71bfac",
"image": "http://lorempixel.com/1024/768/",
"description": "Bla",
"device": "desktop"
},
{
"id": "58bfeacf80021c56cc71bfad",
"image": "http://lorempixel.com/800/600/",
"description": "Bla",
"device": "laptop"
}
]
}
My first idea was to create custom Input Components but I don't know if it's the best solution? Any ideas or examples?
Admin-on-rest relies on redux-form, which supports nested attributes. Just set the source of your input as the path to the nested property, with dot separator:
<TextInput source="foo.bar" />
For your filters and thumbnails, you'll have to use redux-form's <Fields> component, and create a custom input component with it.