Skip to content

Commit

Permalink
feat: improve routing and redirects (#2210)
Browse files Browse the repository at this point in the history
  • Loading branch information
stepan662 committed Mar 26, 2024
1 parent 118ecf7 commit 74aa4aa
Show file tree
Hide file tree
Showing 126 changed files with 1,327 additions and 2,542 deletions.
11 changes: 3 additions & 8 deletions e2e/cypress/e2e/errorHandling/errorHandlingGet.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,18 @@ describe('Error handling', () => {
});

it('Handles 404 by redirect', () => {
simulateError({
method: 'get',
endpoint: 'facebook',
statusCode: 404,
});
cy.visit(`${HOST}/organizations/facebook/profile`);
cy.visit(`${HOST}/organizations/not-existant/profile`);
assertMessage('Not found');
cy.url().should('include', '/projects');
});

it('Handles 401 by logout', () => {
simulateError({
method: 'get',
endpoint: 'facebook',
endpoint: 'projects-with-stats',
statusCode: 401,
});
cy.visit(`${HOST}/organizations/facebook/profile`);
cy.visit(`${HOST}`);
cy.url().should('include', '/login');
});

Expand Down
2 changes: 1 addition & 1 deletion e2e/cypress/e2e/projects/contentDelivery.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe('Content delivery', () => {
.findDcy('content-delivery-item-publish')
.click();
waitForGlobalLoading();
assertMessage('Content published sucessfuly!');
assertMessage('Content published successfully!');
});

it('creates content delivery', () => {
Expand Down
6 changes: 2 additions & 4 deletions e2e/cypress/e2e/security/signUp.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ context('Sign up', () => {
fillAndSubmitSignUpForm(TEST_USERNAME);
cy.wait(['@signUp']);
setRecaptchaSecretKey('dummy_secret_key');
cy.contains('You are robot').should('be.visible');
cy.contains('You are a robot').should('be.visible');
});

it('Signs up', () => {
Expand Down Expand Up @@ -197,9 +197,7 @@ context('Sign up', () => {
createProjectWithInvitation('Crazy project').then(({ invitationLink }) => {
cy.visit(invitationLink);
assertMessage('Log in or sign up first please');
cy.intercept('/api/public/authorize_oauth/github**http://**').as(
'GithubSignup'
);
cy.intercept('/api/public/authorize_oauth/github**').as('GithubSignup');
loginWithFakeGithub();
cy.wait('@GithubSignup').then((interception) => {
assert.isTrue(interception.request.url.includes('invitationCode'));
Expand Down
2 changes: 2 additions & 0 deletions e2e/cypress/e2e/userSettings/userSettings.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { getAnyContainingText } from '../../common/xPath';
import { HOST } from '../../common/constants';
import { createTestProject, login } from '../../common/apiCalls/common';
import { gcy, getPopover } from '../../common/shared';
import { waitForGlobalLoading } from '../../common/loading';

describe('User settings', () => {
beforeEach(() => {
Expand All @@ -19,6 +20,7 @@ describe('User settings', () => {
it('Opens user menu from projects', () => {
createTestProject().then((r) => {
cy.visit(`${HOST}/projects/${r.body.id}`);
waitForGlobalLoading();
cy.xpath("//*[@aria-controls='user-menu']").click();
getPopover().contains('settings').click();
cy.contains('User profile').should('be.visible');
Expand Down
1 change: 0 additions & 1 deletion e2e/cypress/support/dataCyType.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ declare namespace DataCy {
"content-delivery-storage-selector" |
"content-delivery-storage-selector-item" |
"content-delivery-subtitle" |
"create-project-language-add-button" |
"dashboard-projects-list-item" |
"delete-user-button" |
"developer-menu-content-delivery" |
Expand Down
58 changes: 5 additions & 53 deletions webapp/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 1 addition & 5 deletions webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,14 @@
"react-markdown": "^8.0.4",
"react-qr-code": "^2.0.7",
"react-query": "^3.39.2",
"react-redux": "^7.2.6",
"react-router-dom": "^5.2.0",
"recharts": "2.1.9",
"redux": "^4.1.0",
"redux-promise-middleware": "^6.1.2",
"redux-thunk": "^2.3.0",
"reflect-metadata": "^0.1.13",
"regenerator-runtime": "^0.13.9",
"sockjs-client": "^1.6.1",
"use-context-selector": "^1.3.9",
"use-debounce": "^10.0.0",
"usehooks-ts": "^2.12.1",
"usehooks-ts": "^3.0.2",
"uuid": "9.0.0",
"web-vitals": "^2.1.0",
"yup": "^0.32.9",
Expand Down
Binary file modified webapp/src/.DS_Store
Binary file not shown.
7 changes: 2 additions & 5 deletions webapp/src/RequirePreferredOrganization.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { FC } from 'react';
import { usePreferredOrganization } from 'tg.globalContext/helpers';
import { useSelector } from 'react-redux';
import { AppState } from 'tg.store/index';
import { DashboardPage } from 'tg.component/layout/DashboardPage';
import { CompactView } from 'tg.component/layout/CompactView';
import { T, useTranslate } from '@tolgee/react';
import { useGlobalContext } from 'tg.globalContext/GlobalContext';

export const RequirePreferredOrganization: FC = (props) => {
const allowPrivate = useSelector(
(v: AppState) => v.global.security.allowPrivate
);
const allowPrivate = useGlobalContext((c) => c.auth.allowPrivate);

const { t } = useTranslate();

Expand Down
27 changes: 27 additions & 0 deletions webapp/src/component/AfterLoginRedirect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useMemo } from 'react';
import { Redirect, useHistory } from 'react-router-dom';
import { LINKS } from 'tg.constants/links';
import { securityService } from 'tg.service/SecurityService';

function rememberCurrentLocation() {
const currentUrl = window.location.pathname + window.location.search;
if (currentUrl !== '/' && currentUrl !== '/login') {
securityService.saveAfterLoginLink({
url: currentUrl,
});
}
}

// use to make user sign up first and then continue to current url
export const useAfterLoginRedirect = () => {
const history = useHistory();
return () => {
rememberCurrentLocation();
history.replace(LINKS.LOGIN.build());
};
};

export const AfterLoginRedirect = () => {
useMemo(() => rememberCurrentLocation(), []);
return <Redirect to={LINKS.LOGIN.build()} />;
};
41 changes: 8 additions & 33 deletions webapp/src/component/App.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,34 @@
import React, { FC, useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { Redirect } from 'react-router-dom';
import { Helmet } from 'react-helmet';
import { useTheme } from '@mui/material';
import {
useOrganizationUsage,
usePreferredOrganization,
} from 'tg.globalContext/helpers';
import { GlobalError } from '../error/GlobalError';
import { AppState } from '../store';
import { globalActions } from '../store/global/GlobalActions';
import ConfirmationDialog from './common/ConfirmationDialog';
import SnackBar from './common/SnackBar';
import { PlanLimitPopover } from './billing/PlanLimitPopover';
import { RootRouter } from './RootRouter';
import { MandatoryDataProvider } from './MandatoryDataProvider';
import { SensitiveOperationAuthDialog } from './SensitiveOperationAuthDialog';
import { Ga4Tag } from './Ga4Tag';
import { SpendingLimitExceededPopover } from './billing/SpendingLimitExceeded';
import { redirectionActions } from 'tg.store/global/RedirectionActions';
import { errorActions } from 'tg.store/global/ErrorActions';

const Redirection = () => {
const redirectionState = useSelector((state: AppState) => state.redirection);

useEffect(() => {
if (redirectionState.to) {
redirectionActions.redirectDone.dispatch();
}
});

if (redirectionState.to) {
return <Redirect to={redirectionState.to} />;
}

return null;
};
import { useGlobalContext } from 'tg.globalContext/GlobalContext';
import { globalContext } from 'tg.globalContext/globalActions';

const GlobalConfirmation = () => {
const state = useSelector(
(state: AppState) => state.global.confirmationDialog
);
const state = useGlobalContext((c) => c.confirmationDialog);

const [wasDisplayed, setWasDisplayed] = useState(false);

const onCancel = () => {
state?.onCancel?.();
globalActions.closeConfirmation.dispatch();
globalContext.actions?.closeConfirmation();
};

const onConfirm = () => {
state?.onConfirm?.();
globalActions.closeConfirmation.dispatch();
globalContext.actions?.closeConfirmation();
};

useEffect(() => {
Expand Down Expand Up @@ -116,19 +93,17 @@ const Head: FC = () => {
};
export class App extends React.Component {
componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
errorActions.globalError.dispatch(error as GlobalError);
globalContext.actions?.setGlobalError(error as GlobalError);
throw error;
}
render() {
return (
<>
<Head />
<Redirection />
<Ga4Tag />
<SensitiveOperationAuthDialog />
<MandatoryDataProvider>
<SensitiveOperationAuthDialog />
<Ga4Tag />
<RootRouter />
<SnackBar />
<GlobalConfirmation />
<GlobalLimitPopover />
</MandatoryDataProvider>
Expand Down
2 changes: 1 addition & 1 deletion webapp/src/component/DangerZone/DangerZone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type Props = {
};

export const DangerZone: React.FC<Props> = ({ actions }) => {
const rightPanelWidth = useGlobalContext((c) => c.rightPanelWidth);
const rightPanelWidth = useGlobalContext((c) => c.layout.rightPanelWidth);
const isSmOrLower = useMediaQuery(
`@container (max-width: ${899 + rightPanelWidth}px)`
);
Expand Down
4 changes: 2 additions & 2 deletions webapp/src/component/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { Container, Box, Paper } from '@mui/material';
import GlobalError from './common/GlobalError';
import GlobalErrorPage from './common/GlobalErrorPage';

export default class ErrorBoundary extends React.Component<
{
Expand Down Expand Up @@ -29,7 +29,7 @@ export default class ErrorBoundary extends React.Component<
<Container maxWidth={dev ? 'lg' : 'sm'}>
<Box mt={5}>
<Paper>
<GlobalError error={this.state.error} />
<GlobalErrorPage error={this.state.error} />
</Paper>
</Box>
</Container>
Expand Down
16 changes: 9 additions & 7 deletions webapp/src/component/GlobalErrorModal.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Dialog, DialogContent, IconButton, styled } from '@mui/material';
import { Close } from '@mui/icons-material';
import { useSelector } from 'react-redux';
import { AppState } from 'tg.store/index';

import GlobalError from './common/GlobalError';
import { errorActions } from 'tg.store/global/ErrorActions';
import GlobalErrorPage from './common/GlobalErrorPage';
import {
useGlobalActions,
useGlobalContext,
} from 'tg.globalContext/GlobalContext';

const CloseIcon = styled('div')`
position: absolute;
Expand All @@ -15,10 +16,11 @@ const CloseIcon = styled('div')`
`;

export const GlobalErrorModal = () => {
const error = useSelector((state: AppState) => state.error.error);
const error = useGlobalContext((c) => c.globalError);
const { setGlobalError } = useGlobalActions();

const handleClose = () => {
errorActions.globalError.dispatch(null);
setGlobalError(undefined);
};

return error ? (
Expand All @@ -30,7 +32,7 @@ export const GlobalErrorModal = () => {
</CloseIcon>

<DialogContent>
<GlobalError error={error} />
<GlobalErrorPage error={error} />
</DialogContent>
</Dialog>
) : null;
Expand Down

0 comments on commit 74aa4aa

Please sign in to comment.