Skip to content

Commit

Permalink
feat: 🔥 [EXL-69] support group settings page
Browse files Browse the repository at this point in the history
support group settings page
  • Loading branch information
tal-rofe committed Sep 20, 2022
1 parent 59a6070 commit ce9373e
Show file tree
Hide file tree
Showing 65 changed files with 1,371 additions and 500 deletions.
1 change: 1 addition & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ module.exports = {
message: 'The year is not 2015 anymore',
},
],
'no-warning-comments': ['error'],

'@typescript-eslint/no-unused-vars': ['error'],
'@typescript-eslint/no-empty-interface': 'off',
Expand Down
64 changes: 64 additions & 0 deletions apps/frontend/src/App.router.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React from 'react';
import { Route, Routes, Navigate } from 'react-router-dom';

import Account from '@/containers/AccountSettings/Account';
import SecretManagement from '@/containers/AccountSettings/SecretManagement';
import NewSecret from '@/containers/AccountSettings/NewSecret';
import NewGroup from '@/containers/GroupCenter/NewGroup';
import GroupDetails from '@/containers/GroupCenter/GroupDetails';
import Settings from '@/containers/GroupCenter/GroupDetails/Settings';

interface IProps {
readonly isAuthenticated: boolean | null;
}

const Auth = React.lazy(() => import('./pages/Auth'));
const ExternalAuthRedirect = React.lazy(() => import('./pages/ExternalAuthRedirect'));
const AccountSettings = React.lazy(() => import('./pages/AccountSettings'));
const CliAuth = React.lazy(() => import('./pages/CliAuth'));
const CliAuthenticated = React.lazy(() => import('./pages/CliAuthenticated'));
const NotFound = React.lazy(() => import('./pages/NotFound'));
const GroupCenter = React.lazy(() => import('./pages/GroupCenter'));

const AppRouter: React.FC<IProps> = (props: React.PropsWithChildren<IProps>) => (
<Routes>
{props.isAuthenticated === false && (
<>
<Route path="" element={<Auth />} />
<Route path="auth" element={<Auth />} />
<Route path="external-auth-redirect" element={<ExternalAuthRedirect />} />
</>
)}
{props.isAuthenticated && (
<>
<Route path="" element={<GroupCenter />} />
<Route path="account-settings" element={<AccountSettings />}>
<Route path="" element={<Navigate to="account" replace />} />
<Route path="account" element={<Account />} />
<Route path="secret-management" element={<SecretManagement />} />
<Route path="secret-management/new" element={<NewSecret />} />
<Route path="secret-management/*" element={<Navigate to="secret-management" replace />} />
<Route path="*" element={<Navigate to="account" replace />} />
</Route>
<Route path="group-center" element={<GroupCenter />}>
<Route path="new" element={<NewGroup />} />
<Route path=":groupId" element={<GroupDetails />}>
<Route path="" element={<Navigate to="policies" replace />} />
<Route path="policies" element={<div>&nbsp;</div>} />
<Route path="history" element={<div>&nbsp;</div>} />
<Route path="settings" element={<Settings />} />
</Route>
</Route>
</>
)}
<Route path="cli-auth" element={<CliAuth />} />
<Route path="cli-authenticated" element={<CliAuthenticated />} />
<Route path="/not-found" element={<NotFound />} />
<Route path="*" element={props.isAuthenticated === null ? null : <NotFound />} />
</Routes>
);

AppRouter.displayName = 'AppRouter';
AppRouter.defaultProps = {};

export default React.memo(AppRouter);
35 changes: 3 additions & 32 deletions apps/frontend/src/App.view.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
import React, { Suspense } from 'react';
import { Route, BrowserRouter, Routes, Navigate } from 'react-router-dom';
import { BrowserRouter } from 'react-router-dom';

import EDNotification from '@/ui/EDNotification';
import AppRouter from './App.router';

interface IProps {
readonly isAuthenticated: boolean | null;
}

const Auth = React.lazy(() => import('./pages/Auth'));
const ExternalAuthRedirect = React.lazy(() => import('./pages/ExternalAuthRedirect'));
const AccountSettings = React.lazy(() => import('./pages/AccountSettings'));
const CliAuth = React.lazy(() => import('./pages/CliAuth'));
const CliAuthenticated = React.lazy(() => import('./pages/CliAuthenticated'));
const NotFound = React.lazy(() => import('./pages/NotFound'));
const GroupCenter = React.lazy(() => import('./pages/GroupCenter'));

