From 17d36c95f3aaf70f5b014b7b9c99574603fedc92 Mon Sep 17 00:00:00 2001 From: Dominik Horn Date: Wed, 26 Feb 2020 17:35:08 +0100 Subject: [PATCH 1/5] implement basic @Routed annotation idea #13 --- packages/frontend/src/components/App.tsx | 11 ++- .../src/components/pages/HomePage.tsx | 26 ++++--- .../src/components/pages/LinkPage.tsx | 28 +++++--- .../pages/support/LinkDirectory.tsx | 2 +- packages/frontend/src/util/approutes.tsx | 70 ------------------- packages/frontend/src/util/routing.tsx | 62 ++++++++++++++++ packages/frontend/tsconfig.json | 3 +- 7 files changed, 106 insertions(+), 96 deletions(-) delete mode 100644 packages/frontend/src/util/approutes.tsx create mode 100644 packages/frontend/src/util/routing.tsx diff --git a/packages/frontend/src/components/App.tsx b/packages/frontend/src/components/App.tsx index 67f2538..dd2be52 100644 --- a/packages/frontend/src/components/App.tsx +++ b/packages/frontend/src/components/App.tsx @@ -1,12 +1,16 @@ import * as React from 'react'; import { hot } from 'react-hot-loader'; -import { Route, Switch } from 'react-router'; +import { Route, Switch, Redirect } from 'react-router'; import { Router } from 'react-router-dom'; -import { APP_ROUTES, ERROR_404_PAGE } from '../util/approutes'; import history from '../util/history'; import { FeatureFlagsProvider } from 'elite-feature-flags'; import { Configuration } from 'elite-types'; import { getConfiguration } from 'elite-configuration'; +import { APP_ROUTES } from '../util/routing'; + +// Files must be required for decorator to work +require('../components/pages/HomePage'); +require('../components/pages/LinkPage'); const configuration: Configuration = getConfiguration(); @@ -17,7 +21,8 @@ export const AppComponent = () => ( {APP_ROUTES.map((routeProps, index) => ( ))} - + {/* Error 404 Fallback */} + diff --git a/packages/frontend/src/components/pages/HomePage.tsx b/packages/frontend/src/components/pages/HomePage.tsx index f3e3656..ec66118 100644 --- a/packages/frontend/src/components/pages/HomePage.tsx +++ b/packages/frontend/src/components/pages/HomePage.tsx @@ -3,16 +3,22 @@ import { RouteComponentProps } from 'react-router'; import { LinkDirectory } from './support/LinkDirectory'; import { Divider } from '@material-ui/core'; import { FeatureFlag } from 'elite-feature-flags'; +import { Routed } from '../../util/routing'; export interface HomePageProps extends RouteComponentProps {} -export const HomePage = (props: HomePageProps) => ( - <> -

Main Page

