Skip to content

Commit a89f026

Browse files
authored
Merge pull request #238 from HDI-Project/switchAnimations
Homepage animations components
2 parents 8b09557 + a82eebc commit a89f026

File tree

12 files changed

+187
-89
lines changed

12 files changed

+187
-89
lines changed

mtv-client/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"react-router-dom": "5.1.2",
2424
"react-scripts": "3.2.0",
2525
"react-select": "^3.0.8",
26+
"react-transition-group": "^4.3.0",
2627
"redux": "^4.0.4",
2728
"redux-devtools-extension": "^2.13.8",
2829
"redux-logger": "^3.0.6",
@@ -78,6 +79,7 @@
7879
"eslint-plugin-react": "7.16.0",
7980
"eslint-plugin-react-hooks": "^2.3.0",
8081
"fetch-mock": "^8.0.0",
82+
"history": "^4.10.1",
8183
"prettier": "^1.19.1",
8284
"redux-mock-store": "^1.5.3",
8385
"stylelint": "^13.0.0",

mtv-client/src/App.tsx

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,37 @@
11
import React from 'react';
2-
import { Provider } from 'react-redux';
3-
2+
import { Route, Switch, withRouter, useLocation } from 'react-router-dom';
3+
import { TransitionGroup, CSSTransition } from 'react-transition-group';
44
import Header from './components/Header/Header';
55
import Landing from './components/Landing/Landing';
6-
import store from './model/store/index';
6+
import Experiment from './components/Timeseries/Overview/Experiment';
7+
8+
const transtitionTimeOut = { enter: 1000, exit: 1000 };
79

8-
const App: React.FC = () => (
9-
<Provider store={store}>
10+
const App: React.FC = () => {
11+
const location = useLocation();
12+
const animateDirection = location.pathname === '/' ? 'animate-left' : 'animate-right';
13+
return (
1014
<div id="content-wrapper">
1115
<Header />
12-
<Landing />
16+
<TransitionGroup component="div" className="page-slider">
17+
<CSSTransition
18+
key={location.pathname}
19+
timeout={transtitionTimeOut}
20+
classNames="page-slider"
21+
mountOnEnter
22+
unmountOnExit={false}
23+
transitionName="page-slider"
24+
>
25+
<div className={animateDirection}>
26+
<Switch location={location}>
27+
<Route exact path="/" component={Landing} />
28+
<Route exact path="/experiment/:id" component={Experiment} />
29+
</Switch>
30+
</div>
31+
</CSSTransition>
32+
</TransitionGroup>
1333
</div>
14-
</Provider>
15-
);
34+
);
35+
};
1636

17-
export default App;
37+
export default withRouter(App);

mtv-client/src/assets/sass/general.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ body {
1515

1616
#content-wrapper {
1717
margin: 0;
18+
height: 93vh;
1819
}
1920

2021
.scroll-style::-webkit-scrollbar {

mtv-client/src/components/Header/Header.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,32 @@
11
import React from 'react';
22
import './header.scss';
33
import { connect } from 'react-redux';
4+
import { Link, useHistory } from 'react-router-dom';
45
import { getSelectedExperiment } from '../../model/selectors/projects';
56
import { RootState } from '../../model/types';
67

78
const mapState = (state: RootState) => ({
8-
isExperimentSelected: getSelectedExperiment(state),
9+
selectedExperimentID: getSelectedExperiment(state),
910
});
1011

1112
type StateProps = ReturnType<typeof mapState>;
1213
type Props = StateProps;
1314

1415
const Header: React.FC<Props> = props => {
15-
const isSwitchActive = props.isExperimentSelected ? 'active' : '';
16+
const isSwitchVisible = props.selectedExperimentID ? 'active' : '';
17+
let history = useHistory();
18+
const currentView = history.location.pathname;
19+
const arrowDirection = currentView === '/' ? 'right' : 'left';
20+
const linkTo = currentView === '/' ? `/experiment/${props.selectedExperimentID}` : '/';
21+
1622
return (
1723
<header id="header" className="main-header">
18-
<a href="/" className="logo">
24+
<Link to="/" className="logo">
1925
<b>MTV</b>
20-
</a>
21-
<a href="/" className={`page-switch-btn ${isSwitchActive}`}>
22-
<i className="fas fa-angle-left" />
23-
</a>
26+
</Link>
27+
<Link to={linkTo} className={`page-switch-btn ${isSwitchVisible}`}>
28+
<i className={`fas fa-angle-${arrowDirection}`} />
29+
</Link>
2430
</header>
2531
);
2632
};

mtv-client/src/components/Header/header.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
overflow: hidden;
2727
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
2828
transition: width 0.3s ease-in-out;
29+
text-decoration: none;
2930
}
3031

