kimkha / aor-loopback Goto Github PK
View Code? Open in Web Editor NEWLoopback-style REST Client for Admin-on-rest
License: MIT License
Loopback-style REST Client for Admin-on-rest
License: MIT License
Hello
Am using aor-loopback to connect with my API.
ON trying to create image upload capability I used the following aor guide to create a wrapper on aor-loopback
Here is my wrapper code.
const fileUploadRESTWrapper = requestHandler => (type, resource, params) => {
if (type === 'UPDATE' && resource === 'tales') {
if (params.data.faceBookImage && params.data.faceBookImage.length) {
let form = new FormData()
form.append('file', params.data.faceBookImage[0]);
delete params.data.faceBookImage
form.append('model', JSON.stringify(params.data))
return requestHandler(type, resource, {
...params,
data: form
},
)
}
}
return requestHandler(type, resource, params);
};
export default fileUploadRESTWrapper;
I encountered some issues. After looking through the aor-loopback source code I found that
case _types.UPDATE:
url = apiUrl + '/' + resource + '/' + params.id;
options.method = 'PUT';
options.body = JSON.stringify(params.data);
break;
aor-loopback is JSON.stringifying the entire response body. Stringifying is removing the image from the FormData object.
Suggestions: It would be great if you could also export the fetchJson method from the package. Someone like me could then create a case in the wrapper above.
url = apiUrl + '/' + resource + '/' + params.id;
options.method = 'PUT';
options.body = params.data
fetchJson(url, options)
This should solve a number of other use cases including create etc.
Above is just a suggestion and you may choose any other idea to account for the image upload use case as well.
Thanks and regards
Could you please add support for these?
https://github.com/marmelab/admin-on-rest/blob/next/UPGRADE.md#data-providers-should-support-two-more-types-for-bulk-actions
I am using the 'next' branch and this would be great, if possible!
Thanks!
Hi @kimkha ,
I try to create a page for create user for admin. I set create
attribute of related Resource
and create a for with below content:
export const UserCreate = (props) => (
<Create {...props}>
<SimpleForm>
<TextInput source="username" validate={ required }/>
<TextInput source="email" type="email" validate={ required }/>
<TextInput source="password" type="password" validate={ required }/>
</SimpleForm>
</Create>
);
But when I fill this form and click submit button my user is going to logout. What is the problem?
Hi,
I will upgrade to AOR version 2 today (now known as "react-admin" version 2).
Because of the rename of "admin-on-rest" to "react-admin", I believe that there is a need to have a different npm package, like they already did with aor-dependent-input: they created another one for ra: https://www.npmjs.com/package/ra-dependent-input
Can this be done please?
Thanks!
Hi @kimkha, I create a simple create form for my users and it's worked well but when I try to add a repeatPassword
field it's not working with this error on browser console:
Unprocessable Entity
Warning: Missing translation for key: "Unprocessable Entity"
This is my form code:
const passwordsMatch = ({ password, confirmPassword }) => {
return password === confirmPassword;
};
export const EmployeeCreate = (props) => (
<Create {...props}>
<SimpleForm validate={passwordsMatch}>
<TextInput source="username" validate={ required }/>
<TextInput source="email" type="email" validate={ required }/>
<TextInput source="name" validate={ required }/>
<TextInput source="family" validate={ required }/>
<TextInput source="password" type="password" validate={ required }/>
<TextInput source="repeatPassword" type="password" validate={ required }/>
</SimpleForm>
</Create>
);
Are you any suggestion to fix it?
SO question: https://stackoverflow.com/questions/48898743/prevent-field-to-send-in-request
E.g. if I want to update the default loopback user model I have to specify all the attributes when using PUT, which is not even possible as I can not have my user re-enter the password every time.
I created a fork under Zoom7/aor-loopback for the time being that does simply replace PUT with PATCH, so I can proceed. Maybe this is also an option for aor-loopback.
Line 17 in b11dca3
Hello, first of all, thank you very much for your work, it has been excellent and it works well with admin on rest, but I do not understand the objective of this line, because I do not simply return the token? Thank you
Hi @kimkha I try using your RestClient but it's return below error:
The X-Total-Count header is missing in the HTTP Response. The jsonServer REST client 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 X-Total-Count in the Access-Control-Expose-Headers header?
Do you have any idea?
Hello.
First of all thanks a lot of writing this code. Saved me a lot of time.
However I see that the getList case is not being handled by the code in index.js
cannot really move forward as my first page is a list view of posts.
Any suggestions?
This is my code
<ReferenceField label={'Album'} source="albumId" reference="albums" allowEmpty linkType={false}>
<TextField source="name" />
</ReferenceField>
This is the error
11:36:46.115 Navigated to http://localhost:3000/
11:36:48.902 proxyConsole.js:54 uncaught at handleFetch TypeError: Cannot read property 'data' of undefined
at Function.mapStateToProps [as mapToProps] (http://localhost:3000/static/js/bundle.js:6873:64)
at mapToPropsProxy (http://localhost:3000/static/js/bundle.js:128653:46)
at Function.detectFactoryAndVerify (http://localhost:3000/static/js/bundle.js:128662:19)
at mapToPropsProxy (http://localhost:3000/static/js/bundle.js:128653:46)
at handleFirstCall (http://localhost:3000/static/js/bundle.js:128487:18)
at pureFinalPropsSelector (http://localhost:3000/static/js/bundle.js:128535:81)
at Object.runComponentSelector [as run] (http://localhost:3000/static/js/bundle.js:127933:25)
at Connect.initSelector (http://localhost:3000/static/js/bundle.js:128085:23)
at new Connect (http://localhost:3000/static/js/bundle.js:128026:15)
at http://localhost:3000/static/js/bundle.js:108118:18
at measureLifeCyclePerf (http://localhost:3000/static/js/bundle.js:107899:12)
at ReactCompositeComponentWrapper._constructComponentWithoutOwner (http://localhost:3000/static/js/bundle.js:108117:16)
at ReactCompositeComponentWrapper._constructComponent (http://localhost:3000/static/js/bundle.js:108108:19)
at ReactCompositeComponentWrapper.mountComponent (http://localhost:3000/static/js/bundle.js:108011:21)
at Object.mountComponent (http://localhost:3000/static/js/bundle.js:114771:35)
at ReactDOMComponent.mountChildren (http://localhost:3000/static/js/bundle.js:114109:44)
at ReactDOMComponent._createInitialChildren (http://localhost:3000/static/js/bundle.js:109556:32)
at ReactDOMComponent.mountComponent (http://localhost:3000/static/js/bundle.js:109375:12)
at Object.mountComponent (http://localhost:3000/static/js/bundle.js:114771:35)
at ReactCompositeComponentWrapper.performInitialMount (http://localhost:3000/static/js/bundle.js:108194:34)
at ReactCompositeComponentWrapper.mountComponent (http://localhost:3000/static/js/bundle.js:108081:21)
at Object.mountComponent (http://localhost:3000/static/js/bundle.js:114771:35)
at ReactCompositeComponentWrapper.performInitialMount (http://localhost:3000/static/js/bundle.js:108194:34)
at ReactCompositeComponentWrapper.mountComponent (http://localhost:3000/static/js/bundle.js:108081:21)
at Object.mountComponent (http://localhost:3000/static/js/bundle.js:114771:35)
at ReactDOMComponent.mountChildren (http://localhost:3000/static/js/bundle.js:114109:44)
at ReactDOMComponent._createInitialChildren (http://localhost:3000/static/js/bundle.js:109556:32)
at ReactDOMComponent.mountComponent (http://localhost:3000/static/js/bundle.js:109375:12)
at Object.mountComponent (http://localhost:3000/static/js/bundle.js:114771:35)
at ReactCompositeComponentWrapper.performInitialMount (http://localhost:3000/static/js/bundle.js:108194:34)
at ReactCompositeComponentWrapper.mountComponent (http://localhost:3000/static/js/bundle.js:108081:21)
at Object.mountComponent (http://localhost:3000/static/js/bundle.js:114771:35)
at Object.updateChildren (http://localhost:3000/static/js/bundle.js:107692:51)
at ReactDOMComponent._reconcilerUpdateChildren (http://localhost:3000/static/js/bundle.js:114079:32)
at ReactDOMComponent._updateChildren (http://localhost:3000/static/js/bundle.js:114183:31)
at ReactDOMComponent.updateChildren (http://localhost:3000/static/js/bundle.js:114170:12)
at ReactDOMComponent._updateDOMChildren (http://localhost:3000/static/js/bundle.js:109799:12)
at ReactDOMComponent.updateComponent (http://localhost:3000/static/js/bundle.js:109613:10)
at ReactDOMComponent.receiveComponent (http://localhost:3000/static/js/bundle.js:109575:10)
at Object.receiveComponent (http://localhost:3000/static/js/bundle.js:114850:22)
at ReactCompositeComponentWrapper._updateRenderedComponent (http://localhost:3000/static/js/bundle.js:108577:23)
at ReactCompositeComponentWrapper._performComponentUpdate (http://localhost:3000/static/js/bundle.js:108547:10)
at ReactCompositeComponentWrapper.updateComponent (http://localhost:3000/static/js/bundle.js:108468:12)
at ReactCompositeComponentWrapper.receiveComponent (http://localhost:3000/static/js/bundle.js:108370:10)
at Object.receiveComponent (http://localhost:3000/static/js/bundle.js:114850:22)
at ReactCompositeComponentWrapper._updateRenderedComponent (http://localhost:3000/static/js/bundle.js:108577:23)
at ReactCompositeComponentWrapper._performComponentUpdate (http://localhost:3000/static/js/bundle.js:108547:10)
at ReactCompositeComponentWrapper.updateComponent (http://localhost:3000/static/js/bundle.js:108468:12)
at ReactCompositeComponentWrapper.receiveComponent (http://localhost:3000/static/js/bundle.js:108370:10)
at Object.receiveComponent (http://localhost:3000/static/js/bundle.js:114850:22)
__stack_frame_overlay_proxy_console__ @ proxyConsole.js:54
log @ utils.js:225
(anonymous) @ proc.js:483
exec @ scheduler.js:19
flush @ scheduler.js:60
asap @ scheduler.js:33
runPutEffect @ proc.js:476
runEffect @ proc.js:425
next @ proc.js:306
currCb @ proc.js:378
I need to set some authorization rule for my admin Resource
for example hide some Resource
from side menu and prevent access to it.
I read https://marmelab.com/admin-on-rest/Authorization.html and see this package https://github.com/marmelab/aor-permissions and also try this:
const App = () => (
<Admin
theme={ myTheme }
restClient={loopbackRestClient('http://0.0.0.0:3001/api')}
authClient={authClient('http://0.0.0.0:3001/api/Employees/login')}
>
{ permissions => [
permissions === 'admin' ? <Resource name="employees" icon={ EmployeeIcon } list={EmployeeList} show={EmployeeShow} create={EmployeeCreate} edit={EmployeeEdit} remove={Delete} /> : null,
<Resource name="projects" icon={ ProjectIcon } list={ProjectList} show={ProjectShow} create={ProjectCreate} edit={ProjectEdit} remove={Delete} />
]}
</Admin>
);
export default App;
I used below code in my LoopBack boot script to create my roles:
Role.create({
name: 'admin',
}, function(err, role) {
if (err) throw err;
...
But it's render below page after login with any user:
and this is my console error logs:
Warning: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead.
bundle.js:11865:10
Warning: Missing translation for key: "aor.page.not_found"
browser.js:49
Warning: Missing translation for key: "aor.message.not_found"
browser.js:49
Warning: Missing translation for key: "aor.action.back"
browser.js:49
uncaught exception: Unkown method
I use ra-loopback. And I want to add a role during authorization. I tried to add a role like this:
./authClient.js
import storage from './storage';
import {decode} from 'jsonwebtoken';
export const authClient = (loginApiUrl, noAccessPage = '/login') => {
return (type, params) => {
if (type === 'AUTH_LOGIN') {
const request = new Request(loginApiUrl, {
method: 'POST',
body: JSON.stringify(params),
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}) => {
const decoded = decode(token);
storage.save('lbtoken',token);
storage.save('role', decoded.role);
});
}
if (type === 'AUTH_LOGOUT') {
storage.remove('lbtoken');
return Promise.resolve();
}
if (type === 'AUTH_ERROR') {
const status = params.message.status;
if (status === 401 || status === 403) {
storage.remove('lbtoken');
return Promise.reject();
}
return Promise.resolve();
}
if (type === 'AUTH_CHECK') {
const token = storage.load('lbtoken');
if (token && token.id) {
return Promise.resolve();
} else {
storage.remove('lbtoken');
return Promise.reject({ redirectTo: noAccessPage });
}
}
if (type === 'AUTH_GET_PERMISSIONS') {
const role = localStorage.getItem('role');
return role ? Promise.resolve(role) : Promise.reject();
}
return Promise.reject('Unknown method');
};
};
When i tried to login, i get an error 'Cannot read property 'role' of null'
I understand it says the plugin will only work with older versions of Admin on Rest.
Is there any chance this can be updated to work with the new react-admin?
When you delete a record, you receive an error message in the response format:
"The response to 'DELETE' must be like { data: { id: 123, ... } }, but the received data does not have an 'id' key. The dataProvider is probably wrong for 'DELETE'"
Hi kimkha,
first of all thanks a lot for writing this client. This is really helpful and speeds up the development process.
I'm having trouble getting the ReferenceArrayInput to work. I implemented it as described here
Displaying the same property in a ReferenceArrayField works as expected. Also, the ReferenceArrayInput correctly displays the possible Choices (Tags, in my case). However when i click on one of them, nothing happens (they don't get added to the list of Tags). When i add them manually through the Loopback Explorer, they get displayed correctly and i can also remove them.
I don't see any console output or network traffic. One thing that is different from the examples is that my IDs are not numbers but strings. Could that be the issue? Let me know if there's anything i can do to help debug/fix the problem.
Regards
Hi @kimkha ,
I think it's better to have a simple example for this package.
I suggest the code block below to add 'like' statement:
if (query['where'] ) { var json = query['where']; query['where'] = {}; Object.keys(json).forEach(function(key) { query['where'][key] = { "like" : json[key], "options":"i" } ; }); }
in src/index.js after
query['where'] = {...params.filter}; //line 41
Hi, do we need any changes for the new (BETA) version of AOR that has just been released?
Or the package can remain the same?
Thanks!
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.