- - Elite Sexyz is currently under construction. See discord main channel for more information - - - - -); +@Routed({ path: '/home', displayName: 'Home' }) +export class HomePage extends React.PureComponent { + render() { + return ( + <> +

Main Page

+ + Elite Sexyz is currently under construction. See discord main channel for more information + + + + + ); + } +} diff --git a/packages/frontend/src/components/pages/LinkPage.tsx b/packages/frontend/src/components/pages/LinkPage.tsx index ef63230..717ba59 100644 --- a/packages/frontend/src/components/pages/LinkPage.tsx +++ b/packages/frontend/src/components/pages/LinkPage.tsx @@ -1,21 +1,27 @@ import { Divider, List } from '@material-ui/core'; import * as React from 'react'; import { RouteComponentProps } from 'react-router'; +import { Routed } from '../../util/routing'; import { LinkListItem } from '../general/LinkListItem'; import { LinkDirectory } from './support/LinkDirectory'; export interface LinkPageProps extends RouteComponentProps {} -export const LinkPage = (props: LinkPageProps) => ( - <> -

Useful Links List

- - - - +@Routed({ path: '/link', displayName: 'Useful Links' }) +export class LinkPage extends React.PureComponent { + render() { + return ( + <> +

Useful Links List

+ + + + - + - - -); + + + ); + } +} diff --git a/packages/frontend/src/components/pages/support/LinkDirectory.tsx b/packages/frontend/src/components/pages/support/LinkDirectory.tsx index b896837..8180d69 100644 --- a/packages/frontend/src/components/pages/support/LinkDirectory.tsx +++ b/packages/frontend/src/components/pages/support/LinkDirectory.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { Link } from 'react-router-dom'; -import { APP_ROUTES, getLinkDisplayNameForPage, getLinkForPage } from '../../../util/approutes'; +import { APP_ROUTES, getLinkForPage, getLinkDisplayNameForPage } from '../../../util/routing'; export const LinkDirectory = () => (
    diff --git a/packages/frontend/src/util/approutes.tsx b/packages/frontend/src/util/approutes.tsx deleted file mode 100644 index e68b8cd..0000000 --- a/packages/frontend/src/util/approutes.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import * as H from 'history'; -import * as React from 'react'; -import { RouteProps, Redirect } from 'react-router'; -import { HomePage } from '../components/pages/HomePage'; -import { LinkPage } from '../components/pages/LinkPage'; - -// If necessary, add support for: H.LocationDescriptor | ((location: H.Location) => H.LocationDescriptor); -type LinkType = string; - -export interface AppRouteProps extends RouteProps { - // Use this if the link target differs from the path specification, - // i.e., if the path url contains paramter specifications etc - readonly link?: LinkType; - - // link text (Human readable!) - readonly linkDisplayName?: string; - - // AppRoutes must have a path - deoptionalize this property - readonly path: string; -} - -/** - * Retrieves the url which other pages can use - * to link to a certain route - * @param route the route to link to - */ -export function getLinkForPage(route: AppRouteProps): LinkType { - return route.link || route.path; -} - -/** - * Retrieves the humand readable link title/displayed name - * for a given route - * - * @param route - */ -export function getLinkDisplayNameForPage(route: AppRouteProps): string { - return route.linkDisplayName || getLinkForPage(route); -} - -/** - * Specify all pages in this file by defining - * a pages route props and adding it to the - * available APP_ROUTES array - */ - -// Landing/Home page -export const HOME_PAGE: AppRouteProps = { - path: '/home', - linkDisplayName: 'Home', - render: props => -}; - -// Page with searchable, useful links for elite-se-degree program -export const LINK_PAGE: AppRouteProps = { - path: '/links', - linkDisplayName: 'Useful Links', - render: props => -}; - -// Simply redirect to the main page on 404 -export const ERROR_404_PAGE: AppRouteProps = { - path: '/', - render: () => , -}; - -export const APP_ROUTES: AppRouteProps[] = [ - HOME_PAGE, - LINK_PAGE -]; \ No newline at end of file diff --git a/packages/frontend/src/util/routing.tsx b/packages/frontend/src/util/routing.tsx new file mode 100644 index 0000000..b659120 --- /dev/null +++ b/packages/frontend/src/util/routing.tsx @@ -0,0 +1,62 @@ +import * as React from 'react'; +import { RouteProps } from 'react-router'; + +// TODO: move to separate package + +/** + * The Routed decorator automatically creates a route for + * the annotated top level page component + * + * @param props route properties + */ +export function Routed(props: AppRouteProps) { + console.log('producing route decorator:', props); + return (constructor: any) => { + APP_ROUTES.push({ + render: p => React.createElement(constructor, p), + ...props, + }); + console.log('added route for', constructor.name); + return constructor; + }; +} + +// If necessary, add support for: H.LocationDescriptor | ((location: H.Location) => H.LocationDescriptor); +type LinkType = string; + +// TODO: Add documentation +export interface AppRouteProps extends RouteProps { + // Use this if the link target differs from the path specification, + // i.e., if the path url contains paramter specifications etc + readonly link?: LinkType; + + // link text (Human readable!) + readonly displayName?: string; + + // AppRoutes must have a path - deoptionalize this property + readonly path: string; +} + +// TODO: replace with proper container/service class +/** + * Retrieves the url which other pages can use + * to link to a certain route + * @param route the route to link to + */ +export function getLinkForPage(route: AppRouteProps): LinkType { + return route.link || route.path; +} + +// TODO: replace with proper container/service class +/** + * Retrieves the humand readable link title/displayed name + * for a given route + * + * @param route + */ +export function getLinkDisplayNameForPage(route: AppRouteProps): string { + return route.displayName || getLinkForPage(route); +} + +// TODO: replace with proper container/service class +export const APP_ROUTES: AppRouteProps[] = []; diff --git a/packages/frontend/tsconfig.json b/packages/frontend/tsconfig.json index c4af582..1d4b811 100644 --- a/packages/frontend/tsconfig.json +++ b/packages/frontend/tsconfig.json @@ -3,7 +3,8 @@ "compilerOptions": { "rootDir": "src", "outDir": "dist", - "baseUrl": "src" + "baseUrl": "src", + "experimentalDecorators": true }, "include": ["src/**/*"], "references": [ From b242ef19c7e36e73d060c5fa5ab5ca61f7ab43b2 Mon Sep 17 00:00:00 2001 From: Dominik Horn Date: Thu, 27 Feb 2020 09:51:35 +0100 Subject: [PATCH 2/5] upgrade routing: use hashmap instead of array for storing routes #13 --- packages/frontend/src/components/App.tsx | 6 +- .../pages/support/LinkDirectory.tsx | 6 +- packages/frontend/src/util/routing.tsx | 75 ++++++++++++------- 3 files changed, 55 insertions(+), 32 deletions(-) diff --git a/packages/frontend/src/components/App.tsx b/packages/frontend/src/components/App.tsx index dd2be52..4d5dcdb 100644 --- a/packages/frontend/src/components/App.tsx +++ b/packages/frontend/src/components/App.tsx @@ -6,9 +6,9 @@ import history from '../util/history'; import { FeatureFlagsProvider } from 'elite-feature-flags'; import { Configuration } from 'elite-types'; import { getConfiguration } from 'elite-configuration'; -import { APP_ROUTES } from '../util/routing'; +import { getAllRegisteredAppRoutes } from '../util/routing'; -// Files must be required for decorator to work +// Files must be required (early!) for decorator to work require('../components/pages/HomePage'); require('../components/pages/LinkPage'); @@ -18,7 +18,7 @@ export const AppComponent = () => ( - {APP_ROUTES.map((routeProps, index) => ( + {getAllRegisteredAppRoutes().map((routeProps, index) => ( ))} {/* Error 404 Fallback */} diff --git a/packages/frontend/src/components/pages/support/LinkDirectory.tsx b/packages/frontend/src/components/pages/support/LinkDirectory.tsx index 8180d69..fe5179c 100644 --- a/packages/frontend/src/components/pages/support/LinkDirectory.tsx +++ b/packages/frontend/src/components/pages/support/LinkDirectory.tsx @@ -1,12 +1,12 @@ import * as React from 'react'; import { Link } from 'react-router-dom'; -import { APP_ROUTES, getLinkForPage, getLinkDisplayNameForPage } from '../../../util/routing'; +import { getLinkForRoute, getDisplayNameForRoute, getAllRegisteredAppRoutes } from '../../../util/routing'; export const LinkDirectory = () => (
      - {APP_ROUTES.map((route, index) => ( + {getAllRegisteredAppRoutes().map((route, index) => (
    • - {getLinkDisplayNameForPage(route)} + {getDisplayNameForRoute(route)}
    • ))}
    diff --git a/packages/frontend/src/util/routing.tsx b/packages/frontend/src/util/routing.tsx index b659120..c4846b9 100644 --- a/packages/frontend/src/util/routing.tsx +++ b/packages/frontend/src/util/routing.tsx @@ -1,7 +1,24 @@ import * as React from 'react'; import { RouteProps } from 'react-router'; -// TODO: move to separate package +// If necessary, add support for: H.LocationDescriptor | ((location: H.Location) => H.LocationDescriptor); +type LinkType = string; + +/** + * Each Approute can have a specific link (i.e., path with filled parameter placeholders), + * a display Name, i.e., text of the link and a nonoptional (!) path + */ +export interface AppRouteProps extends RouteProps { + // Use this if the link target differs from the path specification, + // i.e., if the path url contains paramter specifications etc + readonly link?: LinkType; + + // link text (Human readable!) + readonly displayName?: string; + + // AppRoutes must have a path - deoptionalize this property + readonly path: string; +} /** * The Routed decorator automatically creates a route for @@ -9,32 +26,41 @@ import { RouteProps } from 'react-router'; * * @param props route properties */ -export function Routed(props: AppRouteProps) { - console.log('producing route decorator:', props); - return (constructor: any) => { - APP_ROUTES.push({ +export function Routed & { render: () => any }, P = any>( + props: AppRouteProps, +): (c: new (props: any) => T) => new (props: any) => T { + return constructor => ( + registerAppRoute({ render: p => React.createElement(constructor, p), ...props, - }); - console.log('added route for', constructor.name); - return constructor; - }; + }), + constructor + ); } -// If necessary, add support for: H.LocationDescriptor | ((location: H.Location) => H.LocationDescriptor); -type LinkType = string; +/** + * Container for all registered app routes + */ +const appRoutes: { [path: string]: AppRouteProps } = {}; -// TODO: Add documentation -export interface AppRouteProps extends RouteProps { - // Use this if the link target differs from the path specification, - // i.e., if the path url contains paramter specifications etc - readonly link?: LinkType; +/** + * Function to retrieve all currently registered app routes + */ +export function getAllRegisteredAppRoutes() { + return Object.values(appRoutes); +} - // link text (Human readable!) - readonly displayName?: string; +/** + * Function for registering a new App route + * @param props AppRouteProps. Note that a render() function must be provided + */ +export function registerAppRoute(props: AppRouteProps & Required>) { + if (appRoutes[props.path]) { + throw new Error(`ERROR: detected illegal duplicate app route ${props.path}`); + } - // AppRoutes must have a path - deoptionalize this property - readonly path: string; + appRoutes[props.path] = props; + console.log('added route ', props.path); } // TODO: replace with proper container/service class @@ -43,7 +69,7 @@ export interface AppRouteProps extends RouteProps { * to link to a certain route * @param route the route to link to */ -export function getLinkForPage(route: AppRouteProps): LinkType { +export function getLinkForRoute(route: AppRouteProps): LinkType { return route.link || route.path; } @@ -54,9 +80,6 @@ export function getLinkForPage(route: AppRouteProps): LinkType { * * @param route */ -export function getLinkDisplayNameForPage(route: AppRouteProps): string { - return route.displayName || getLinkForPage(route); +export function getDisplayNameForRoute(route: AppRouteProps): string { + return route.displayName || getLinkForRoute(route); } - -// TODO: replace with proper container/service class -export const APP_ROUTES: AppRouteProps[] = []; From 25eff2ac6825d3acd52c8e66e68d62b8d7963d42 Mon Sep 17 00:00:00 2001 From: Dominik Horn Date: Thu, 27 Feb 2020 10:18:44 +0100 Subject: [PATCH 3/5] move routing util code to separate package #13 --- packages/frontend/package.json | 3 ++- packages/frontend/src/components/App.tsx | 6 ++++-- .../src/components/pages/HomePage.tsx | 5 +++-- .../src/components/pages/LinkPage.tsx | 5 +++-- .../pages/support/LinkDirectory.tsx | 2 +- packages/frontend/src/util/routes.ts | 4 ++++ packages/frontend/tsconfig.json | 6 ++++-- packages/routing/package.json | 21 +++++++++++++++++++ packages/routing/src/index.ts | 1 + .../src/util => routing/src}/routing.tsx | 2 -- packages/routing/tsconfig.json | 14 +++++++++++++ 11 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 packages/frontend/src/util/routes.ts create mode 100644 packages/routing/package.json create mode 100644 packages/routing/src/index.ts rename packages/{frontend/src/util => routing/src}/routing.tsx (95%) create mode 100644 packages/routing/tsconfig.json diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 6fec32b..acbb49c 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -26,6 +26,7 @@ "react-router": "^5.1.2", "react-router-dom": "^5.1.2", "elite-feature-flags": "^1.0.0", - "elite-configuration": "^1.0.0" + "elite-configuration": "^1.0.0", + "elite-routing": "^1.0.0" } } diff --git a/packages/frontend/src/components/App.tsx b/packages/frontend/src/components/App.tsx index 4d5dcdb..64e7c14 100644 --- a/packages/frontend/src/components/App.tsx +++ b/packages/frontend/src/components/App.tsx @@ -6,9 +6,11 @@ import history from '../util/history'; import { FeatureFlagsProvider } from 'elite-feature-flags'; import { Configuration } from 'elite-types'; import { getConfiguration } from 'elite-configuration'; -import { getAllRegisteredAppRoutes } from '../util/routing'; +import { getAllRegisteredAppRoutes } from 'elite-routing'; +import { AppPaths } from '../util/routes'; // Files must be required (early!) for decorator to work +// TODO: move to routes.ts require('../components/pages/HomePage'); require('../components/pages/LinkPage'); @@ -22,7 +24,7 @@ export const AppComponent = () => ( ))} {/* Error 404 Fallback */} - +
    diff --git a/packages/frontend/src/components/pages/HomePage.tsx b/packages/frontend/src/components/pages/HomePage.tsx index ec66118..0961e64 100644 --- a/packages/frontend/src/components/pages/HomePage.tsx +++ b/packages/frontend/src/components/pages/HomePage.tsx @@ -3,11 +3,12 @@ import { RouteComponentProps } from 'react-router'; import { LinkDirectory } from './support/LinkDirectory'; import { Divider } from '@material-ui/core'; import { FeatureFlag } from 'elite-feature-flags'; -import { Routed } from '../../util/routing'; +import { Routed } from 'elite-routing'; +import { AppPaths } from '../../util/routes'; export interface HomePageProps extends RouteComponentProps {} -@Routed({ path: '/home', displayName: 'Home' }) +@Routed({ path: AppPaths.HOME, displayName: 'Home' }) export class HomePage extends React.PureComponent { render() { return ( diff --git a/packages/frontend/src/components/pages/LinkPage.tsx b/packages/frontend/src/components/pages/LinkPage.tsx index 717ba59..989a7ca 100644 --- a/packages/frontend/src/components/pages/LinkPage.tsx +++ b/packages/frontend/src/components/pages/LinkPage.tsx @@ -1,13 +1,14 @@ import { Divider, List } from '@material-ui/core'; import * as React from 'react'; import { RouteComponentProps } from 'react-router'; -import { Routed } from '../../util/routing'; +import { Routed } from 'elite-routing'; +import { AppPaths } from '../../util/routes'; import { LinkListItem } from '../general/LinkListItem'; import { LinkDirectory } from './support/LinkDirectory'; export interface LinkPageProps extends RouteComponentProps {} -@Routed({ path: '/link', displayName: 'Useful Links' }) +@Routed({ path: AppPaths.LINK, displayName: 'Useful Links' }) export class LinkPage extends React.PureComponent { render() { return ( diff --git a/packages/frontend/src/components/pages/support/LinkDirectory.tsx b/packages/frontend/src/components/pages/support/LinkDirectory.tsx index fe5179c..ec54a4f 100644 --- a/packages/frontend/src/components/pages/support/LinkDirectory.tsx +++ b/packages/frontend/src/components/pages/support/LinkDirectory.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { Link } from 'react-router-dom'; -import { getLinkForRoute, getDisplayNameForRoute, getAllRegisteredAppRoutes } from '../../../util/routing'; +import { getLinkForRoute, getDisplayNameForRoute, getAllRegisteredAppRoutes } from 'elite-routing'; export const LinkDirectory = () => (
      diff --git a/packages/frontend/src/util/routes.ts b/packages/frontend/src/util/routes.ts new file mode 100644 index 0000000..09af683 --- /dev/null +++ b/packages/frontend/src/util/routes.ts @@ -0,0 +1,4 @@ +export enum AppPaths { + HOME = '/home', + LINK = '/link', +} diff --git a/packages/frontend/tsconfig.json b/packages/frontend/tsconfig.json index 1d4b811..7b0a9ff 100644 --- a/packages/frontend/tsconfig.json +++ b/packages/frontend/tsconfig.json @@ -3,8 +3,7 @@ "compilerOptions": { "rootDir": "src", "outDir": "dist", - "baseUrl": "src", - "experimentalDecorators": true + "baseUrl": "src" }, "include": ["src/**/*"], "references": [ @@ -14,6 +13,9 @@ { "path": "../feature-flags" }, + { + "path": "../routing" + }, { "path": "../types" } diff --git a/packages/routing/package.json b/packages/routing/package.json new file mode 100644 index 0000000..9f2e324 --- /dev/null +++ b/packages/routing/package.json @@ -0,0 +1,21 @@ +{ + "name": "elite-routing", + "version": "1.0.0", + "private": true, + "publishConfig": { + "access": "public" + }, + "types": "dist/index.d.ts", + "main": "dist/index.js", + "scripts": { + "clean": "rm -rf dist/ node_modules/ tsconfig.tsbuildinfo" + }, + "devDependencies": { + "@types/react": "^16.9.11", + "@types/react-router": "^5.1.3", + "elite-types": "^1.0.0" + }, + "dependencies": { + "react": "^16.12.0" + } +} diff --git a/packages/routing/src/index.ts b/packages/routing/src/index.ts new file mode 100644 index 0000000..161ba39 --- /dev/null +++ b/packages/routing/src/index.ts @@ -0,0 +1 @@ +export * from './routing'; diff --git a/packages/frontend/src/util/routing.tsx b/packages/routing/src/routing.tsx similarity index 95% rename from packages/frontend/src/util/routing.tsx rename to packages/routing/src/routing.tsx index c4846b9..494e99e 100644 --- a/packages/frontend/src/util/routing.tsx +++ b/packages/routing/src/routing.tsx @@ -63,7 +63,6 @@ export function registerAppRoute(props: AppRouteProps & Required Date: Thu, 27 Feb 2020 16:05:26 +0100 Subject: [PATCH 4/5] revert to less declarative routing #13 * avoid having to forcefully require components * avoid namespace/path collisions more elegantly * make ordering pages (regarding navbar) easily feasable --- packages/frontend/src/components/App.tsx | 9 ++---- .../src/components/pages/HomePage.tsx | 27 +++++++---------- .../src/components/pages/LinkPage.tsx | 29 +++++++------------ packages/frontend/src/util/routes.ts | 4 --- packages/frontend/src/util/routes.tsx | 22 ++++++++++++++ packages/routing/src/routing.tsx | 18 ------------ 6 files changed, 46 insertions(+), 63 deletions(-) delete mode 100644 packages/frontend/src/util/routes.ts create mode 100644 packages/frontend/src/util/routes.tsx diff --git a/packages/frontend/src/components/App.tsx b/packages/frontend/src/components/App.tsx index 64e7c14..4fa933c 100644 --- a/packages/frontend/src/components/App.tsx +++ b/packages/frontend/src/components/App.tsx @@ -7,13 +7,10 @@ import { FeatureFlagsProvider } from 'elite-feature-flags'; import { Configuration } from 'elite-types'; import { getConfiguration } from 'elite-configuration'; import { getAllRegisteredAppRoutes } from 'elite-routing'; -import { AppPaths } from '../util/routes'; - -// Files must be required (early!) for decorator to work -// TODO: move to routes.ts -require('../components/pages/HomePage'); -require('../components/pages/LinkPage'); +import { AppPaths, registerRoutes } from '../util/routes'; +// Global bootstrap: install subsystems and load configuration +registerRoutes(); const configuration: Configuration = getConfiguration(); export const AppComponent = () => ( diff --git a/packages/frontend/src/components/pages/HomePage.tsx b/packages/frontend/src/components/pages/HomePage.tsx index 0961e64..f3e3656 100644 --- a/packages/frontend/src/components/pages/HomePage.tsx +++ b/packages/frontend/src/components/pages/HomePage.tsx @@ -3,23 +3,16 @@ import { RouteComponentProps } from 'react-router'; import { LinkDirectory } from './support/LinkDirectory'; import { Divider } from '@material-ui/core'; import { FeatureFlag } from 'elite-feature-flags'; -import { Routed } from 'elite-routing'; -import { AppPaths } from '../../util/routes'; export interface HomePageProps extends RouteComponentProps {} -@Routed({ path: AppPaths.HOME, displayName: 'Home' }) -export class HomePage extends React.PureComponent { - render() { - return ( - <> -

      Main Page

      - - Elite Sexyz is currently under construction. See discord main channel for more information - - - - - ); - } -} +export const HomePage = (props: HomePageProps) => ( + <> +

      Main Page

      + + Elite Sexyz is currently under construction. See discord main channel for more information + + + + +); diff --git a/packages/frontend/src/components/pages/LinkPage.tsx b/packages/frontend/src/components/pages/LinkPage.tsx index 989a7ca..ef63230 100644 --- a/packages/frontend/src/components/pages/LinkPage.tsx +++ b/packages/frontend/src/components/pages/LinkPage.tsx @@ -1,28 +1,21 @@ import { Divider, List } from '@material-ui/core'; import * as React from 'react'; import { RouteComponentProps } from 'react-router'; -import { Routed } from 'elite-routing'; -import { AppPaths } from '../../util/routes'; import { LinkListItem } from '../general/LinkListItem'; import { LinkDirectory } from './support/LinkDirectory'; export interface LinkPageProps extends RouteComponentProps {} -@Routed({ path: AppPaths.LINK, displayName: 'Useful Links' }) -export class LinkPage extends React.PureComponent { - render() { - return ( - <> -

      Useful Links List

      - - - - +export const LinkPage = (props: LinkPageProps) => ( + <> +

      Useful Links List

      + + + + - + - - - ); - } -} + + +); diff --git a/packages/frontend/src/util/routes.ts b/packages/frontend/src/util/routes.ts deleted file mode 100644 index 09af683..0000000 --- a/packages/frontend/src/util/routes.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum AppPaths { - HOME = '/home', - LINK = '/link', -} diff --git a/packages/frontend/src/util/routes.tsx b/packages/frontend/src/util/routes.tsx new file mode 100644 index 0000000..da2b0b0 --- /dev/null +++ b/packages/frontend/src/util/routes.tsx @@ -0,0 +1,22 @@ +import * as React from 'react'; +import { HomePage } from '../components/pages/HomePage'; +import { LinkPage } from '../components/pages/LinkPage'; +import { registerAppRoute } from 'elite-routing'; + +export enum AppPaths { + HOME = '/home', + LINK = '/link', +} + +export function registerRoutes() { + registerAppRoute({ + path: AppPaths.HOME, + displayName: 'Home', + render: props => , + }); + registerAppRoute({ + path: AppPaths.LINK, + displayName: 'Useful Links', + render: props => , + }); +} diff --git a/packages/routing/src/routing.tsx b/packages/routing/src/routing.tsx index 494e99e..3b125f3 100644 --- a/packages/routing/src/routing.tsx +++ b/packages/routing/src/routing.tsx @@ -20,24 +20,6 @@ export interface AppRouteProps extends RouteProps { readonly path: string; } -/** - * The Routed decorator automatically creates a route for - * the annotated top level page component - * - * @param props route properties - */ -export function Routed & { render: () => any }, P = any>( - props: AppRouteProps, -): (c: new (props: any) => T) => new (props: any) => T { - return constructor => ( - registerAppRoute({ - render: p => React.createElement(constructor, p), - ...props, - }), - constructor - ); -} - /** * Container for all registered app routes */ From fcc1d4de98e58fefa229cff12bab8be49e1eb383 Mon Sep 17 00:00:00 2001 From: Dominik Horn Date: Thu, 27 Feb 2020 16:22:09 +0100 Subject: [PATCH 5/5] remove routing package and reimplement old routing style #13 --- packages/frontend/package.json | 3 +- packages/frontend/src/components/App.tsx | 16 ++- .../src/components/pages/HomePage.tsx | 4 +- .../pages/support/LinkDirectory.tsx | 4 +- packages/frontend/src/util/routes.tsx | 109 +++++++++++++++--- packages/frontend/tsconfig.json | 3 - packages/routing/package.json | 21 ---- packages/routing/src/index.ts | 1 - packages/routing/src/routing.tsx | 65 ----------- packages/routing/tsconfig.json | 14 --- 10 files changed, 108 insertions(+), 132 deletions(-) delete mode 100644 packages/routing/package.json delete mode 100644 packages/routing/src/index.ts delete mode 100644 packages/routing/src/routing.tsx delete mode 100644 packages/routing/tsconfig.json diff --git a/packages/frontend/package.json b/packages/frontend/package.json index acbb49c..6fec32b 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -26,7 +26,6 @@ "react-router": "^5.1.2", "react-router-dom": "^5.1.2", "elite-feature-flags": "^1.0.0", - "elite-configuration": "^1.0.0", - "elite-routing": "^1.0.0" + "elite-configuration": "^1.0.0" } } diff --git a/packages/frontend/src/components/App.tsx b/packages/frontend/src/components/App.tsx index 4fa933c..a277b98 100644 --- a/packages/frontend/src/components/App.tsx +++ b/packages/frontend/src/components/App.tsx @@ -1,27 +1,25 @@ +import { getConfiguration } from 'elite-configuration'; +import { FeatureFlagsProvider } from 'elite-feature-flags'; +import { Configuration } from 'elite-types'; import * as React from 'react'; import { hot } from 'react-hot-loader'; -import { Route, Switch, Redirect } from 'react-router'; +import { Redirect, Route, Switch } from 'react-router'; import { Router } from 'react-router-dom'; import history from '../util/history'; -import { FeatureFlagsProvider } from 'elite-feature-flags'; -import { Configuration } from 'elite-types'; -import { getConfiguration } from 'elite-configuration'; -import { getAllRegisteredAppRoutes } from 'elite-routing'; -import { AppPaths, registerRoutes } from '../util/routes'; +import { AppPath, APP_ROUTES } from '../util/routes'; // Global bootstrap: install subsystems and load configuration -registerRoutes(); const configuration: Configuration = getConfiguration(); export const AppComponent = () => ( - {getAllRegisteredAppRoutes().map((routeProps, index) => ( + {APP_ROUTES.map((routeProps, index) => ( ))} {/* Error 404 Fallback */} - + diff --git a/packages/frontend/src/components/pages/HomePage.tsx b/packages/frontend/src/components/pages/HomePage.tsx index f3e3656..272989c 100644 --- a/packages/frontend/src/components/pages/HomePage.tsx +++ b/packages/frontend/src/components/pages/HomePage.tsx @@ -1,8 +1,8 @@ +import { Divider } from '@material-ui/core'; +import { FeatureFlag } from 'elite-feature-flags'; import * as React from 'react'; import { RouteComponentProps } from 'react-router'; import { LinkDirectory } from './support/LinkDirectory'; -import { Divider } from '@material-ui/core'; -import { FeatureFlag } from 'elite-feature-flags'; export interface HomePageProps extends RouteComponentProps {} diff --git a/packages/frontend/src/components/pages/support/LinkDirectory.tsx b/packages/frontend/src/components/pages/support/LinkDirectory.tsx index ec54a4f..84964f2 100644 --- a/packages/frontend/src/components/pages/support/LinkDirectory.tsx +++ b/packages/frontend/src/components/pages/support/LinkDirectory.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; import { Link } from 'react-router-dom'; -import { getLinkForRoute, getDisplayNameForRoute, getAllRegisteredAppRoutes } from 'elite-routing'; +import { APP_ROUTES, getDisplayNameForRoute, getLinkForRoute } from '../../../util/routes'; export const LinkDirectory = () => (
        - {getAllRegisteredAppRoutes().map((route, index) => ( + {APP_ROUTES.map((route, index) => (
      • {getDisplayNameForRoute(route)}
      • diff --git a/packages/frontend/src/util/routes.tsx b/packages/frontend/src/util/routes.tsx index da2b0b0..2428e6e 100644 --- a/packages/frontend/src/util/routes.tsx +++ b/packages/frontend/src/util/routes.tsx @@ -1,22 +1,105 @@ import * as React from 'react'; import { HomePage } from '../components/pages/HomePage'; import { LinkPage } from '../components/pages/LinkPage'; -import { registerAppRoute } from 'elite-routing'; +import { RouteProps } from 'react-router'; -export enum AppPaths { +// If necessary, add support for: H.LocationDescriptor | ((location: H.Location) => H.LocationDescriptor); +type LinkType = string; + +/** + * Each Approute can have a specific link (i.e., path with filled parameter placeholders), + * a display Name, i.e., text of the link and a nonoptional (!) path + * + * TODO: move to types package to be able to move app routes to their own + * individual packages + */ +export interface AppRouteProps extends RouteProps { + // Use this if the link target differs from the path specification, + // i.e., if the path url contains paramter specifications etc + readonly link?: LinkType; + + // link text (Human readable!) + readonly displayName?: string; + + // AppRoutes must have a path - deoptionalize this property + readonly path: AppPath; +} + +/** + * All available paths in this app + */ +export enum AppPath { HOME = '/home', LINK = '/link', + ERROR = '/', +} + +/** + * Route for the Home page of this app + * + * TODO: replace with imported version (except of path: property) + * once HomePage is moved to different package + */ +const HOME_ROUTE: AppRouteProps = { + path: AppPath.HOME, + displayName: 'Home', + render: props => , +}; + +/** + * Route for the Link page of this app + * + * TODO: replace `with imported version (except of path: property + * once LinkPage is moved to different package) + */ +const LINK_ROUTE: AppRouteProps = { + path: AppPath.LINK, + displayName: 'Useful Links', + render: props => , +}; + +export const APP_ROUTES: AppRouteProps[] = [HOME_ROUTE, LINK_ROUTE]; + +/** + * Retrieves the url which other pages can use to link to a certain + * app path + * + * @param route + */ +export function getLinkForRoute(route: AppRouteProps): LinkType { + return route.link || route.path; +} + +/** + * Retrieves the url which other pages can use to link to a certain + * app path + * + * @param path + */ +export function getLinkForPath(path: AppPath): LinkType { + const route = APP_ROUTES.find(route => route.path == path); + if (!route) return AppPath.ERROR; + + return getLinkForRoute(route); +} + +/** + * Retrieves the human readable link title/displayed name for + * a given route + * + * @param route + */ +export function getDisplayNameForRoute(route: AppRouteProps): string { + return route.displayName || getLinkForRoute(route); } -export function registerRoutes() { - registerAppRoute({ - path: AppPaths.HOME, - displayName: 'Home', - render: props => , - }); - registerAppRoute({ - path: AppPaths.LINK, - displayName: 'Useful Links', - render: props => , - }); +/** + * Retrieves the human readable link title/displayed name for + * a given path + * + * @param path + */ +export function getDisplayNameForPath(path: AppPath): string { + const route = APP_ROUTES.find(route => route.path == path); + return route ? getDisplayNameForRoute(route) : 'Error'; } diff --git a/packages/frontend/tsconfig.json b/packages/frontend/tsconfig.json index 7b0a9ff..c4af582 100644 --- a/packages/frontend/tsconfig.json +++ b/packages/frontend/tsconfig.json @@ -13,9 +13,6 @@ { "path": "../feature-flags" }, - { - "path": "../routing" - }, { "path": "../types" } diff --git a/packages/routing/package.json b/packages/routing/package.json deleted file mode 100644 index 9f2e324..0000000 --- a/packages/routing/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "elite-routing", - "version": "1.0.0", - "private": true, - "publishConfig": { - "access": "public" - }, - "types": "dist/index.d.ts", - "main": "dist/index.js", - "scripts": { - "clean": "rm -rf dist/ node_modules/ tsconfig.tsbuildinfo" - }, - "devDependencies": { - "@types/react": "^16.9.11", - "@types/react-router": "^5.1.3", - "elite-types": "^1.0.0" - }, - "dependencies": { - "react": "^16.12.0" - } -} diff --git a/packages/routing/src/index.ts b/packages/routing/src/index.ts deleted file mode 100644 index 161ba39..0000000 --- a/packages/routing/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './routing'; diff --git a/packages/routing/src/routing.tsx b/packages/routing/src/routing.tsx deleted file mode 100644 index 3b125f3..0000000 --- a/packages/routing/src/routing.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import * as React from 'react'; -import { RouteProps } from 'react-router'; - -// If necessary, add support for: H.LocationDescriptor | ((location: H.Location) => H.LocationDescriptor); -type LinkType = string; - -/** - * Each Approute can have a specific link (i.e., path with filled parameter placeholders), - * a display Name, i.e., text of the link and a nonoptional (!) path - */ -export interface AppRouteProps extends RouteProps { - // Use this if the link target differs from the path specification, - // i.e., if the path url contains paramter specifications etc - readonly link?: LinkType; - - // link text (Human readable!) - readonly displayName?: string; - - // AppRoutes must have a path - deoptionalize this property - readonly path: string; -} - -/** - * Container for all registered app routes - */ -const appRoutes: { [path: string]: AppRouteProps } = {}; - -/** - * Function to retrieve all currently registered app routes - */ -export function getAllRegisteredAppRoutes() { - return Object.values(appRoutes); -} - -/** - * Function for registering a new App route - * @param props AppRouteProps. Note that a render() function must be provided - */ -export function registerAppRoute(props: AppRouteProps & Required>) { - if (appRoutes[props.path]) { - throw new Error(`ERROR: detected illegal duplicate app route ${props.path}`); - } - - appRoutes[props.path] = props; - console.log('added route ', props.path); -} - -/** - * Retrieves the url which other pages can use - * to link to a certain route - * @param route the route to link to - */ -export function getLinkForRoute(route: AppRouteProps): LinkType { - return route.link || route.path; -} - -/** - * Retrieves the humand readable link title/displayed name - * for a given route - * - * @param route - */ -export function getDisplayNameForRoute(route: AppRouteProps): string { - return route.displayName || getLinkForRoute(route); -} diff --git a/packages/routing/tsconfig.json b/packages/routing/tsconfig.json deleted file mode 100644 index ccfc6c0..0000000 --- a/packages/routing/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "rootDir": "src", - "outDir": "dist", - "baseUrl": "src" - }, - "include": ["src/**/*"], - "references": [ - { - "path": "../types" - } - ] -}