3132
&:hover,

mtv-client/src/components/Landing/Experiments.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react';
22
import { connect } from 'react-redux';
33
import * as _ from 'lodash';
4+
import { withRouter, useHistory } from 'react-router-dom';
45
import Loader from '../Common/Loader';
56
import {
67
getFilteredExperiments,
@@ -79,7 +80,7 @@ const Experiments: React.FC<Props> = ({
7980
<Loader isLoading={isExperimentsLoading}>
8081
{filteredExperiments.length ? (
8182
filteredExperiments.map((experiment, index) =>
82-
renderExperiment({
83+
Experiment({
8384
experiment,
8485
tagStats: tagStatsList[index],
8586
matrixScale,
@@ -103,7 +104,7 @@ const countDatarunEvents = experiment => {
103104
return dataruns.map(datarun => datarun.events.length).reduce((item, accumulator) => item + accumulator, 0);
104105
};
105106

106-
const renderExperiment: React.FC<renderExperimentProps> = ({
107+
const Experiment: React.FC<renderExperimentProps> = ({
107108
experiment,
108109
tagStats,
109110
matrixScale,
@@ -112,10 +113,11 @@ const renderExperiment: React.FC<renderExperimentProps> = ({
112113
selectedPipeline,
113114
selectedExperiment,
114115
}) => {
116+
let history = useHistory();
115117
const activeClass = selectedPipeline || selectedExperiment === experiment.id ? 'active' : '';
116118
const eventCounts = countDatarunEvents(experiment);
117119
return (
118-
<div className={`cell ${activeClass}`} key={index} onClick={() => onSelectExperiment(experiment.id)}>
120+
<div className={`cell ${activeClass}`} key={index} onClick={() => onSelectExperiment(history, experiment.id)}>
119121
<h3>
120122
#{index + 1} {experiment.dataset}_{experiment.pipeline}
121123
</h3>
@@ -140,7 +142,7 @@ const mapState = (state: RootState) => ({
140142
});
141143

142144
const mapDispatch = (dispatch: Function) => ({
143-
onSelectExperiment: (experiment: string) => dispatch(selectExperiment(experiment)),
145+
onSelectExperiment: (history, experiment: string) => dispatch(selectExperiment(history, experiment)),
144146
});
145147

146-
export default connect<StateProps, DispatchProps, {}, RootState>(mapState, mapDispatch)(Experiments);
148+
export default withRouter(connect<StateProps, DispatchProps, {}, RootState>(mapState, mapDispatch)(Experiments));

mtv-client/src/components/Landing/Landing.scss

Lines changed: 88 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,49 +2,11 @@
22
@import '../../assets/sass/animations.scss';
33

44
.page-landing {
5-
margin-top: 65px;
6-
position: relative;
7-
overflow-x: hidden;
8-
overflow-y: auto;
9-
10-
.page-wrapper {
11-
left: 0;
12-
top: 0;
13-
width: 100%;
14-
height: calc(100vh - 70px);
15-
}
16-
175
.projects-wrapper {
186
background: $second-color;
197
z-index: 10;
20-
transition: transform 1s cubic-bezier(0.694, 0, 0.335, 1), -webkit-transform 1s cubic-bezier(0.694, 0, 0.335, 1);
21-
22-
&:not(.active) {
23-
transform: translate3d(-100%, 0, 0);
24-
}
25-
26-
&.active {
27-
animation-name: homepage;
28-
animation-duration: 1s;
29-
}
308
}
319

32-
.projects-wrapper,
33-
.experiments-wrapper {
34-
position: absolute;
35-
left: 0;
36-
top: 0;
37-
width: 100%;
38-
height: 100%;
39-
}
40-
41-
.experiments-wrapper {
42-
opacity: 0;
43-
padding: 0 0 0 25px;
44-
&.active {
45-
opacity: 1;
46-
}
47-
}
4810
}
4911

5012
@keyframes homepage {
@@ -57,12 +19,12 @@
5719
}
5820

5921
.item-row {
60-
margin: 0 50px;
22+
margin: 0;
6123
padding: 0 10px;
6224
white-space: nowrap;
6325
overflow-y: hidden;
6426
overflow-x: auto;
65-
width: calc(100% - 100px);
27+
width: 100%;
6628

6729
.item-wrapper {
6830
display: flex;
@@ -135,11 +97,95 @@
13597
}
13698
.matrix {
13799
flex: 1 1 50px;
138-
// width: 180px;
139-
// height: 50px;
140100
min-width: 180px;
141101
min-height: 180px;
142102
}
143103
}
144104
}
145105
}
106+
107+
.page-slider {
108+
margin-top: 51px;
109+
width: 100%;
110+
height: 94vh;
111+
position: relative;
112+
animation-name: enterRight;
113+
animation-duration: 1s;
114+
.animate-left, .animate-right {
115+
position: absolute;
116+
top: 0;
117+
width: 100%;
118+
}
119+
120+
.mask{
121+
overflow: hidden;
122+
}
123+
124+
.page-slider-enter{
125+
background:#23242b;
126+
z-index: 9;
127+
}
128+
.page-slider-exit{
129+
background: #23242b;
130+
z-index: 1;
131+
}
132+
133+
.animate-left {
134+
&.page-slider-enter {
135+
animation-name: enterLeft;
136+
animation-duration: 1s;
137+
}
138+
&.page-slider-exit {
139+
animation-name: leaveLeft;
140+
animation-duration: 1s;
141+
}
142+
}
143+
144+
.animate-right {
145+
&.page-slider-enter{
146+
animation-name: enterRight;
147+
animation-duration: 1s;
148+
}
149+
150+
&.page-slider-exit{
151+
animation-name: leaveRight;
152+
animation-duration: 1s;
153+
}
154+
}
155+
}
156+
157+
@keyframes enterLeft {
158+
0% {
159+
transform: translate3d(-100%, 0, 0);
160+
}
161+
100% {
162+
transform: translate3d(0%, 0, 0);
163+
}
164+
}
165+
166+
@keyframes leaveLeft {
167+
0% {
168+
transform: translate3d(0%, 0, 0);
169+
}
170+
100% {
171+
transform: translate3d(-100%, 0, 0);
172+
}
173+
}
174+
175+
@keyframes enterRight {
176+
0% {
177+
transform: translate3d(100%, 0, 0);
178+
}
179+
100% {
180+
transform: translate3d(0, 0, 0);
181+
}
182+
}
183+
184+
@keyframes leaveRight{
185+
0% {
186+
transform: translate3d(0%, 0, 0);
187+
}
188+
100% {
189+
transform: translate3d(100%, 0, 0);
190+
}
191+
}

mtv-client/src/components/Landing/Landing.tsx

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
import React from 'react';
22
import { connect } from 'react-redux';
33
import { fetchProjects } from '../../model/actions/landing';
4-
import Experiment from '../Timeseries/Overview/Experiment';
5-
64
import Projects from './Projects';
75
import Pipelines from './Pipelines';
86
import Experiments from './Experiments';
97

108
import { getSelectedExperiment } from '../../model/selectors/projects';
119
import { RootState } from '../../model/types';
12-
1310
import './Landing.scss';
1411

1512
type StateProps = ReturnType<typeof mapState>;
@@ -18,26 +15,17 @@ type Props = StateProps & DispatchProps;
1815

1916
class Landing extends React.Component<Props> {
2017
componentDidMount() {
21-
this.props.fetchProjectsList();
18+
if (this.props.isExperimentSelected === null) {
19+
this.props.fetchProjectsList();
20+
}
2221
}
2322

2423
render() {
25-
const isMainPageActive = !this.props.isExperimentSelected ? 'active' : '';
26-
const isExperimentPageActive = this.props.isExperimentSelected ? 'active' : '';
27-
2824
return (
2925
<div className="page-landing">
30-
<div className="page-wrapper">
31-
<div className={`projects-wrapper ${isMainPageActive}`}>
32-
<Projects />
33-
<Pipelines />
34-
<Experiments />
35-
</div>
36-
<div className={`experiments-wrapper ${isExperimentPageActive}`}>
37-
<Experiment />
38-
<div className="clear" />
39-
</div>
40-
</div>
26+
<Projects />
27+
<Pipelines />
28+
<Experiments />
4129
</div>
4230
);
4331
}

mtv-client/src/components/Timeseries/Overview/Experiment.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11

2+
.experiment {
3+
margin: 10px 0px 10px 10px;
4+
position: relative;
5+
height: 92vh;
6+
}
7+
28
.left-sidebar{
39
float: left;
410
margin-right: 20px;

0 commit comments

Comments
 (0)