const AppView: React.FC<IProps> = (props: React.PropsWithChildren<IProps>) => (
<BrowserRouter>
<Suspense fallback={null}>
Expand All @@ -23,29 +16,7 @@ const AppView: React.FC<IProps> = (props: React.PropsWithChildren<IProps>) => (

<EDNotification />

<Routes>
{props.isAuthenticated === false && (
<>
<Route path="/" element={<Auth />} />
<Route path="/auth" element={<Auth />} />
<Route path="/external-auth-redirect" element={<ExternalAuthRedirect />} />
</>
)}
{props.isAuthenticated && (
<>
<Route path="/" element={<GroupCenter />} />
<Route path="/account-settings/*" element={<AccountSettings />} />
<Route path="/group-center/*" element={<GroupCenter />} />
</>
)}
<Route path="/cli-auth" element={<CliAuth />} />
<Route path="/cli-authenticated" element={<CliAuthenticated />} />
<Route path="/not-found" element={<NotFound />} />
<Route
path="*"
element={props.isAuthenticated === null ? null : <Navigate replace to="/not-found" />}
/>
</Routes>
<AppRouter isAuthenticated={props.isAuthenticated} />
</Suspense>
</BrowserRouter>
);
Expand Down
12 changes: 12 additions & 0 deletions apps/frontend/src/assets/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,18 @@ const icons = {
<path d="M9.069 20h1.872c.373 0 .693-.105.961-.314.268-.21.444-.494.53-.854l.391-1.688.275-.098 1.46.913c.315.196.638.271.971.226.34-.04.644-.194.912-.462l1.294-1.295c.275-.268.432-.573.47-.913.04-.34-.038-.664-.234-.971l-.912-1.463.098-.255 1.686-.382a1.52 1.52 0 0 0 .843-.54c.21-.268.314-.589.314-.962V9.117c0-.373-.105-.694-.314-.962a1.412 1.412 0 0 0-.843-.54l-1.666-.402-.108-.265.911-1.462a1.42 1.42 0 0 0 .226-.972 1.515 1.515 0 0 0-.46-.912L16.45 2.296a1.492 1.492 0 0 0-.902-.451 1.486 1.486 0 0 0-.98.216l-1.461.893-.285-.098-.392-1.688a1.473 1.473 0 0 0-.529-.844 1.484 1.484 0 0 0-.96-.324H9.068c-.373 0-.693.108-.961.324-.268.21-.445.49-.53.844l-.392 1.688-.284.098-1.47-.893a1.47 1.47 0 0 0-.981-.216c-.34.04-.637.19-.892.451L2.255 3.602a1.59 1.59 0 0 0-.46.912 1.42 1.42 0 0 0 .225.972l.911 1.462-.098.265-1.657.402a1.5 1.5 0 0 0-.862.54c-.21.268-.314.589-.314.962v1.825c0 .373.108.694.324.962.215.268.5.448.852.54l1.667.382.098.255-.912 1.463a1.41 1.41 0 0 0-.225.971c.046.34.2.645.46.913l1.295 1.295c.268.268.572.422.912.462.34.045.666-.03.98-.226l1.46-.913.275.098.392 1.688c.085.36.262.645.53.854.268.21.588.314.96.314zm.186-1.57c-.144 0-.229-.069-.255-.206l-.559-2.297a5.062 5.062 0 0 1-.843-.265 5.898 5.898 0 0 1-.706-.373l-2.01 1.237c-.117.079-.235.065-.353-.04L3.5 15.437c-.105-.084-.118-.192-.04-.323L4.707 13.1a8.888 8.888 0 0 1-.353-.707 4.856 4.856 0 0 1-.265-.824l-2.304-.55c-.137-.026-.206-.114-.206-.264V9.284c0-.15.07-.24.206-.265l2.294-.55c.072-.307.167-.595.285-.863.117-.269.225-.498.323-.687L3.451 4.917c-.078-.131-.069-.249.03-.354l1.039-1.02c.11-.105.232-.121.362-.05l1.99 1.227a4.7 4.7 0 0 1 .726-.353 5.93 5.93 0 0 1 .853-.285L9 1.776c.026-.13.111-.196.255-.196h1.5c.144 0 .229.065.255.196l.559 2.306c.294.079.571.177.833.295.261.111.503.229.726.353l2-1.227c.124-.072.241-.058.352.04l1.04 1.03c.104.098.114.213.029.344l-1.235 2.002c.104.19.215.418.333.687.124.268.219.556.284.863l2.295.55c.137.026.205.114.205.265v1.472c0 .15-.068.238-.206.265l-2.303.55a4.366 4.366 0 0 1-.275.824 7.16 7.16 0 0 1-.343.706l1.235 2.012c.079.124.066.232-.039.324l-1.03 1.04c-.117.111-.231.128-.343.049l-2.01-1.236a5.62 5.62 0 0 1-1.548.637l-.56 2.297c-.025.137-.11.206-.254.206h-1.5zm.755-4.897a3.39 3.39 0 0 0 1.764-.471c.53-.32.955-.746 1.275-1.276a3.42 3.42 0 0 0 .48-1.786c0-.648-.16-1.237-.48-1.766a3.635 3.635 0 0 0-1.274-1.266 3.34 3.34 0 0 0-1.765-.481c-.647 0-1.239.16-1.775.48a3.61 3.61 0 0 0-1.284 1.267A3.35 3.35 0 0 0 6.471 10c0 .648.16 1.24.48 1.776.32.53.745.955 1.274 1.276.536.32 1.131.48 1.785.48zm0-1.511c-.366 0-.703-.092-1.01-.275a2.113 2.113 0 0 1-.725-.736A1.94 1.94 0 0 1 8 10c0-.36.091-.69.275-.991.183-.308.424-.553.725-.736a1.935 1.935 0 0 1 1.01-.275c.353 0 .68.092.98.275.307.183.55.428.726.736.183.3.274.631.274.991 0 .366-.091.703-.274 1.01a2.116 2.116 0 0 1-.726.737 1.85 1.85 0 0 1-.98.275z"/>
`,
],
policies: [
'16 20',
`
<path d="M2.975 20h12.21a.77.77 0 0 0 .576-.236.75.75 0 0 0 .239-.57.775.775 0 0 0-.17-.49 1.026 1.026 0 0 0-.407-.304 1.57 1.57 0 0 1-.846-.786c-.166-.353-.206-.743-.12-1.168.094-.432.336-.835.727-1.208.206-.196.392-.425.557-.687.173-.262.259-.625.259-1.09V2.985c0-.989-.252-1.732-.756-2.229C14.746.252 14 0 13.005 0H2.995C2.007 0 1.26.252.756.756.252 1.253 0 1.996 0 2.985v14.08c0 .968.249 1.698.746 2.189.504.497 1.247.746 2.23.746Zm-1.274-5.695V3.063c0-.451.117-.795.349-1.03.232-.243.584-.364 1.054-.364h9.782c.47 0 .825.121 1.064.363.24.236.359.58.359 1.031v10.152c0 .491-.26.737-.777.737H3.174c-.298 0-.57.033-.816.098a2.627 2.627 0 0 0-.657.255Zm1.433 4.085c-.49 0-.862-.128-1.114-.383-.246-.249-.368-.596-.368-1.04 0-.413.136-.747.408-1.002.278-.256.66-.383 1.144-.383h9.532c.113 0 .22-.01.319-.03a3.009 3.009 0 0 0-.299 1.463c.027.504.163.962.408 1.375H3.134Zm-.338-3.604H4.09V1.247H2.796v13.54Z" />
`,
],
history: [
'22 20',
`
<path d="M11.6 4.313a.802.802 0 0 0-.59.237.783.783 0 0 0-.237.576V10.5a1 1 0 0 0 .051.32c.042.102.104.209.186.318l2.378 3.12c.172.219.369.35.59.39a.86.86 0 0 0 .64-.164.665.665 0 0 0 .3-.525.935.935 0 0 0-.186-.638l-3.225-4.313.899 2.748V5.126a.782.782 0 0 0-.238-.576.777.777 0 0 0-.568-.237ZM11.96 20a9.601 9.601 0 0 0 3.877-.793 10.219 10.219 0 0 0 3.205-2.161c.924-.92 1.648-1.98 2.171-3.18A9.622 9.622 0 0 0 22 9.994a9.596 9.596 0 0 0-.786-3.86A10.219 10.219 0 0 0 15.838.782 9.71 9.71 0 0 0 11.961 0a9.71 9.71 0 0 0-3.876.782A10.231 10.231 0 0 0 4.88 2.934a10.049 10.049 0 0 0-2.171 3.18 9.523 9.523 0 0 0-.786 3.85h1.83c0-1.125.213-2.182.64-3.17A8.15 8.15 0 0 1 6.163 4.2a8.135 8.135 0 0 1 5.8-2.367c1.137 0 2.202.212 3.194.637a8.168 8.168 0 0 1 2.616 1.75 8.01 8.01 0 0 1 1.757 2.594c.427.988.641 2.049.641 3.18a7.925 7.925 0 0 1-.64 3.181 8.248 8.248 0 0 1-1.758 2.615 8.168 8.168 0 0 1-2.616 1.75 7.9 7.9 0 0 1-3.195.628 7.995 7.995 0 0 1-2.574-.412 8.178 8.178 0 0 1-2.223-1.132 8.267 8.267 0 0 1-1.757-1.74 1.085 1.085 0 0 0-.62-.412.87.87 0 0 0-.693.134.831.831 0 0 0-.372.608c-.035.253.045.5.238.74a10.269 10.269 0 0 0 2.16 2.1c.841.611 1.754 1.088 2.74 1.431.986.343 2.02.515 3.101.515ZM.734 8.06c-.248 0-.434.051-.558.154A.51.51 0 0 0 0 8.616c.007.164.08.34.217.524l2.275 3.191c.165.227.354.34.568.34.22 0 .41-.113.569-.34l2.285-3.2c.13-.172.196-.34.196-.505a.48.48 0 0 0-.176-.412c-.117-.103-.3-.154-.548-.154H.734Z" />
`,
],
};

export default icons;
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,9 @@
}

&__button {
padding: map.get($sizes, spacing-m) map.get($sizes, spacing-l);
font-size: 1.5rem;
font-weight: normal;
color: map.get($colors, greys-onyx);
background-color: map.get($colors, whites-ghost-white);
border: 2px solid map.get($colors, greys-platinum);
border-radius: 6px;

&--delete {
font-weight: 500;
color: map.get($colors, reds-persian-plum);
}
box-shadow: inset 0 0 0 2px map.get($colors, greys-platinum);
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, { useState } from 'react';
import React from 'react';
import { connect } from 'react-redux';
import type { PayloadAction } from '@reduxjs/toolkit';
import { useNavigate } from 'react-router-dom';

import { authActions } from '@/store/reducers/auth';
import { backendApi } from '@/utils/http';

import AccountView from './Account.view';

Expand All @@ -16,25 +17,21 @@ interface IProps extends IPropsFromDispatch {}
const Account: React.FC<IProps> = (props: React.PropsWithChildren<IProps>) => {
const navigate = useNavigate();

const [isDeleteAccountModalOnViewState, setIsDeleteAccountModalOnViewState] = useState<boolean>(false);

const onSignOutClick = () => {
props.setUnauthenticated();

navigate('/auth');
};

const onOpenDeleteAccountModal = () => setIsDeleteAccountModalOnViewState(() => true);
const onCloseDeleteAccountModal = () => setIsDeleteAccountModalOnViewState(() => false);

return (
<AccountView
isDeleteAccountModalOnView={isDeleteAccountModalOnViewState}
onSignOutClick={onSignOutClick}
onOpenDeleteAccountModal={onOpenDeleteAccountModal}
onCloseDeleteAccountModal={onCloseDeleteAccountModal}
/>
);
const onModalConfirmClick = () => {
backendApi.delete('/user/auth').then(() => {
props.setUnauthenticated();

navigate('/auth');
});
};

return <AccountView onSignOutClick={onSignOutClick} onModalConfirmClick={onModalConfirmClick} />;
};

Account.displayName = 'Account';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@ import React from 'react';
import { useTranslation } from 'react-i18next';

import { concatClasses } from '@/utils/component';

import DeleteAccountModal from './DeleteAccountModal';
import EDDeleteButton from '@/ui/EDDeleteButton';
import EDAcceptButton from '@/ui/EDAcceptButton';

import classes from './Account.module.scss';

interface IProps {
readonly isDeleteAccountModalOnView: boolean;
readonly onSignOutClick: VoidFunction;
readonly onOpenDeleteAccountModal: VoidFunction;
readonly onCloseDeleteAccountModal: VoidFunction;
readonly onModalConfirmClick: VoidFunction;
}

const AccountView: React.FC<IProps> = (props: React.PropsWithChildren<IProps>) => {
Expand All @@ -27,13 +25,14 @@ const AccountView: React.FC<IProps> = (props: React.PropsWithChildren<IProps>) =
<span className={classes['actionSection__subHeader']}>
{t('accountSettings.account.signOutSubHeader')}
</span>
<button
<EDAcceptButton
className={classes['actionSection__button']}
disabled={false}
type="button"
onClick={props.onSignOutClick}
>
{t('accountSettings.account.signOutButton')}
</button>
</EDAcceptButton>
</section>

<section className={classes['actionSection']}>
Expand All @@ -50,20 +49,14 @@ const AccountView: React.FC<IProps> = (props: React.PropsWithChildren<IProps>) =
<span className={classes['actionSection__subHeader']}>
{t('accountSettings.account.deleteAccountSubHeader')}
</span>
<button
className={concatClasses(
classes,
'actionSection__button',
'actionSection__button--delete',
)}
type="button"
onClick={props.onOpenDeleteAccountModal}
<EDDeleteButton
modalTitle={t('accountSettings.account.deleteModal.header')}
modalSubTitle={t('accountSettings.account.deleteModal.subHeader')}
modalConfirmationKeyword={t('accountSettings.account.deleteModal.actionPhraseText')}
onModalConfirmClick={props.onModalConfirmClick}
>
{t('accountSettings.account.deleteAccountButton')}
</button>
{props.isDeleteAccountModalOnView && (
<DeleteAccountModal onClose={props.onCloseDeleteAccountModal} />
)}
</EDDeleteButton>
</section>
</main>
);
Expand Down

This file was deleted.

Loading

0 comments on commit ce9373e

Please sign in to comment.