Fix "used before it was defined" warning
* updated react-scripts (fix eslint-plugin problems) * reorder functions where needed
This commit is contained in:
parent
c12aadef04
commit
b26d6d6e69
|
@ -13,7 +13,10 @@ parserOptions:
|
||||||
plugins:
|
plugins:
|
||||||
- react
|
- react
|
||||||
- '@typescript-eslint'
|
- '@typescript-eslint'
|
||||||
rules: {}
|
rules:
|
||||||
|
no-use-before-define: off
|
||||||
|
"@typescript-eslint/no-use-before-define":
|
||||||
|
- error
|
||||||
settings:
|
settings:
|
||||||
react:
|
react:
|
||||||
version: detect
|
version: detect
|
||||||
|
|
10927
redaktions-app/package-lock.json
generated
10927
redaktions-app/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -12,7 +12,7 @@
|
||||||
"react": "^16.13.1",
|
"react": "^16.13.1",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "^3.4.4",
|
"react-scripts": "^4.0.2",
|
||||||
"typescript": "^3.8",
|
"typescript": "^3.8",
|
||||||
"notistack": "^1.0.3"
|
"notistack": "^1.0.3"
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,22 +5,6 @@ import { Redirect, Route, RouteProps, Switch } from "react-router-dom";
|
||||||
import SignIn from "./components/SignIn";
|
import SignIn from "./components/SignIn";
|
||||||
import SignUp from "./components/SignUp";
|
import SignUp from "./components/SignUp";
|
||||||
|
|
||||||
function App(): React.ReactElement {
|
|
||||||
return (
|
|
||||||
<Switch>
|
|
||||||
<PrivateRoute exact path={"/"}>
|
|
||||||
<Main />
|
|
||||||
</PrivateRoute>
|
|
||||||
<NotLoggedInOnlyRoute path={"/login"}>
|
|
||||||
<SignIn />
|
|
||||||
</NotLoggedInOnlyRoute>
|
|
||||||
<NotLoggedInOnlyRoute path={"/signup"}>
|
|
||||||
<SignUp />
|
|
||||||
</NotLoggedInOnlyRoute>
|
|
||||||
</Switch>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const isLoggedIn = (): boolean => !!localStorage.getItem("token");
|
export const isLoggedIn = (): boolean => !!localStorage.getItem("token");
|
||||||
|
|
||||||
function PrivateRoute({ children, ...rest }: RouteProps) {
|
function PrivateRoute({ children, ...rest }: RouteProps) {
|
||||||
|
@ -62,4 +46,20 @@ function NotLoggedInOnlyRoute({ children, ...rest }: RouteProps) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function App(): React.ReactElement {
|
||||||
|
return (
|
||||||
|
<Switch>
|
||||||
|
<PrivateRoute exact path={"/"}>
|
||||||
|
<Main />
|
||||||
|
</PrivateRoute>
|
||||||
|
<NotLoggedInOnlyRoute path={"/login"}>
|
||||||
|
<SignIn />
|
||||||
|
</NotLoggedInOnlyRoute>
|
||||||
|
<NotLoggedInOnlyRoute path={"/signup"}>
|
||||||
|
<SignUp />
|
||||||
|
</NotLoggedInOnlyRoute>
|
||||||
|
</Switch>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|
|
@ -33,6 +33,22 @@ const useStyles = makeStyles((theme) => ({
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
export const getIconForPosition = (
|
||||||
|
position: CandidatePosition,
|
||||||
|
props?: SvgIconProps
|
||||||
|
): JSX.Element => {
|
||||||
|
switch (position) {
|
||||||
|
case CandidatePosition.positive:
|
||||||
|
return <ThumbUpIcon {...props} />;
|
||||||
|
case CandidatePosition.neutral:
|
||||||
|
return <RadioButtonUncheckedIcon {...props} />;
|
||||||
|
case CandidatePosition.negative:
|
||||||
|
return <ThumbDown {...props} />;
|
||||||
|
case CandidatePosition.skipped:
|
||||||
|
return <CloseIcon {...props} />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export function CandidatePositionLegend(): React.ReactElement {
|
export function CandidatePositionLegend(): React.ReactElement {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
|
@ -57,19 +73,3 @@ export function CandidatePositionLegend(): React.ReactElement {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getIconForPosition = (
|
|
||||||
position: CandidatePosition,
|
|
||||||
props?: SvgIconProps
|
|
||||||
): JSX.Element => {
|
|
||||||
switch (position) {
|
|
||||||
case CandidatePosition.positive:
|
|
||||||
return <ThumbUpIcon {...props} />;
|
|
||||||
case CandidatePosition.neutral:
|
|
||||||
return <RadioButtonUncheckedIcon {...props} />;
|
|
||||||
case CandidatePosition.negative:
|
|
||||||
return <ThumbDown {...props} />;
|
|
||||||
case CandidatePosition.skipped:
|
|
||||||
return <CloseIcon {...props} />;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
|
@ -8,23 +8,6 @@ export interface SignUpError {
|
||||||
passwordInvalid: boolean;
|
passwordInvalid: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parseErrorMessage = (error: ApolloError): string => {
|
|
||||||
let result = "Sign-up failed because of the following reason(s): ";
|
|
||||||
if (isEmailAlreadyUsed(error)) {
|
|
||||||
result += "The E-Mail is already in use. ";
|
|
||||||
}
|
|
||||||
if (isFirstNameInvalid(error)) {
|
|
||||||
result += "The provided 'First Name' is invalid. ";
|
|
||||||
}
|
|
||||||
if (isLastNameInvalid(error)) {
|
|
||||||
result += "The provided 'Last Name' is invalid. ";
|
|
||||||
}
|
|
||||||
if (isPasswordInvalid(error)) {
|
|
||||||
result += "The provided password is invalid. ";
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
const isEmailAlreadyUsed = (error: ApolloError): boolean => {
|
const isEmailAlreadyUsed = (error: ApolloError): boolean => {
|
||||||
const errorMessage = error.message.toLowerCase();
|
const errorMessage = error.message.toLowerCase();
|
||||||
|
|
||||||
|
@ -53,6 +36,23 @@ const isPasswordInvalid = (error: ApolloError): boolean => {
|
||||||
return errorMessage.includes("invalid") && errorMessage.includes("password");
|
return errorMessage.includes("invalid") && errorMessage.includes("password");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const parseErrorMessage = (error: ApolloError): string => {
|
||||||
|
let result = "Sign-up failed because of the following reason(s): ";
|
||||||
|
if (isEmailAlreadyUsed(error)) {
|
||||||
|
result += "The E-Mail is already in use. ";
|
||||||
|
}
|
||||||
|
if (isFirstNameInvalid(error)) {
|
||||||
|
result += "The provided 'First Name' is invalid. ";
|
||||||
|
}
|
||||||
|
if (isLastNameInvalid(error)) {
|
||||||
|
result += "The provided 'Last Name' is invalid. ";
|
||||||
|
}
|
||||||
|
if (isPasswordInvalid(error)) {
|
||||||
|
result += "The provided password is invalid. ";
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
export const errorHandler = (
|
export const errorHandler = (
|
||||||
error: undefined | ApolloError
|
error: undefined | ApolloError
|
||||||
): undefined | SignUpError => {
|
): undefined | SignUpError => {
|
||||||
|
|
|
@ -1,10 +1,29 @@
|
||||||
|
type UserRole = "candymat_editor" | "candymat_candidate" | "candymat_person";
|
||||||
|
|
||||||
|
interface JwtPayload {
|
||||||
|
role: UserRole;
|
||||||
|
person_row_id: number;
|
||||||
|
exp: number;
|
||||||
|
iat: number;
|
||||||
|
aud: "postgraphile";
|
||||||
|
iss: "postgraphile";
|
||||||
|
}
|
||||||
|
|
||||||
|
const claims = ["role", "person_row_id", "exp", "iat", "aud", "iss"];
|
||||||
|
const userRoles = ["candymat_editor", "candymat_candidate", "candymat_person"];
|
||||||
|
|
||||||
export const getRawJsonWebToken = (): string | null => {
|
export const getRawJsonWebToken = (): string | null => {
|
||||||
return localStorage.getItem("token");
|
return localStorage.getItem("token");
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getJsonWebToken = (): JwtPayload | null => {
|
export const isJwtPayloadValid = (jwtPayload: JwtPayload): boolean => {
|
||||||
const rawToken = getRawJsonWebToken();
|
return (
|
||||||
return rawToken ? parseJwt(rawToken) : null;
|
claims.every((claim) => Object.keys(jwtPayload).includes(claim)) &&
|
||||||
|
userRoles.includes(jwtPayload.role) &&
|
||||||
|
typeof jwtPayload.person_row_id === "number" &&
|
||||||
|
typeof jwtPayload.exp === "number" &&
|
||||||
|
typeof jwtPayload.iat === "number"
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const parseJwt = (token: string): JwtPayload | null => {
|
export const parseJwt = (token: string): JwtPayload | null => {
|
||||||
|
@ -24,26 +43,7 @@ export const parseJwt = (token: string): JwtPayload | null => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isJwtPayloadValid = (jwtPayload: JwtPayload): boolean => {
|
export const getJsonWebToken = (): JwtPayload | null => {
|
||||||
return (
|
const rawToken = getRawJsonWebToken();
|
||||||
claims.every((claim) => Object.keys(jwtPayload).includes(claim)) &&
|
return rawToken ? parseJwt(rawToken) : null;
|
||||||
userRoles.includes(jwtPayload.role) &&
|
|
||||||
typeof jwtPayload.person_row_id === "number" &&
|
|
||||||
typeof jwtPayload.exp === "number" &&
|
|
||||||
typeof jwtPayload.iat === "number"
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const claims = ["role", "person_row_id", "exp", "iat", "aud", "iss"];
|
|
||||||
const userRoles = ["candymat_editor", "candymat_candidate", "candymat_person"];
|
|
||||||
|
|
||||||
interface JwtPayload {
|
|
||||||
role: UserRole;
|
|
||||||
person_row_id: number;
|
|
||||||
exp: number;
|
|
||||||
iat: number;
|
|
||||||
aud: "postgraphile";
|
|
||||||
iss: "postgraphile";
|
|
||||||
}
|
|
||||||
|
|
||||||
type UserRole = "candymat_editor" | "candymat_candidate" | "candymat_person";
|
|
||||||
|
|
|
@ -25,40 +25,6 @@ type Config = {
|
||||||
onUpdate?: (registration: ServiceWorkerRegistration) => void;
|
onUpdate?: (registration: ServiceWorkerRegistration) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function register(config?: Config): void {
|
|
||||||
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
|
|
||||||
// The URL constructor is available in all browsers that support SW.
|
|
||||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
|
||||||
if (publicUrl.origin !== window.location.origin) {
|
|
||||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
|
||||||
// from what our page is served on. This might happen if a CDN is used to
|
|
||||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener("load", () => {
|
|
||||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
|
||||||
|
|
||||||
if (isLocalhost) {
|
|
||||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
|
||||||
checkValidServiceWorker(swUrl, config);
|
|
||||||
|
|
||||||
// Add some additional logging to localhost, pointing developers to the
|
|
||||||
// service worker/PWA documentation.
|
|
||||||
navigator.serviceWorker.ready.then(() => {
|
|
||||||
console.log(
|
|
||||||
"This web app is being served cache-first by a service " +
|
|
||||||
"worker. To learn more, visit https://bit.ly/CRA-PWA"
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Is not localhost. Just register service worker
|
|
||||||
registerValidSW(swUrl, config);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerValidSW(swUrl: string, config?: Config) {
|
function registerValidSW(swUrl: string, config?: Config) {
|
||||||
navigator.serviceWorker
|
navigator.serviceWorker
|
||||||
.register(swUrl)
|
.register(swUrl)
|
||||||
|
@ -133,6 +99,40 @@ function checkValidServiceWorker(swUrl: string, config?: Config) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function register(config?: Config): void {
|
||||||
|
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
|
||||||
|
// The URL constructor is available in all browsers that support SW.
|
||||||
|
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||||
|
if (publicUrl.origin !== window.location.origin) {
|
||||||
|
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||||
|
// from what our page is served on. This might happen if a CDN is used to
|
||||||
|
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("load", () => {
|
||||||
|
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||||
|
|
||||||
|
if (isLocalhost) {
|
||||||
|
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||||
|
checkValidServiceWorker(swUrl, config);
|
||||||
|
|
||||||
|
// Add some additional logging to localhost, pointing developers to the
|
||||||
|
// service worker/PWA documentation.
|
||||||
|
navigator.serviceWorker.ready.then(() => {
|
||||||
|
console.log(
|
||||||
|
"This web app is being served cache-first by a service " +
|
||||||
|
"worker. To learn more, visit https://bit.ly/CRA-PWA"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Is not localhost. Just register service worker
|
||||||
|
registerValidSW(swUrl, config);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function unregister(): void {
|
export function unregister(): void {
|
||||||
if ("serviceWorker" in navigator) {
|
if ("serviceWorker" in navigator) {
|
||||||
navigator.serviceWorker.ready
|
navigator.serviceWorker.ready
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"esnext"
|
||||||
|
],
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
|
@ -13,7 +17,10 @@
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"jsx": "react"
|
"jsx": "react",
|
||||||
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
"include": ["src"]
|
"include": [
|
||||||
|
"src"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue