nazirov91 / ra-strapi-rest Goto Github PK
View Code? Open in Web Editor NEWReact Admin data provider for Strapi.js
React Admin data provider for Strapi.js
Hello,
In the README, you state that we must update the controller for each model we have, overriding the async find method in the controller file. However, Since the user model is automatically included with Strapi, there is no controller file for the user model. How do you suppose we get rid of the cors error associated when trying to access the user data.
What am i missing here? i've defined the "create", "edit" and "show" functions, yet no buttons appear in the list at all. if i manually enter the url's for these routes they work as expected, but nothing appears in the list view to access these? Using Strapi 3.6.8 on the latest version of React Admin.
Thank you for a great effort. Just what I was looking for. Could you give a tip on what settings should be in the authProvider to connect to Strapi?
Tried the following but it doesn't seem to work:
if (type === AUTH_LOGIN) {
const { username, password } = params;
const request = new Request('http://localhost:1337/auth/local', {
method: 'POST',
body: JSON.stringify({ username, password }),
headers: new Headers({ 'Content-Type': 'application/json' }),
})
return fetch(request)
.then(response => {
if (response.status < 200 || response.status >= 300) {
throw new Error(response.statusText);
}
return response.json();
})
.then(({ token }) => {
localStorage.setItem('token', token);
});
}
return Promise.resolve();
I am working on a small example application to get familiar with Strapi and React-Admin and am attempting to upload an image using the ImageInput component. I feel like I've read your documentation at https://github.com/nazirov91/ra-strapi-rest#file-upload and React-Admins at ImageInput at https://marmelab.com/react-admin/Inputs.html.
Right now I only have a single field that allows file upload so my App.js
has:
const uploadFields = ["avatar"];
And is being passed in verbatim as what you've written in the documentation:
const dataProvider = simpleRestProvider('http://localhost:1337', httpClient, uploadFields);
For my create screen I also have your code verbatim as:
<ImageInput source="avatar" label="Avatar" accept="image/*">
<ImageField source="url" title="name" />
</ImageInput>
Inside of my person.settings.json
the field is referenced as:
"avatar": {
"model": "file",
"via": "related",
"allowedTypes": [
"images"
],
"plugin": "upload",
"required": false
},
Whenever I hit save on the form I see the following error logged from the server:
error CastError: Cast to ObjectId failed for value "[]" at path "avatar"
at new CastError (server\node_modules\mongoose\lib\error\cast.js:39:11)
at ObjectId.cast (server\node_modules\mongoose\lib\schema\objectid.js:246:11)
When I inspect the post request I do see it sending an empty array as the field which makes me think that's likely where the error is coming from, the POST request is:
-----------------------------3577480103102910508985816256
Content-Disposition: form-data; name="data"
{"fullname":"Bob Smith","avatar":[]}
-----------------------------3577480103102910508985816256--
I think this is an issue with how the uploaded files are being mapped to the fields but first wanted to see if you saw anything I had missed. I also wanted to thank you for providing the ra-strapi-rest
as it did save me a ton of time in getting an example application up and running with React-Admin
I am trying to perform a simple fetch with strapi rest. I am able to fetch the data with Resource from react-admin but when i want to fetch a single record with custom query or a getList in useEffect i am not able to do so
import simpleRestProvider from 'ra-strapi-rest';
const strapiDataProvider = simpleRestProvider(
'http://localhost:1337'
);
useEffect(() => {
strapiDataProvider
.getList('customers')
.then((data: any) => {
console.log('data: ', data);
})
.catch((error: any) => {
console.log('error: ', error);
});
}, []);
I am getting following error
TypeError: dataProvider_server_rest__WEBPACK_IMPORTED_MODULE_3_.strapiDataProvider.getList is not a function
I have also tried to get a single record
useEffect(() => {
strapiDataProvider
.getOne('customers', { id: 61 })
.then((data:any) => {
console.log('data: ', data);
})
.catch((error: any) => {
console.log('error: ', error);
});
}, []);
I am getting same error for the above as well
TypeError: dataProvider_server_rest__WEBPACK_IMPORTED_MODULE_3_.strapiDataProvider.getOne is not a function
What am i doing wrong?
I try using Relationship, but I don`t get category date
I have a api to get all categories
http://localhost:1337/categories
Strapi v4 was released a couple of days ago.
Are there any plans to update this procject to make use of the new response format, filters etc. of strapi v4?
By Default, when strapi is returning the url to an image it only returns beginning with the "/uploads/[id]". Is there anyway to get the entire url to return so that we can use the ImageField Elements in ReactAdmin?
Hello!
I'm facing another problem. In this case with the Has and belongs to many relation from Strapi.
Example, I have an entity called users and an entity called projects. Users are assigned to multiple projects and a project has many users assigned.
This is supposed to be working in react admin with something like:
<ReferenceArrayInput
source="project"
reference="projects"
label="Projects"
>
<SelectArrayInput optionText="name" label="Choose project" />
</ReferenceArrayInput>
<ReferenceArrayField source="project" reference="projects">
<SingleFieldList>
<ChipField source="name" />
</SingleFieldList>
</ReferenceArrayField>
I've tried on source adding .id, .ids, _ids but is not working. Any idea why? Thanks!
Strapi refuses to update data due to the created_at
and updated_at
fields in the request. A possible solution would be to remove these fields from params.data. Or you can limit the updated data in the react-admin itself?
Problem code
case UPDATE:
url = `${apiUrl}/${resource}/${params.id}`;
options.method = 'PUT';
delete params.data["created_at"];
delete params.data["updated_at"];
options.body = JSON.stringify(params.data);
break;
UPDATE for the admin:
Please delete this issue, I found the fix, I forgot to add the 'http' client, and this had nothing to do with what I asked. Thanks.
This issue was already created, but I didn't get response so I created this new thread.
Please see my response
@nazirov91 I am running into this problem as well, it goes away when I change this to
if(existingFileIds.length === 1){
data[fieldName] = existingFileIds[0];
}else if (existingFileIds.length > 1) {
data[fieldName] = [...existingFileIds];
}
I am not sure that this will play nice in all scenarios tho, maybe you have more insight on this.
How to use this data provider for strapi's beta version as using this data provider requires us to add a Content-Range header in the strapi's controller's plugin which is not provided in the beta version.
In beta version of strapi the controller's and service's are empty for any plugin we install externally.
Hi!
I am trying to load images following the instructions from readme.md
And when I pass field name to the data provider I am getting the following error: Unhandled Rejection (Error): The dataProvider threw an error. It should return a rejected Promise instead.
// <strapi_project>/api/dish/models/dish.settings.json
...
"image": {
"model": "file",
"via": "related",
"allowedTypes": [
"images"
],
"plugin": "upload",
"required": false,
"pluginOptions": {}
},
...
in App.js:
const uploadFields = ["image"];
const dataProvider = simpleRestProvider(baseUrl, uploadFields);
I am not sure if this is going to work anymore cause i see the post and get request it is trying to call /count and gets 404. also it does not automatically get all the fields. So were do i find the updated one ?
I noticed that using the code as it-is from the Example will throw an error in Strapi console
TypeError: Cannot read property 'source' of undefined
I fixed the error by sending the ctx.query as a parameter in the count method plus using the fully qualified class name as below:
ctx.set('Content-Range', await strapi.services.<Model>.count(ctx.query));
My Node/Strapi : Version: 3.0.0-alpha.25.2 (node v11.1.0)
Hi is is possible to handle file uploading to Strapi for some records in the future? I have tried using FormData and FileInput from react-admin but was not able to produce successful result. Thanks
Hi @nazirov91
Thanks for creating this plugin and maintaining it.
This is a follow up question on issue #9.
Do you have an example with a middleware to implement the content-range behaviour for all routes?
Another option could be to request the total with the count route:
strapiAPI/MY-MODEL/count
An additional request could be worth it and it shouldn't be too complicated to implement 👍
What do you think?
Hello, I'm using and ArrayInput like this:
<ArrayInput source="webs">
<SimpleFormIterator>
<TextInput source="name" />
<TextInput source="web" />
</SimpleFormIterator>
</ArrayInput>
In Strapi I have a JSON field to store this data. When I save in react admin the data in Strapi is being saved this way:
[
{
"name": "coolName",
"web": "coolUrl"
}
]
In react admin it recognizes there is a record or more than one but the information is not showing in any of the views.
Show view:
<Datagrid>
<TextField source="name" />
<UrlField source="web" />
</Datagrid>
</ArrayField>
Any idea why the data is not displaying correctly?
Thanks a lot for the work you put into this, it's making my life a lot easier for building a small internal app. When it came to following your auth provider, the examples were slightly off for the versions I was running. For example, the user's plugin directory structure has changed ever so slightly
I'm using:
Strapi - 3.0.0-beta.19.3
React-Admin - 3.3.0
I was able to get it working with
// App.js
const httpClient = (url, options = {}) => {
if (!options.headers) {
options.headers = new Headers({ Accept: 'application/json' })
}
const token = Cookies.getCookie('token') // <-- Change localstorage to the cookie helper
options.headers.set('Authorization', `Bearer ${token}`)
return fetchUtils.fetchJson(url, options)
}
// authProvider.js
import Cookies from './helpers/Cookies'
export default {
login: ({ username, password }) => {
const identifier = username // <-- Changing username to match Strapi's identifier requirement
const request = new Request('http://localhost:1337/auth/local', {
method: 'POST',
body: JSON.stringify({ identifier, password }),
headers: new Headers({ 'Content-Type': 'application/json'})
});
return fetch(request)
.then(response => {
if (response.status < 200 || response.status >= 300) {
throw new Error(response.statusText);
}
return response.json();
})
.then(response => {
Cookies.setCookie('token', response.jwt, 1);
Cookies.setCookie('role', response.user.role.name, 1);
});
},
logout: () => {
Cookies.deleteCookie('token');
Cookies.deleteCookie('role');
return Promise.resolve();
},
checkAuth: () => {
return Cookies.getCookie('token') ? Promise.resolve() : Promise.reject();
},
checkError: ({ status }) => {
if (status === 401 || status === 403) {
Cookies.deleteCookie('token');
Cookies.deleteCookie('role');
return Promise.reject();
}
return Promise.resolve();
},
getPermissions: () => {
const role = Cookies.getCookie('role');
return role ? Promise.resolve(role) : Promise.reject();
},
}
This may just fit my use case, but just wanted to make sure to help others if they come across this issue. Let me know if you would like this issue as a pull request instead.
I have a find permission on my strapi model for public, I did go through all the steps for strapi, added the content-range and replaced the cors with provided code.
I also imported the strapi-provider file in App.js and passed the URL both localhost:1338 and http://localhost:1338. My endpoint is seller-subscriptions and I passed in the Resource but I got the "An internal server error occurred".
Thanks
I fail to understand if this Data Provider is supposed to work with Strapi Realtions and React-Admins ReferenceManyField or ReferenceArrayField - can you please add examples to the ReadMe for those use cases ?
For my specific issue:
I have 2 collections Users and Groups - with a one user to many groups relation field in strapi (reference field is called re_groups in users and re_users in groups)
if i use a 1:1 relation this works without an issue
<ReferenceField source="re_users.id" reference="users"> <TextField source="username" /> </ReferenceField>
but if i use a ReferenceManyField target seems to be ignored or i simply dont understand what the target is supposed to be:
according to https://marmelab.com/react-admin/Fields.html#reference-fields
accepts a reference attribute, which specifies the resource to fetch for the related record. It also accepts a source attribute which defines the field containing the value to look for in the target field of the referenced resource. By default, this is the id of the resource (post.id in the previous example).
<ReferenceManyField label="Comments by" reference="users" target="???"> <SingleFieldList> <ChipField source="username" /> </SingleFieldList> </ReferenceManyField>
same goes for the ReferenceArrayField - basic examples with the relationship field of strapi should get added.
thank you!
after login using it
import React from 'react';
import authProvider from './authProvider';
//import dataProvider from './dataProvider';
import { fetchUtils, Admin, Resource ,ListGuesser} from 'react-admin';
import simpleRestProvider from './helpers/rest.strapi';
import { apiUrl } from './config';
const httpClient = (url, options = {}) => {
if (!options.headers) {
options.headers = new Headers({ Accept: 'application/json' });
}
const token = localStorage.getItem('token');
options.headers.set('Authorization', `Bearer ${token}`);
return fetchUtils.fetchJson(url, options);
}
const dataProvider = simpleRestProvider(apiUrl, httpClient);
const App = () => (
<Admin authProvider={authProvider} dataProvider={dataProvider}>
<Resource name="products" list={ListGuesser} />
</Admin>
);
export default App;
display it
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?
When A schema from strapi includes a 'component' field; It will be replaced with IDs hence the 'show' and 'Edit' will fail to show proper data. (since components do not have 'crud's in strapi)
I had To Do Something Like This:
const replaceRefObjectsWithIds = json => {
Object.keys(json).forEach(key => {
const fd = json[key]; // field data
const referenceKeys = [];
if (fd && (fd.id || fd._id) && !fd.mime) {
json[key] = fd.id || fd._id;
} else if (Array.isArray(fd) && fd.length > 0 && !fd[0].mime) {
fd.map(item => referenceKeys.push(item.id || item._id));
if(key != "KEY_IN_DOCUMENT_REFERS_TO_AN_ARRAY_OF_COMPONENTS") { // HERE -----------
json[key] = referenceKeys;
}
}
});
To Avoid component values being replaced with IDs
Hello, I have a model with Accounts and Projects. The relation is one account can have many projects and one project is related to one account.
This is working fine in creation, updating and showing views but not in List view. The code is the same for Show and List:
<ReferenceField source="account" reference="accounts" label="Account">
<TextField source="name" />
</ReferenceField>
Also, I have a filter by Account in the List view and it's properly working.
Any idea why the reference field is not showing data in the list view?
Hello :)
I try to use to very great module with react-admin and strapi. But i've question about Pagination, because my Content-Range is present in my header, but the pagination don't show the correct count and button next/prev.
I've try with static count (ex. 500), but same result.
Do you know if we need other setting ?
Thank you !
In the readme example, using fetchAll
doesnt work. Use find
instead. e.g
find: async (ctx) => {
ctx.set('Content-Range', await <Model_Name>.count());
if (ctx.query._q) {
return strapi.services.<Model_Name>.search(ctx.query);
} else {
return strapi.services.<Model_Name>.find(ctx.query);
}
},
I'm using Strapi for the backend and ra-strapi-rest
dataProvider in react-admin
but I'm experiencing some issues.
For instance, Strapi sends a ValidationError
this way:
{"statusCode":400,"error":"Bad Request","message":"ValidationError","data":{"errors":{"members":["members must be greater than or equal to 1"]}}}
·
This results in a single error Notification on react-admin
which only displays: "ValidationError" instead of a more descriptive error or errors.
Any ideas on how to fix this?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.