React, Node.js, Postgresql
Explore the docs »
Report Bug
·
Request Feature?
Click the title to go to the live app!
This README will systematically go over the entire app from the top level to the bottom layer, so I'll provide links to various sections for convenience.
This app is for tracking bugs in your app, offering an API for both users and developers to submit bugs and then follow-up with a kind of message board on a bug-by-bug basis. I'll quickly go over the basic functions of the client - with pictures!
- The main take-away here is that devs can see all bugs, while regular users can only see bugs they submitted themselves. That's the basic for the difference between user and developer views throughout the app.
- Here you can see your current dev status, and enter a secret to toggle it on (or off!). The current secret code is
irdev
- Here you can view all comments for the selected bug ordered by date, and create a new comment when desired.
- Here you can add a new bug, with a default status and severity set to pending, later to be updated by a dev.
Lastly, as a dev, there's an extra button above the comments when viewing a bug. Clicking the Edit Bug button leads to...
- Devs can set status and severity here, along with some other parameters if the bug was submitted incorrectly.
The Public folder is nothing special, besides the custom favicon and (as I'll note later) some imported CDNs in the head of index.html for a few Google Fonts.
As an aside, it's actually faster (from a runtime perspective) to import fonts via CDNs, as apposed to importing them directly into stylesheets
[ config.js ] - this is essentially where I store "environment" variables. One important thing to know is that React has a built-in NODE_ENV
variable that is set automatically when running scripts:
- Run Start:
NODE_ENV = developement
- Run Build:
NODE_ENV = production
Knowing this, you can take advantage and set up conditionals based on the already-available
NODE_ENV
. A major advantage is setting up API urls. When exporting like this...export default { ...config };
... you can access variables like this...
import config from '.../config.js'; ... await fetch(config.API_ENDPOINT)
[ index.js ] - bog-standard React App-wrapper using BrowserRouter [ setupTests.js ] - configuration for Enzyme testing
Fairly straight-forward Sass setup, with a simple reset and global stylesheet imported into the root index file. I won't get into Sass here, but know that I broke-out individual mixins to be used as imports in isolated [ .scss ] files
This is at the root level, but it's use is important in understanding the syntax used throughout the app. I won't go too in-depth, but essentially what's going on is it's creating a global alias for the [ src/ ] file directory. The side effect is that you can re-factor local imports:
/* deeplyNestedComponent.js */
import { PostService } from '../../../../../src/services';
...to...
import { PostService } from 'src/services';
For more info on the jsconfig.json
, check out the docs HERE!
Not strictly necessary, but this can help prevent typos, along with making changes to the database less tedious to update throughout the app.
This is where the logic for interfacing with the server lives. Each "method" has been broken-out into it's own file. [ token.service.js ] is for handling Auth-token processes.
One exception in the token.service.js
file, where all the interfacing with window.localStorage
is handled. The other is idle.service.js
, which determins the JWT expiration and regularly refreshes the stored authToken
.
This is where I keep custom hooks used by multiple components, though only 1 was needed. This hook handles every form in the app, recieving and updating piped-in form-fields. The major benefit of this kind of hook is that it minimizes the use of useState
hooks throughout the app and normalizes form handling.
This is the "hook" way of doing context, both creating the context...
export const DatabaseContext = createContext();
...and provider...
<DatabaseContext.Provider value={value}>
{props.children}
</DatabaseContext.Provider>
...in the same file. To use, you import the provider at the top level...
import DatabaseContextProvider from '.../databaseContext';
...
<DatabaseContextProvider>
(...insert components here!)
</DatabaseContextProvider>
...then invoke inside a component and just use it:
import { useContext } from 'react';
import { DatabaseContext } from '.../databaseContext';
...
const { data, functions, andMore } = useContext(DatabaseContext);
You may have already noticed that there are actually many [ index.js ] files peppered throughout the app. These are known as "barrel" exports, and have a few advantages when dealing with a complex file-directory. The index file in the [ components ] folder has a short explanation, but I'll also put it here:
/*
|------------------------------------------------------
| BARREL EXPORT FILE
|------------------------------------------------------
| How-To barrel-export components:
| export { default as Comp1 } from './comp1/comp1.js' (omit .js)
|
| Why? Readability and (to an extent) testing:
| import { Comp1, Comp2, Comp3, Comp4 } from './components'
| import { Route1, Route2, Route3, Route4 } from './routes'
*/
export { default as LoginForm } from './loginForm/loginForm'
export { default as Header } from './header/header'
etc...
You can see this in action in [ app.js ]:
import {
HomeRoute,
DashboardRoute,
LoginRoute,
RegisterRoute,
PrivateRoute,
PublicRoute,
} from 'src/routes';
Note that the import doesn't point to the index file. Node perceives [ index.js ] files as points of entry and the default file to grab exports from, essentially making it an implicit file in import statements
Nothing much to say. This is a basic point-of-entry using React-Router. The switch at the top level acts as a router for pointing those logged in/out to the right destination.
These essentially just import and render components, acting as entry points to component trees. However, I'll briefly cover...
Private/Public-Routes: This serves as a UX enhancement, both preventing users not logged in from accessing the app, and already logged in users from accessing the Login page.
I won't cover every component individually, but take a more broad-stroke approach, mentioning any note-worthy features when necessary
This acts like a new "root" component, much like the App component. There's some basic state handling at the top level, and another switch that takes care of the app proper, with the various extra context providers taking care of dynamic database operations.
This file - src/helpers/formFields.js
- is the main "constructor" for rendering forms throughout the app. Each export contains some schema data and a single method that uses the schema data and any necessary state/handlers passed in to return an array of labels and inputs. Mainly, this keeps the component files much, much leaner and easier to read!
Github - musicMan1337
LinkedIn - Derek-8Bit-Nellis
Facebook - Derek Nellis
Instagram - @derek.8bit.nellis
Github - Mark-The-Dev
LinkedIn - Mark Marcello
Github - Russjames92
<<<<<<< HEAD
=======
LinkedIn - Russell Champlain
a1e4c43fd25ec404b1e62a7569897a2b53e67f66