Staging: https://simple-panel-react-client.robertz.co (server based in Poland, app may be asleep and take time to wake up)
RAILS API: https://github.com/robertziel/simple_panel_rails_backend
Init based on https://www.reactboilerplate.com
Run using npm
cd react_client
npm run setup
npm start
Sample user:
- email:
hello@robertz.co - password:
12345678
Just sign in implemented. Other authentication features like registrations, password remind, lockable can be quickly added but I omitted them as someone may accidentally block sample account on staging :)
A simple fetching hook allows you to focus on what is the most important. Only path, body and afterSuccess callback are required to define a request to API anywhere in the project. All necessary settings and errors handling are handled under the hood and kept DRY in one place. Check folder: app/containers/BackendApiConnector/fetcher
- Use fetcher hook in your component:
import useApiFetcher from 'containers/BackendApiConnector/fetcher';
const fetcher = useApiFetcher();To make code clean it is better to use one fetcher per component.
- Now you can call fetch function in your component. Available fetchers:
fetcher.delete(options: { disableRetry, path, body, afterSuccess() })fetcher.get(options: { disableRetry, path, afterSuccess() })fetcher.post(options: { disableRetry, path, body, afterSuccess() })
More about passed params:
- options:
- disableRetry
- it's better to set it true in forms
- false as default - if fetching error occurs the processing does not stop and fetch is reported to
connectionRefusedHandler.jswhere it waits in queue to retry (check how it works by cutting your internet connection) - if set to true the processing stops and fetch is reported to
connectionRefusedHandler.jsbut it is not added to retry queue
- path (required)
- body
- afterSuccess()
- disableRetry
- You can check if fetcher is processing by the following code
fetcher.processing-
You can use ready spinner component:
import FetchedContent from 'containers/FetchedContent'; <FetchedContent processing={fetcher.processing} spinner={<CustomSpinner />} > <VisibleAfterProcessingSucceeded /> </FetchedContent>
- all authentication related containers are kept in
app/containers/_authPages app/containers/BackendApiConnectoris responsible for:- handling all requests to API
- API URL is set in
.envasBACKEND_API_URL
- API URL is set in
- keeping signed in currentUser data and authenticationToken:
- User data are not saved in cookies and application asks API to access them each time it initializes before render proper content
- authenticationToken is saved in cookies
- when any API request has authentication problem then:
- authenticationToken is set to null
- currentUser is set to null
- when authenticationToken is null SignInPage is rendered ( handled in
app/containers/BackendApiConnector/index.js)
- handling all requests to API
Repository contains basic docker setup. Depending on needs you can run app locally using both traditional npm start or docker-compose.
Docker compose is set up as default to run locally in development environment but can be easily changed for production needs.
- Build:
docker-compose build
- Start containers and check
localhost:3000:
docker-compose up
- Shut down containers:
docker-compose down
It's hard to make forms DRY, but we can adopt some conventions.
Example form can be found in containers/_authPages/SignInPage/Form.js
- keeps all form params in state and updates them on input's onChange event
onSubmit()function should be responsible for any actions made after form is submitted, in most cases it will be API fetch (check section API fetchers)- when using API fetcher:
- Please check API fetchers / Processing section
- pass
disableRetry: trueas config to fetcher so that form will not be submitted without user's knowledge
- Location
containers/InternetConnectionDetector import { isOnline }function to get current online/offline boolean value
- Based on https://www.npmjs.com/package/react-notifications-component
- path
app/containers/NotificationsSystem - notification functions should be defined in
notifications.jsfiles for each component they belong to separately, with following name formatfunction *Notify()likefunction randomNameNotify()
- CSS based on https://www.styled-components.com/
- Global style is defined in
app/styles/global-styles.js - Constants with common variables like colors etc. are defined in
app/styles/constants.js - Containers and components have own SCSS defined in
Wrapper.js
- Global style is defined in
- Basic commonly used elements like container, grid, h1 are defined in
app/components/_ui-elementsfolder- The elements' components are based on:
- https://material-ui.com
- Custom components are defined in
app/components/_ui-elements/*Corefolder likeDivCore
- Each element should be accessible in
app/components/_ui-elements/index.jsasimport { Element1, Element2 } from components/_ui-elementsby exporting its styled version - Styled version is defined in
app/components/_ui-elements/*.jsfile. For exampleapp/components/_ui-elements/Div.js- Additional style version can be added like:
So that style version (in that case named${({ topLine }) => topLine && css` border-top: 4px solid ${colors.main} ` }
topLine) can be used in element by adding it to props<Div topLine />- If https://material-ui.com element is styled please use the following convention (styled-components/styled-components#1198 (comment))
/* eslint-disable react/jsx-props-no-spreading, indent */ import React from 'react'; // then define additional style called here as topLine const Button = styled(({ topLine, ...props }) => <ButtonCore {...props} />)` // some code // then define additional style as mentioned above ${({ topLine }) => topLine && css` border-top: 4px solid ${colors.main} ` } `;
- The elements' components are based on:
BUG -app/containers/BackendApiConnector/connectionRefusedHandler.js:should refetch on click or after time, only if refetch queue is not empty (currently refetch is handled when notification disappears)Fix issue with queued refetch related to unmounted components, should be ignored
- fix styles, make sure mobile UI is working well
- Add Users page with actions (show, new, edit, delete)
- Implement User roles system
- Add simple Profile page (show, edit)