Skip to content

Commit

Permalink
feat: Portal design (#688)
Browse files Browse the repository at this point in the history
* Add user, dev, isv, admin portal routes

* feat: Portal architecture

* chore: Admin portal (#690)

* chore: Developer portal (#691)

* fix: TopNav switch link in different portals (#692)

* feat: Add cluster, cluster detail to user portal

* Refine entry file

* Refine Layout comp, remove socket listen

* feat: Add runtimes, runtime create page for user portal

* Fix all routes links

* Refactor: Cluster, runtime pages suit user and non-user portal
  • Loading branch information
sunnywx authored Jan 22, 2019
1 parent 8663247 commit cb05f32
Show file tree
Hide file tree
Showing 86 changed files with 1,592 additions and 986 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"lodash": "^4.17.5",
"mobx": "^5.1.0",
"mobx-react": "^5.3.6",
"path-to-regexp": "^3.0.0",
"promise-polyfill": "^7.0.0",
"prop-types": "^15.6.0",
"query-string": "^6.2.0",
Expand Down
137 changes: 48 additions & 89 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,104 +1,63 @@
import React from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';

import { Provider } from 'mobx-react';
import React, { lazy } from 'react';
import {
Router, Switch, Route, Redirect
} from 'react-router-dom';
import { I18nextProvider } from 'react-i18next';

import LazyLoad from 'components/LazyLoad';
import Header from 'components/Header';
import Footer from 'components/Footer';
import ErrorBoundary from 'components/ErrorBoundary';
import Wrapper from 'routes/wrapper';
import history from './createHistory';

import './scss/index.scss';

// fixme
const noHeaderPath = ['/dashboard/provider/submit'];

const WrapRoute = ({ component: Comp, ...rest }) => {
const {
path, store, computedMatch, needAuth, noMatch
} = rest;
const user = store.user || {};

// todo
const hasHeader = path !== '/login'
&& !noHeaderPath.includes(path)
&& (user.isNormal || !user.accessToken);

if (noMatch) {
return <Redirect to="/" />;
}
import NotFound from 'components/NotFound';

if (needAuth && !user.isLoggedIn()) {
return <Redirect to={`/login?redirect_url=${computedMatch.url || ''}`} />;
}

const isHome = rest.applyHome || Comp.isHome;
let { acl } = rest;

if (!_.isEmpty(acl)) {
acl = [].concat(acl);
if (!_.some(acl, role => user[`is${role}`])) {
return <Redirect to="/" />;
}
}
import Home from 'pages/Home';
import { Account } from 'pages/Dashboard';
import {
UserRoutes, DevRoutes, IsvRoutes, AdminRoutes
} from 'routes';
import WrapRoute from 'routes/WrapRoute';

return (
<Route
{...rest}
render={props => (
<ErrorBoundary>
{(hasHeader || isHome) && <Header />}
<Wrapper comp={Comp} {...props} rootStore={store} />
{(hasHeader || isHome) && <Footer />}
</ErrorBoundary>
)}
/>
);
};
import history from './createHistory';

class App extends React.Component {
static propTypes = {
i18n: PropTypes.object,
routes: PropTypes.array.isRequired,
store: PropTypes.object.isRequired
};
import './scss/index.scss';

static defaultProps = {
routes: [],
store: {},
i18n: {}
};
const Login = lazy(() => import('./pages/Login'));
const AppDetail = lazy(() => import('./pages/AppDetail'));

export default class App extends React.Component {
render() {
const {
routes, store, sock, i18n
} = this.props;

return (
<I18nextProvider i18n={i18n}>
<Provider rootStore={store} sock={sock}>
<Router history={history}>
<div className="main">
<LazyLoad>
<Switch>
{routes.map(route => (
<WrapRoute {...route} store={store} key={route.path} />
))}
</Switch>
</LazyLoad>
</div>
</Router>
</Provider>
</I18nextProvider>
<Router history={history}>
<LazyLoad>
<div className="main">
<Switch>
<WrapRoute path="/" component={Home} />
<WrapRoute path="/login" component={Login} />
<WrapRoute path="/apps/:appId" component={AppDetail} />
<WrapRoute path="/profile" component={Account} />

<Route
path="/user"
render={({ match }) => <UserRoutes prefix={match.path} />}
/>

<Route
path="/dev"
render={({ match }) => <DevRoutes prefix={match.path} />}
/>

<Route
path="/isv"
render={({ match }) => <IsvRoutes prefix={match.path} />}
/>

<Route
path="/admin"
render={({ match }) => <AdminRoutes prefix={match.path} />}
/>

<Redirect from="/apps" exact to="/" />
<WrapRoute component={NotFound} />
</Switch>
</div>
</LazyLoad>
</Router>
);
}
}

export default App;
3 changes: 2 additions & 1 deletion src/components/AppImages/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { translate } from 'react-i18next';
import { inject } from 'mobx-react';

import { Image } from 'components/Base';
import routes, { toRoute } from 'routes';

import styles from './index.scss';

Expand Down Expand Up @@ -34,7 +35,7 @@ export default class AppImages extends Component {
<Link
className={styles.image}
key={app_id}
to={`/apps/${app_id}`}
to={toRoute(routes.appDetail, { appId: app_id })}
title={name}
>
<Image src={icon} iconLetter={name} className={styles.img} />
Expand Down
6 changes: 1 addition & 5 deletions src/components/AppList/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@

.appList {
position: relative;
margin-top: -10px;
overflow: hidden;
_zoom: 1;

&.fixNav {
top: 132px;
}
top: 30px;

> div {
&:nth-child(3n+4) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,20 @@ import { inject, observer } from 'mobx-react';

import { Image } from 'components/Base';
import SearchBox from 'pages/Home/SearchBox';
import { getPortalFromPath } from 'routes';

import styles from './index.scss';

@translate()
@inject('rootStore')
@observer
export default class TitleBanner extends Component {
export default class Banner extends Component {
static propTypes = {
className: PropTypes.string,
description: PropTypes.string,
hasSearch: PropTypes.bool,
icon: PropTypes.string,
shrink: PropTypes.bool,
stretch: PropTypes.bool,
title: PropTypes.string
};
Expand All @@ -27,7 +29,8 @@ export default class TitleBanner extends Component {
title: '',
description: '',
hasSearch: false,
stretch: false
stretch: false,
shrink: false
};

render() {
Expand All @@ -38,18 +41,23 @@ export default class TitleBanner extends Component {
hasSearch,
className,
stretch,
shrink,
rootStore,
t
} = this.props;

if (!['', 'user'].includes(getPortalFromPath())) {
return null;
}

return (
<div
className={classnames(
'banner',
styles.titleBanner,
styles.banner,
{
[styles.stretch]: stretch,
[styles.shrink]: rootStore.fixNav
[styles.shrink]: shrink || rootStore.fixNav
},
className
)}
Expand Down
117 changes: 117 additions & 0 deletions src/components/Banner/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
@import "~scss/vars";

.banner {
//position: sticky;
position: fixed;
width: 100%;
z-index: 2;
top: $header-height;
padding: 30px 0;
background-color: $N500;
transition: height .3s ease-in-out;

&.stretch {
padding: 64px 0;
.search {
float: none;
top: 0;
}
}

&.shrink {
padding: 30px 0 !important;
.search {
transition: all .3s ease-in-out;
float: right;
top: -15px;
}
}

.wrapper {
width: $content-width;
margin: 0 auto;

.words {
display: inline-block;
}
}

.image,
.icon {
float: left;
margin-right: 12px;
width: 48px;
height: 48px;
}

.image {
line-height: 48px;

img {
max-width: 100%;
max-height: 100%;
vertical-align: middle;
}
}

.icon {
box-sizing: border-box;
padding: 12px;
background-color: $N400;
border-radius: 3px;
}

.name {
margin-bottom: 4px;
font-size: 20px;
font-weight: 500;
line-height: 24px;
letter-spacing: 0;
color: $N0;
}

.description {
display: inline-block;
height: 20px;
line-height: 20px;
font-size: 12px;
color: $N65;
overflow: hidden;
}

.search {
position: relative;
width: 303px;

input {
color: $N0;
padding-left: 36px;
border-radius: 16px;
border: 1px solid transparent;
background-color: rgba(255, 255, 255, 0.1);
transition: all 0.3s ease-in-out;

&::placeholder {
font-size: 12px;
color: $N65;
line-height: 1;
letter-spacing: 0;
}

&:focus, &:hover {
border: solid 1px $P75;
}
}

svg {
--primary-color: #{$N0};
--secondary-color: #{$N0};
opacity: 0.5;

&:hover,
&:focus {
opacity: 1;
}
}
}
}
2 changes: 1 addition & 1 deletion src/components/Base/Checkbox/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
position: absolute;
left: 1px;
top: 50%;
z-index: 2;
z-index: 1;
width: 14px;
height: 14px;
font-style: normal;
Expand Down
Loading

0 comments on commit cb05f32

Please sign in to comment.