Skip to content

Commit

Permalink
Merge pull request #70 from Motii1/comments-refactor
Browse files Browse the repository at this point in the history
[f] comments refactor and minor improvements
  • Loading branch information
PrzeSta authored Aug 12, 2022
2 parents c7b32dc + 7871c40 commit 8cd056c
Show file tree
Hide file tree
Showing 42 changed files with 174 additions and 132 deletions.
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
import { Location } from 'history';
import { useEffect, useState } from 'react';
import { useDispatch } from 'react-redux';
import { Redirect, Route } from 'react-router-dom';
import { useQuery } from '../../axios/useQuery';
import { setError } from '../../views/ErrorView/errorSlice';
import { LoadingView } from '../../views/LoadingView/LoadingView';
import viewsRoutes from '../../views/viewsRoutes';
import { RouteWrapper } from '../RouteWrapper/RouteWrapper';

type ProtectedRouteWrapperProps = {
path: string;
location?: Location;
} & Record<string, unknown>;

/**
* Wrapper on our custom RouteWrapper used to check if user has access
* to requested route (that is: if user is logged in) and throwing an error
* if user doesn't have access
* to requested route (that is: if user is logged in)
* and throwing an error if user doesn't have access
* @param param0
* @returns
*/
export const ProtectedRouteWrapper: React.FC<ProtectedRouteWrapperProps> = ({
path,
location,
children,
...rest
}) => {
Expand All @@ -43,6 +48,13 @@ export const ProtectedRouteWrapper: React.FC<ProtectedRouteWrapperProps> = ({
else if (!isLoading && !isAccessValid)
dispatch(setError({ isError: true, message: 'Unauthorized access' }));

if (location && path !== location.pathname)
return (
<Route {...rest}>
<Redirect to={viewsRoutes.ERROR} />
</Route>
);

return (
<RouteWrapper path={path} {...rest}>
{children}
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/Routing/RouteWrapper/RouteWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ type RouteWrapperProps = {
* @param param0
* @returns
*/
export const RouteWrapper: React.FC<RouteWrapperProps> = ({ path, children, ...rest }) => {
export const RouteWrapper: React.FC<RouteWrapperProps> = ({
path,

children,
...rest
}) => {
const isError = useSelector((state: RootState) => state.error.isError);

if (isError)
Expand All @@ -21,6 +26,7 @@ export const RouteWrapper: React.FC<RouteWrapperProps> = ({ path, children, ...r
<Redirect to={viewsRoutes.ERROR} />
</Route>
);

return (
<Route path={path} exact {...rest}>
{children}
Expand Down
9 changes: 4 additions & 5 deletions frontend/src/Routing/Routing.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Route, Switch } from 'react-router-dom';
import { Redirect, Route, Switch } from 'react-router-dom';
import { CampaignView } from '../views/CampaignView/CampaignView';
import { CodexView } from '../views/CodexView/CodexView';
import { ErrorView } from '../views/ErrorView/ErrorView';
import { ExplorerView } from '../views/ExplorerView/ExplorerView';
import { LandingView } from '../views/LandingView/LandingView';
import { MapView } from '../views/MapView/MapView';
import { NotesView } from '../views/NotesView/NotesView';
import { StartView } from '../views/StartView/StartView';
import viewsRoutes from '../views/viewsRoutes';
import { ProtectedRouteWrapper } from './ProtectedRouteWrapper/ProtectedRouteWrapper';
Expand Down Expand Up @@ -34,14 +33,14 @@ export const Routing: React.FC = () => (
<ProtectedRouteWrapper path={viewsRoutes.CODEX}>
<CodexView />
</ProtectedRouteWrapper>
<ProtectedRouteWrapper path={viewsRoutes.NOTES}>
<NotesView />
</ProtectedRouteWrapper>
<Route path={viewsRoutes.ERROR}>
<ErrorView />
</Route>
<RouteWrapper path={viewsRoutes.LANDING}>
<LandingView />
</RouteWrapper>
<RouteWrapper path="*">
<Redirect to={viewsRoutes.LANDING} />
</RouteWrapper>
</Switch>
);
2 changes: 1 addition & 1 deletion frontend/src/axios/useQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type useQueryArgs<T> = {

/**
* Custom React hook used to performe queries to server through the application.
* Requires url to query, query method and optional headers for the query.
* Requires url for query, query method and optional headers for the query.
* Provides developers with information about query execution status (loading/loaded),
* response status (http), error (if occurs), data returned in response (if any)
* and methods for running the query and reseting it (so it can be run again)
Expand Down
Binary file removed frontend/src/graphics/giantOwl.jpg
Binary file not shown.
2 changes: 1 addition & 1 deletion frontend/src/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import campaignsReducer from './views/StartView/campaignsSlice';
import startViewReducer from './views/StartView/startViewSlice';

/**
* Reducer for reducer from all slices used in project
* Combined reducer containing reducers from all slices used in project
*/
export const appReducer = combineReducers({
theme: themeReducer,
Expand Down
17 changes: 15 additions & 2 deletions frontend/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from '../views/MapView/eventsSlice';

/**
* Used to convert files into base64
* Used to convert files into base64 encoding
* @param file
* @returns
*/
Expand Down Expand Up @@ -49,7 +49,7 @@ export const convertReferenceFieldToCodexMetadata = (
let index = 0;
const metadata: CodexMetadataInstance[] = [];
// no data is present in field, but it must be provided to validate request on backend
if (fieldMetadata.length === 0)
if (fieldMetadata.length === 0 || (fieldMetadata.length === 1 && fieldMetadata[0].value === '')) {
return [
{
type: 'string',
Expand All @@ -58,6 +58,7 @@ export const convertReferenceFieldToCodexMetadata = (
fieldName: fieldName,
},
];
}
fieldMetadata.forEach(field => {
if (field.value !== '')
if (field.id)
Expand Down Expand Up @@ -348,3 +349,15 @@ export const compareEventsByXThenId = (
if (e1.id < e2.id) return -1;
return 0;
};

/**
* Used to compare codex entries by their id (ASC)
* @param e1
* @param e2
* @returns
*/
export const compareEntriesById = (e1: Entry, e2: Entry): number => {
if (e1.id < e2.id) return -1;
if (e1.id > e2.id) return 1;
return 0;
};
38 changes: 20 additions & 18 deletions frontend/src/views/CampaignView/CampaignView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { fetchSessions, updateCampaignId } from './sessionsSlice';

/**
* Component responsible for UI and logic of CampaignView which displays campaign selected
* by user in StartView, list of sessions in it, allows creation of new session
* by user in StartView (list of sessions in that campaign), allows creation of new sessions
* and editing/deleting existing ones
* @returns
*/
Expand All @@ -39,24 +39,26 @@ export const CampaignView: React.FC = () => {

useEffect(() => setQuote(quotes[Math.floor(Math.random() * quotes.length)]), []);

if (currentCampaignId === '') {
const lastCampaign = campaignsList[campaignsList.length - 1];
if (lastCampaign) {
dispatch(
updateSelectedCampaignData({
campaignId: lastCampaign.id,
campaignName: lastCampaign.name,
campaignImageBase64: lastCampaign.imageBase64,
})
);
dispatch(fetchSchemasAndEntries(lastCampaign.id));
useEffect(() => {
if (currentCampaignId === '') {
const lastCampaign = campaignsList[campaignsList.length - 1];
if (lastCampaign) {
dispatch(
updateSelectedCampaignData({
campaignId: lastCampaign.id,
campaignName: lastCampaign.name,
campaignImageBase64: lastCampaign.imageBase64,
})
);
dispatch(fetchSchemasAndEntries(lastCampaign.id));
}
} else if (!isSessionsListDownloaded || sessionsCampaignId !== currentCampaignId) {
dispatch(fetchSessions(currentCampaignId));
dispatch(fetchSchemasAndEntries(currentCampaignId));
dispatch(resetCurrent({}));
dispatch(updateCampaignId({ campaignId: currentCampaignId }));
}
} else if (!isSessionsListDownloaded || sessionsCampaignId !== currentCampaignId) {
dispatch(fetchSessions(currentCampaignId));
dispatch(fetchSchemasAndEntries(currentCampaignId));
dispatch(resetCurrent({}));
dispatch(updateCampaignId({ campaignId: currentCampaignId }));
}
}, [campaignsList, currentCampaignId, dispatch, isSessionsListDownloaded, sessionsCampaignId]);

const handleFab = () => {
setDialogType(NavBarViewDialog.NewSession);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type CampaignSecondaryDialogProps = {

/**
* Component used as secondary dialog in CampaignView to ask user
* for reconfirmation that they want to delete selected session
* for confirmation that they want to delete selected session
* @param props
* @returns
*/
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/views/CampaignView/sessionsSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ export const fetchSessions = createAsyncThunk(
);

/**
* Redux slice used to store and operate on information about sessions belonging
* to currently selected campaign
* Redux slice used to store and operate on information about sessions
* belonging to currently selected campaign
*/
const sessionsSlice = createSlice({
name: 'sessions',
Expand Down
12 changes: 7 additions & 5 deletions frontend/src/views/CodexView/CodexView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ export const CodexView: React.FC = () => {
else setDialogType(NavBarViewDialog.NewEntry);
}, [currentEntry]);

if (currentCampaignId === '') history.push(viewsRoutes.CAMPAIGN);
else if (!isCodexDownloaded || codexCampaignId !== currentCampaignId) {
dispatch(fetchSchemasAndEntries(currentCampaignId));
dispatch(updateCampaignId({ campaignId: currentCampaignId }));
}
useEffect(() => {
if (currentCampaignId === '') history.push(viewsRoutes.CAMPAIGN);
else if (!isCodexDownloaded || codexCampaignId !== currentCampaignId) {
dispatch(fetchSchemasAndEntries(currentCampaignId));
dispatch(updateCampaignId({ campaignId: currentCampaignId }));
}
}, [codexCampaignId, currentCampaignId, dispatch, history, isCodexDownloaded]);

return (
<ViewWithNavBarWrapper
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/views/CodexView/codexSlice.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import protectedApiClient from '../../axios/axios';
import { compareEntriesById } from '../../utils/utils';

export type Schema = {
id: string;
Expand Down Expand Up @@ -83,6 +84,7 @@ const codexViewSlice = createSlice({
newEntries[action.payload.schemaId] = newEntries[action.payload.schemaId].concat(
action.payload.newEntry
);
newEntries[action.payload.schemaId].sort(compareEntriesById);
state.entries = newEntries;
},
editEntry: (state, action) => {
Expand All @@ -93,13 +95,15 @@ const codexViewSlice = createSlice({
newEntries[action.payload.schemaId] = newEntries[action.payload.schemaId].concat(
action.payload.newEntry
);
newEntries[action.payload.schemaId].sort(compareEntriesById);
state.entries = newEntries;
},
deleteEntry: (state, action) => {
const newEntries = state.entries;
newEntries[action.payload.schemaId] = newEntries[action.payload.schemaId].filter(
element => element.id !== action.payload.entryId
);
newEntries[action.payload.schemaId].sort(compareEntriesById);
state.entries = newEntries;
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type EntriesListElementProps = {
};

/**
* Component reponsible for displaying name of entry,
* Component reponsible for displaying name of entry om entries list,
* allows opening it in EntryDisplayPanel on click
*/
export const EntriesListElement: React.FC<EntriesListElementProps> = props => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type ReferenceChipProps = {
};

/**
* Component responsible for displaying another entry, referenced
* Component responsible for displaying reference to another entry
* in currently displayed entry in distinct way and opening that entry on click
* @param props
* @returns
Expand Down
15 changes: 6 additions & 9 deletions frontend/src/views/CodexView/dialog/CodexDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ import { addEntry, CodexMetadataInstance, editEntry } from '../codexSlice';
import { setCurrentEntry } from '../codexViewSlice';
import { CodexFieldList } from './components/EditFieldList/CodexFieldList';

export type NewEntryData = {
type NewEntryData = {
title: string;
schemaId: string;
imageBase64: string;
metadataArray: CodexMetadataInstance[];
};

export type EditEntryData = {
type EditEntryData = {
title: string;
imageBase64: string;
metadataArray: CodexMetadataInstance[];
Expand All @@ -43,8 +43,7 @@ type CodexDialogProps = {
* Component serving as main dialog in CodexView, used for creation of new entries
* and editing/deleting existing ones. Can be opened in "create new entry" mode
* (all fields are empty) by FAB when schema is selected and no entry is selected
* or in "edit entry" mode (title is filled with data from existing entry)
* by FAB when entry is selected
* or in "edit entry" mode by FAB when entry is selected
* @param props
* @returns
*/
Expand Down Expand Up @@ -89,8 +88,6 @@ export const CodexDialog: React.FC<CodexDialogProps> = props => {
}
}, [currentEntry, currentSchema, entries]);

// useEffect(() => resetDialog(), [resetDialog, props.isOpen]);

const {
isLoading: isLoadingNew,
data: dataNew,
Expand Down Expand Up @@ -185,7 +182,7 @@ export const CodexDialog: React.FC<CodexDialogProps> = props => {

const handleOk = () => {
if (entryTitleHelperText === '' && currentSchema)
if (props.dialogType === NavBarViewDialog.NewEntry)
if (props.dialogType === NavBarViewDialog.NewEntry) {
runQueryNew({
title: entryTitle,
schemaId: currentSchema.id.toString(),
Expand All @@ -194,14 +191,15 @@ export const CodexDialog: React.FC<CodexDialogProps> = props => {
.map(fieldName => convertReferenceFieldToCodexMetadata(fields[fieldName], fieldName))
.flat(),
});
else
} else {
runQueryEdit({
title: entryTitle,
imageBase64: entryImageBase64,
metadataArray: currentSchema.fields
.map(fieldName => convertReferenceFieldToCodexMetadata(fields[fieldName], fieldName))
.flat(),
});
}
};

const handleCancel = () => {
Expand Down Expand Up @@ -283,6 +281,5 @@ export const CodexDialog: React.FC<CodexDialogProps> = props => {
</CustomDialog>
);

// props.setIsOpen(false);
return null;
};
4 changes: 2 additions & 2 deletions frontend/src/views/ErrorView/ErrorView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import { ViewWithSidebarWrapper } from '../components/ViewWithSidebarWrapper/Vie
import { clearError } from './errorSlice';

/**
* Component shown in error boundary
* Component shown as error boundary
* @returns
*/
export const ErrorView: React.FC = () => {
const { isError, message } = store.getState().error;
const dispatch = useDispatch();

useEffect(() => {
dispatch(clearError());
dispatch(clearError({}));
}, [dispatch]);

return (
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/views/ErrorView/errorSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ const errorSlice = createSlice({
state.isError = action.payload.isError;
state.message = action.payload.message;
},
clearError: state => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
clearError: (state, _action) => {
state.isError = false;
state.message = null;
},
Expand Down
Loading

0 comments on commit 8cd056c

Please sign in to comment.