Skip to content

Commit ecfe35a

Browse files
authored
Merge pull request #82 from zenml-io/Redirect-via-URL
Redirect via url
2 parents 9b14d52 + 7214a2d commit ecfe35a

File tree

13 files changed

+394
-299
lines changed

13 files changed

+394
-299
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
"tslint": "tsc",
7979
"all": "eslint './src/**/*.ts*' & react-scripts test --all & tsc"
8080
},
81-
"homepage": "/login",
81+
8282
"browserslist": {
8383
"production": [
8484
">0.2%",

src/constants/routes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
import { routePaths } from '../routes/routePaths';
22
export const loggedOutRoute = routePaths.login;
3-
export const loggedInRoute = routePaths.home(':string');
3+
export const loggedInRoute = routePaths.home;

src/routes/appRoutesConfig.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Signup from '../ui/layouts/session/Signup';
88
import UserEmail from '../ui/layouts/session/UserEmail';
99
import ForgotPassword from '../ui/layouts/session/ForgotPassword';
1010
import Home from '../ui/layouts/Home';
11+
import DashBoard from '../ui/layouts/DashBoard';
1112

1213
import Pipelines from '../ui/layouts/pipelines/Pipelines';
1314
import stacks from '../ui/layouts/stacks/Stacks';
@@ -53,7 +54,15 @@ const routes = [
5354
},
5455
},
5556
{
56-
path: routePaths.home(':string'),
57+
path: routePaths.dashboard(':string'),
58+
Component: DashBoard,
59+
visibility: {
60+
authentication: RouteVisibilityAuthentication.authenticatedOnly,
61+
},
62+
exact: true,
63+
},
64+
{
65+
path: routePaths.home,
5766
Component: Home,
5867
visibility: {
5968
authentication: RouteVisibilityAuthentication.authenticatedOnly,

src/routes/routePaths.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ export const routePaths = {
77
signup: '/signup',
88
userEmail: `/user-email`,
99
forgot: '/forgot-password',
10-
home: (project: string): string => `/projects/${project}`,
10+
home: `/`,
11+
dashboard: (project: string): string => `/projects/${project}`,
1112
pipelines: {
1213
base: `/pipelines`,
1314
list: (project: string): string => `/projects/${project}/pipelines/list`,

src/routes/utils/replaceRouteIfNeeded.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export const replaceRouteIfNeeded = ({
4747
const logRoute =
4848
user?.emailOptedIn === null
4949
? `/user-email`
50-
: routePaths.home(DEFAULT_PROJECT_NAME);
50+
: routePaths.dashboard(DEFAULT_PROJECT_NAME);
5151

5252
return isAuthenticated ? logRoute : loggedOutRoute;
5353
};

src/ui/layouts/DashBoard.tsx

Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
/* eslint-disable */
2+
3+
import React, { useState, useEffect } from 'react';
4+
import { AuthenticatedLayout } from './common/layouts/AuthenticatedLayout';
5+
import { SidebarContainer } from './common/layouts/SidebarContainer';
6+
import {
7+
Box,
8+
Col,
9+
EaseInBox,
10+
FlexBox,
11+
H2,
12+
H4,
13+
Row,
14+
ColoredCircle,
15+
icons,
16+
GhostButton,
17+
Paragraph,
18+
FullWidthSpinner,
19+
} from '../components';
20+
import { getTranslateByScope } from '../../services';
21+
22+
import styles from './Home.module.scss';
23+
import {
24+
iconColors,
25+
DEFAULT_PROJECT_NAME,
26+
toasterTypes,
27+
} from '../../constants';
28+
import { sessionSelectors } from '../../redux/selectors/session';
29+
import {
30+
useDispatch,
31+
useLocationPath,
32+
usePushRoute,
33+
useSelector,
34+
} from '../hooks';
35+
import axios from 'axios';
36+
import { routePaths } from '../../routes/routePaths';
37+
import {
38+
projectSelectors,
39+
stackComponentSelectors,
40+
} from '../../redux/selectors';
41+
import {
42+
showToasterAction,
43+
projectsActions,
44+
pipelinesActions,
45+
pipelinePagesActions,
46+
runPagesActions,
47+
} from '../../redux/actions';
48+
import { NotFound } from './NotFound';
49+
50+
import Tour from './Tour';
51+
52+
export const translate = getTranslateByScope('ui.layouts.Dashboard');
53+
54+
const GreyBoxWithIcon: React.FC<{
55+
title: string;
56+
buttonText: string;
57+
IconComponent: React.ReactNode;
58+
onClick: () => void;
59+
}> = ({ title, buttonText, IconComponent, onClick }) => {
60+
return (
61+
<FlexBox.Row
62+
marginVertical="md"
63+
className={styles.greyBoxWithIcon}
64+
padding="md"
65+
alignItems="center"
66+
justifyContent="space-between"
67+
>
68+
<FlexBox.Row alignItems="center">
69+
<Box marginRight="md">
70+
<ColoredCircle color="primary" size="lg">
71+
{IconComponent}
72+
</ColoredCircle>
73+
</Box>
74+
<H4 bold>{title}</H4>
75+
</FlexBox.Row>
76+
<Box>
77+
<GhostButton style={{ width: '124px' }} onClick={onClick}>
78+
{buttonText}
79+
</GhostButton>
80+
</Box>
81+
</FlexBox.Row>
82+
);
83+
};
84+
85+
export const DashBoard: React.FC = () => {
86+
const { push } = usePushRoute();
87+
const dispatch = useDispatch();
88+
const locationPath = useLocationPath();
89+
const [isHover, setIsHover] = useState(false);
90+
const [box, setBox] = useState('');
91+
const stackComponentsTypes: any[] = useSelector(
92+
stackComponentSelectors.stackComponentTypes,
93+
);
94+
const [notFound, setNotFound] = useState(false);
95+
96+
const selectedProject = useSelector(projectSelectors.selectedProject);
97+
const projects = useSelector(projectSelectors.myProjects);
98+
const [fetching, setFetching] = useState(false);
99+
const [dashboardData, setDashboardData] = useState('');
100+
const authToken = useSelector(sessionSelectors.authenticationToken);
101+
102+
const startLoad = () => {
103+
dispatch(pipelinePagesActions.setFetching({ fetching: true }));
104+
dispatch(runPagesActions.setFetching({ fetching: true }));
105+
};
106+
107+
const stopLoad = () => {
108+
dispatch(pipelinePagesActions.setFetching({ fetching: false }));
109+
dispatch(runPagesActions.setFetching({ fetching: false }));
110+
};
111+
112+
const url = window.location.pathname;
113+
// const url = new URL(url_string);
114+
// const projectName = url.searchParams.get('project');
115+
116+
useEffect(() => {
117+
if (url === '/') {
118+
push(
119+
routePaths.dashboard(
120+
selectedProject ? selectedProject : DEFAULT_PROJECT_NAME,
121+
),
122+
);
123+
}
124+
if (locationPath.includes('projects')) {
125+
const projectFromUrl = locationPath.split('/')[2];
126+
127+
push(
128+
routePaths.dashboard(
129+
projectFromUrl ? projectFromUrl : DEFAULT_PROJECT_NAME,
130+
),
131+
);
132+
}
133+
if (authToken) {
134+
const getDashboardData = async () => {
135+
setFetching(true);
136+
startLoad();
137+
138+
try {
139+
const { data } = await axios.get(
140+
`${process.env.REACT_APP_BASE_API_URL}/projects/${
141+
selectedProject ? selectedProject : DEFAULT_PROJECT_NAME
142+
}/statistics`,
143+
{ headers: { Authorization: `bearer ${authToken}` } },
144+
);
145+
146+
// await dispatch(
147+
// projectsActions.getMy({
148+
// selectDefault: false,
149+
// selectedProject: selectedProject,
150+
// onSuccess: () => stopLoad(),
151+
// onFailure: () => stopLoad(),
152+
// }),
153+
// );
154+
155+
// await dispatch(
156+
// projectsActions.getSelectedProject({
157+
// allProjects: projects,
158+
// seletecdProject: selectedProject
159+
// ? selectedProject
160+
// : DEFAULT_PROJECT_NAME,
161+
// }),
162+
// );
163+
164+
// await dispatch(
165+
// pipelinesActions.getMy({
166+
// project: selectedProject ? selectedProject : DEFAULT_PROJECT_NAME,
167+
// onSuccess: () => stopLoad(),
168+
// onFailure: () => stopLoad(),
169+
// }),
170+
// );
171+
172+
setDashboardData(data);
173+
setFetching(false);
174+
} catch (e) {
175+
dispatch(
176+
showToasterAction({
177+
description: 'Not found',
178+
type: toasterTypes.failure,
179+
}),
180+
);
181+
182+
await dispatch(
183+
projectsActions.getMy({
184+
selectDefault: false,
185+
selectedProject: DEFAULT_PROJECT_NAME,
186+
onSuccess: () => setNotFound(true),
187+
onFailure: () => stopLoad(),
188+
}),
189+
);
190+
191+
// push(routePaths.home(DEFAULT_PROJECT_NAME));
192+
}
193+
};
194+
getDashboardData();
195+
}
196+
}, [authToken, selectedProject]);
197+
198+
const preData = Object.entries(dashboardData);
199+
const data = preData?.map(([key, value]) => {
200+
const objData = { text: key, value: value };
201+
return objData;
202+
});
203+
204+
const handleMouseEnter = (e: { text: any; value?: string }) => {
205+
setBox(e.text);
206+
setIsHover(true);
207+
};
208+
209+
const handleMouseLeave = () => {
210+
setBox('');
211+
setIsHover(false);
212+
};
213+
console.log(notFound, 'notFound');
214+
if (notFound) return <NotFound />;
215+
216+
return (
217+
<AuthenticatedLayout>
218+
<SidebarContainer>
219+
<Tour />
220+
<EaseInBox>
221+
<Box marginTop="5xl" marginLeft="xl">
222+
<Row style={{ alignItems: 'center' }}>
223+
<Col xs={12} lg={10}>
224+
<Box paddingBottom="md">
225+
<H2 bold>{translate('title')}</H2>
226+
</Box>
227+
<Box paddingBottom="lg">
228+
<H4 bold>{translate('subtitle')}</H4>
229+
</Box>
230+
</Col>
231+
{fetching ? (
232+
<FullWidthSpinner color="black" size="md" />
233+
) : (
234+
<Row style={{ alignItems: 'center', marginLeft: '15px' }}>
235+
{data?.map((e, index) => (
236+
<Box
237+
onMouseEnter={() => handleMouseEnter(e)}
238+
onMouseLeave={handleMouseLeave}
239+
key={index}
240+
marginRight="xxl"
241+
style={{
242+
width: '220px',
243+
minHeight: '100px',
244+
border: '1px solid #C9CBD0',
245+
borderRadius: '6px',
246+
padding: '13px 14px',
247+
marginTop: '10px',
248+
cursor: 'pointer',
249+
backgroundColor:
250+
box === e.text && isHover ? '#431D93' : '#fff',
251+
}}
252+
onClick={() => {
253+
if (e.text === 'stacks') {
254+
push(routePaths.stacks.base);
255+
} else if (e.text === 'pipelines') {
256+
push(routePaths.pipelines.base);
257+
} else if (e.text === 'runs') {
258+
push(routePaths.pipelines.allRuns(selectedProject));
259+
} else if (e.text === 'components') {
260+
push(
261+
routePaths.stackComponents.base(
262+
stackComponentsTypes[0],
263+
selectedProject,
264+
),
265+
);
266+
}
267+
}}
268+
>
269+
<Paragraph
270+
style={{
271+
fontSize: '24px',
272+
fontWeight: 'bold',
273+
color: box === e.text ? '#fff' : '#431D93',
274+
}}
275+
>
276+
{e.value}
277+
</Paragraph>
278+
<Paragraph
279+
style={{
280+
fontSize: '14px',
281+
fontWeight: 'inherit',
282+
color: box === e.text ? '#fff' : '#646972',
283+
marginTop: '38px',
284+
}}
285+
>
286+
Number of {e.text}
287+
</Paragraph>
288+
</Box>
289+
))}
290+
</Row>
291+
)}
292+
293+
<Col xs={12} lg={7}>
294+
<Box marginTop="xxxl">
295+
<GreyBoxWithIcon
296+
onClick={() =>
297+
window.open(translate('cardOne.button.href'), '_blank')
298+
}
299+
IconComponent={<icons.bookOpen color={iconColors.white} />}
300+
title={translate('cardOne.title')}
301+
buttonText={translate('cardOne.button.text')}
302+
/>
303+
<GreyBoxWithIcon
304+
onClick={() => push('/settings/personal-details')}
305+
IconComponent={<icons.tool color={iconColors.white} />}
306+
title={translate('cardTwo.title')}
307+
buttonText={translate('cardTwo.button.text')}
308+
/>
309+
<GreyBoxWithIcon
310+
onClick={() => push('/settings/organization')}
311+
IconComponent={<icons.userPlus color={iconColors.white} />}
312+
title={translate('cardThree.title')}
313+
buttonText={translate('cardThree.button.text')}
314+
/>
315+
</Box>
316+
</Col>
317+
</Row>
318+
</Box>
319+
</EaseInBox>
320+
</SidebarContainer>
321+
</AuthenticatedLayout>
322+
);
323+
};
324+
325+
export default DashBoard;

0 commit comments

Comments
 (0)