0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-17 22:31:28 -05:00

feat(console): active tab by route (#309)

* feat(console): active tab by route

* refactor(console): export sidebar utils and consts in index
This commit is contained in:
Gao Sun 2022-03-03 15:02:30 +08:00 committed by GitHub
parent 14d6c9e18a
commit cc8bb825fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 85 additions and 23 deletions

View file

@ -21,9 +21,11 @@
"classnames": "^2.3.1",
"i18next": "^21.6.12",
"i18next-browser-languagedetector": "^6.1.3",
"lodash.kebabcase": "^4.1.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-i18next": "^11.15.4"
"react-i18next": "^11.15.4",
"react-router-dom": "^6.2.2"
},
"devDependencies": {
"@parcel/core": "^2.3.1",
@ -32,6 +34,7 @@
"@silverhand/eslint-config-react": "^0.9.3",
"@silverhand/ts-config": "^0.9.1",
"@silverhand/ts-config-react": "^0.9.3",
"@types/lodash.kebabcase": "^4.1.6",
"@types/react": "^17.0.14",
"@types/react-dom": "^17.0.9",
"eslint": "^8.10.0",

View file

@ -1,15 +1,25 @@
import React from 'react';
import React, { useEffect } from 'react';
import { BrowserRouter, useLocation, useNavigate } from 'react-router-dom';
import './scss/normalized.scss';
import * as styles from './App.module.scss';
import Content from './components/Content';
import Sidebar from './components/Sidebar';
import Sidebar, { getPath, sections } from './components/Sidebar';
import Topbar from './components/Topbar';
import initI18n from './i18n/init';
void initI18n();
export const App = () => {
const Main = () => {
const location = useLocation();
const navigate = useNavigate();
useEffect(() => {
if (location.pathname === '/') {
navigate(getPath(sections[0]?.items[0]?.title ?? ''));
}
}, [location.pathname, navigate]);
return (
<div className={styles.app}>
<Topbar />
@ -20,3 +30,11 @@ export const App = () => {
</div>
);
};
const App = () => (
<BrowserRouter>
<Main />
</BrowserRouter>
);
export default App;

View file

@ -7,6 +7,8 @@
padding: _.unit(3) _.unit(4);
color: var(--color-on-surface-variant);
border-radius: _.unit(2);
text-decoration: none;
user-select: none;
.icon {
width: _.unit(6);

View file

@ -1,6 +1,7 @@
import classNames from 'classnames';
import React, { ReactChild } from 'react';
import { getPath } from '../../utils';
import * as styles from './index.module.scss';
type Props = {
@ -11,10 +12,10 @@ type Props = {
const Item = ({ icon, title, isActive = false }: Props) => {
return (
<div className={classNames(styles.row, isActive && styles.active)}>
<a href={getPath(title)} className={classNames(styles.row, isActive && styles.active)}>
{icon && <div className={styles.icon}>{icon}</div>}
<div className={styles.title}>{title}</div>
</div>
</a>
);
};

View file

@ -1,11 +1,13 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useLocation } from 'react-router-dom';
import Item from './components/Item';
import Section from './components/Section';
import { sections } from './consts';
import Gear from './icons/Gear';
import * as styles from './index.module.scss';
import { getPath } from './utils';
const Sidebar = () => {
const { t: tSection } = useTranslation(undefined, {
@ -14,6 +16,7 @@ const Sidebar = () => {
const { t: tItem } = useTranslation(undefined, {
keyPrefix: 'admin_console.tabs',
});
const location = useLocation();
return (
<div className={styles.sidebar}>
@ -24,7 +27,7 @@ const Sidebar = () => {
key={title}
title={tItem(title)}
icon={<Icon />}
isActive={title === 'api_resources'}
isActive={location.pathname === getPath(title)}
/>
))}
</Section>
@ -36,3 +39,6 @@ const Sidebar = () => {
};
export default Sidebar;
export * from './consts';
export * from './utils';

View file

@ -0,0 +1,3 @@
import kebabCase from 'lodash.kebabcase';
export const getPath = (title: string): string => `/${kebabCase(title)}`;

View file

@ -1,7 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { App } from './App';
import App from './App';
const app = document.querySelector('#app');
ReactDOM.render(<App />, app);

59
pnpm-lock.yaml generated
View file

@ -28,6 +28,7 @@ importers:
'@silverhand/eslint-config-react': ^0.9.3
'@silverhand/ts-config': ^0.9.1
'@silverhand/ts-config-react': ^0.9.3
'@types/lodash.kebabcase': ^4.1.6
'@types/react': ^17.0.14
'@types/react-dom': ^17.0.9
classnames: ^2.3.1
@ -35,6 +36,7 @@ importers:
i18next: ^21.6.12
i18next-browser-languagedetector: ^6.1.3
lint-staged: ^11.1.1
lodash.kebabcase: ^4.1.1
parcel: ^2.3.1
postcss: ^8.4.6
postcss-modules: ^4.3.0
@ -42,6 +44,7 @@ importers:
react: ^17.0.2
react-dom: ^17.0.2
react-i18next: ^11.15.4
react-router-dom: ^6.2.2
stylelint: ^13.13.1
typescript: ^4.5.5
dependencies:
@ -50,9 +53,11 @@ importers:
classnames: 2.3.1
i18next: 21.6.12
i18next-browser-languagedetector: 6.1.3
lodash.kebabcase: 4.1.1
react: 17.0.2
react-dom: 17.0.2_react@17.0.2
react-i18next: 11.15.4_2c37a602a29bb6bd53f3de707a8cfcc5
react-router-dom: 6.2.2_react-dom@17.0.2+react@17.0.2
devDependencies:
'@parcel/core': 2.3.1
'@parcel/transformer-sass': 2.3.1_@parcel+core@2.3.1
@ -60,6 +65,7 @@ importers:
'@silverhand/eslint-config-react': 0.9.3_40768c17363f6507b3c2d36cc72e1a6b
'@silverhand/ts-config': 0.9.1_typescript@4.5.5
'@silverhand/ts-config-react': 0.9.3_typescript@4.5.5
'@types/lodash.kebabcase': 4.1.6
'@types/react': 17.0.37
'@types/react-dom': 17.0.11
eslint: 8.10.0
@ -3462,6 +3468,12 @@ packages:
'@types/node': 16.11.12
dev: true
/@types/lodash.kebabcase/4.1.6:
resolution: {integrity: sha512-+RAD9pCAa8kuVyCYTeDNiwBXwD/0u0p+hos3NSqD+tXTjJextbfF3farfYB+ssAKgEssoewXEtBsfwBpsI7gsA==}
dependencies:
'@types/lodash': 4.14.178
dev: true
/@types/lodash.pick/4.4.6:
resolution: {integrity: sha512-u8bzA16qQ+8dY280z3aK7PoWb3fzX5ATJ0rJB6F+uqchOX2VYF02Aqa+8aYiHiHgPzQiITqCgeimlyKFy4OA6g==}
dependencies:
@ -6655,6 +6667,12 @@ packages:
value-equal: 1.0.1
dev: false
/history/5.3.0:
resolution: {integrity: sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==}
dependencies:
'@babel/runtime': 7.16.3
dev: false
/hoist-non-react-statics/3.3.2:
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
dependencies:
@ -8922,7 +8940,6 @@ packages:
/lodash.kebabcase/4.1.1:
resolution: {integrity: sha1-hImxyw0p/4gZXM7KRI/21swpXDY=}
dev: true
/lodash.memoize/4.1.2:
resolution: {integrity: sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=}
@ -9272,14 +9289,14 @@ packages:
engines: {node: '>=4'}
dev: true
/mini-create-react-context/0.4.1_prop-types@15.7.2+react@17.0.2:
/mini-create-react-context/0.4.1_prop-types@15.8.1+react@17.0.2:
resolution: {integrity: sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==}
peerDependencies:
prop-types: ^15.0.0
react: ^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@babel/runtime': 7.16.3
prop-types: 15.7.2
prop-types: 15.8.1
react: 17.0.2
tiny-warning: 1.0.3
dev: false
@ -11037,21 +11054,12 @@ packages:
read: 1.0.7
dev: true
/prop-types/15.7.2:
resolution: {integrity: sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==}
dependencies:
loose-envify: 1.4.0
object-assign: 4.1.1
react-is: 16.13.1
dev: false
/prop-types/15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
dependencies:
loose-envify: 1.4.0
object-assign: 4.1.1
react-is: 16.13.1
dev: true
/propagate/2.0.1:
resolution: {integrity: sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==}
@ -11244,13 +11252,25 @@ packages:
'@babel/runtime': 7.16.3
history: 4.10.1
loose-envify: 1.4.0
prop-types: 15.7.2
prop-types: 15.8.1
react: 17.0.2
react-router: 5.2.1_react@17.0.2
tiny-invariant: 1.2.0
tiny-warning: 1.0.3
dev: false
/react-router-dom/6.2.2_react-dom@17.0.2+react@17.0.2:
resolution: {integrity: sha512-AtYEsAST7bDD4dLSQHDnk/qxWLJdad5t1HFa1qJyUrCeGgEuCSw0VB/27ARbF9Fi/W5598ujvJOm3ujUCVzuYQ==}
peerDependencies:
react: '>=16.8'
react-dom: '>=16.8'
dependencies:
history: 5.3.0
react: 17.0.2
react-dom: 17.0.2_react@17.0.2
react-router: 6.2.2_react@17.0.2
dev: false
/react-router/5.2.1_react@17.0.2:
resolution: {integrity: sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==}
peerDependencies:
@ -11260,15 +11280,24 @@ packages:
history: 4.10.1
hoist-non-react-statics: 3.3.2
loose-envify: 1.4.0
mini-create-react-context: 0.4.1_prop-types@15.7.2+react@17.0.2
mini-create-react-context: 0.4.1_prop-types@15.8.1+react@17.0.2
path-to-regexp: 1.8.0
prop-types: 15.7.2
prop-types: 15.8.1
react: 17.0.2
react-is: 16.13.1
tiny-invariant: 1.2.0
tiny-warning: 1.0.3
dev: false
/react-router/6.2.2_react@17.0.2:
resolution: {integrity: sha512-/MbxyLzd7Q7amp4gDOGaYvXwhEojkJD5BtExkuKmj39VEE0m3l/zipf6h2WIB2jyAO0lI6NGETh4RDcktRm4AQ==}
peerDependencies:
react: '>=16.8'
dependencies:
history: 5.3.0
react: 17.0.2
dev: false
/react/17.0.2:
resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==}
engines: {node: '>=0.10.0'}