Skip to content

Commit beaed64

Browse files
authored
Merge pull request #342 from HDI-Project/timeRngeSync
Time rnge sync
2 parents 20d53a7 + 4ae6802 commit beaed64

File tree

13 files changed

+181
-48
lines changed

13 files changed

+181
-48
lines changed

client/src/components/Header/header.scss

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,20 +119,18 @@
119119
position: absolute;
120120
left: -16px;
121121
margin: 4px 0 0 0;
122-
z-index: -100;
123122
padding: 10px 15px;
124123
transition: all .2s ease-in-out;
125-
opacity: 0;
126124
top: 21px;
125+
display: none;
127126
}
128127

129128
&.active{
130129
border-bottom: none;
131130
box-shadow: none;
132131

133132
ul{
134-
z-index: 1;
135-
opacity: 1;
133+
display: block;
136134
}
137135

138136
span{

client/src/components/Timeseries/FocusChart/FocusChart.tsx

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,9 @@ export class FocusChart extends Component<Props, State> {
9191
getScale() {
9292
const { width, height } = this.state;
9393
const { dataRun } = this.props;
94-
const { maxTimeSeries } = dataRun;
94+
95+
const { maxTimeSeries, timeSeries } = dataRun;
96+
const [minDtTX, maxDtTX] = d3.extent(timeSeries, (time: Array<number>) => time[0]);
9597
const [minTX, maxTX] = d3.extent(maxTimeSeries, (time: Array<number>) => time[0]);
9698
const [minTY, maxTY] = d3.extent(maxTimeSeries, (time: Array<number>) => time[1]);
9799
const drawableWidth = width - 2 * CHART_MARGIN - TRANSLATE_LEFT;
@@ -100,16 +102,20 @@ export class FocusChart extends Component<Props, State> {
100102
const xCoord = d3.scaleTime().range([0, drawableWidth]);
101103
const yCoord = d3.scaleLinear().range([drawableHeight, 0]);
102104

105+
const minDtX = Math.min(MIN_VALUE, minDtTX);
106+
const maxDtX = Math.max(MAX_VALUE, maxDtTX);
107+
103108
const minX = Math.min(MIN_VALUE, minTX);
104109
const maxX = Math.max(MAX_VALUE, maxTX);
105110

106111
const minY = Math.min(MIN_VALUE, minTY);
107112
const maxY = Math.max(MAX_VALUE, maxTY);
108113

114+
const maxDtXCood = xCoord.domain([minDtX, maxDtX]);
109115
xCoord.domain([minX, maxX]);
110116
yCoord.domain([minY, maxY]);
111117

112-
return { xCoord, yCoord };
118+
return { xCoord, yCoord, maxDtXCood };
113119
}
114120

115121
drawLine(data) {
@@ -279,7 +285,7 @@ export class FocusChart extends Component<Props, State> {
279285
zoomValue,
280286
};
281287

282-
this.props.setPeriodRange(periodRange);
288+
this.rangeToTimestamp(periodRange);
283289
}
284290

285291
toggleZoom() {
@@ -292,6 +298,17 @@ export class FocusChart extends Component<Props, State> {
292298
}
293299
}
294300

301+
rangeToTimestamp(periodRange) {
302+
const { zoomValue } = periodRange;
303+
const { maxDtXCood } = this.getScale();
304+
const xCoordCopy = maxDtXCood.copy();
305+
// @ts-ignore
306+
const timeStamp = zoomValue.rescaleX(xCoordCopy.copy()).domain();
307+
const timestampStart = new Date(timeStamp[0]).getTime();
308+
const timestampStop = new Date(timeStamp[1]).getTime();
309+
this.props.setPeriodRange({ ...periodRange, timeStamp: [timestampStart, timestampStop] });
310+
}
311+
295312
updateChartZoomOnSelectPeriod() {
296313
const { width } = this.state;
297314
const focusChartWidth = width - TRANSLATE_LEFT - 2 * CHART_MARGIN;
@@ -302,12 +319,18 @@ export class FocusChart extends Component<Props, State> {
302319

303320
const startRange = xCoord(dateRangeStart * 1000);
304321
const stopRange = xCoord(dateRangeStop * 1000);
305-
306322
const zoomValue = d3.zoomIdentity.scale(focusChartWidth / (stopRange - startRange)).translate(-startRange, 0);
323+
324+
const xCoordCopy = xCoord.copy();
325+
const timeStamp = zoomValue.rescaleX(xCoordCopy).domain();
326+
const timestampStart = new Date(timeStamp[0]).getTime();
327+
const timestampStop = new Date(timeStamp[1]).getTime();
328+
307329
selectedPeriod &&
308330
setPeriodRange({
309331
eventRange: [startRange, stopRange],
310332
zoomValue,
333+
timeStamp: [timestampStart, timestampStop],
311334
});
312335
}
313336

client/src/components/Timeseries/Overview/DrawChart.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,14 @@ export class DrawChart extends Component<ChartProps, ChartState> {
171171

172172
const zoomValue = d3.zoomIdentity.scale(focusWidth / (eventRange[1] - eventRange[0])).translate(-eventRange[0], 0);
173173

174+
const { xCoord } = this.getScale();
175+
const xCoordCopy = xCoord.copy();
176+
const timeStamp = zoomValue.rescaleX(xCoordCopy).domain();
177+
174178
const selectedRange = {
175179
eventRange,
176180
zoomValue,
181+
timeStamp: [new Date(timeStamp[0]).getTime(), new Date(timeStamp[1]).getTime()],
177182
};
178183

179184
if (d3.event && d3.event.sourceEvent.type !== 'zoom') {
@@ -315,7 +320,8 @@ const mapState = (state: RootState) => ({
315320

316321
const mapDispatch = (dispatch: Function) => ({
317322
onSelectDatarun: (datarunID: string) => dispatch(selectDatarun(datarunID)),
318-
onChangePeriod: (period: { eventRange: Array<number>; zoomValue: object }) => dispatch(setTimeseriesPeriod(period)),
323+
onChangePeriod: (period: { eventRange: Array<number>; zoomValue: object; timeStamp: Array<number> }) =>
324+
dispatch(setTimeseriesPeriod(period)),
319325
});
320326

321327
export default connect<StateProps, DispatchProps, {}, RootState>(mapState, mapDispatch)(DrawChart);

client/src/components/Timeseries/Sidebar/Header.jsx

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import {
88
getIsEditingEventRange,
99
getGrouppedDatarunEvents,
1010
getIsEventModeEnabled,
11+
getIsTimeSyncModeEnabled,
1112
} from '../../../model/selectors/datarun';
12-
import { reviewPeriodAction, toggleEventModeAction } from '../../../model/actions/datarun';
13+
import { reviewPeriodAction, toggleEventModeAction, toggleTimeSyncModeAction } from '../../../model/actions/datarun';
1314
import './Header.scss';
1415

1516
const showPeriod = (selectedPeriodLevel) => {
@@ -28,7 +29,7 @@ const showPeriod = (selectedPeriodLevel) => {
2829
);
2930
};
3031

31-
const SidebarHeading = ({ signalName, toggleEvent, isEventModeEnabled }) => (
32+
const SidebarHeading = ({ signalName, toggleEvent, isEventModeEnabled, toggleTimeSync, isTimeSyncEnabled }) => (
3233
<div className="sidebar-heading">
3334
<ul>
3435
<li className="signal-title">{signalName}</li>
@@ -48,6 +49,22 @@ const SidebarHeading = ({ signalName, toggleEvent, isEventModeEnabled }) => (
4849
</div>
4950
</div>
5051
</li>
52+
<li>
53+
<div className="switch-control">
54+
<div className="row">
55+
<label htmlFor="toggleTimeSync">
56+
<input
57+
type="checkbox"
58+
id="toggleTimeSync"
59+
onChange={(event) => toggleTimeSync(event.target.checked)}
60+
checked={isTimeSyncEnabled}
61+
/>
62+
<span className="switch" />
63+
Sync Time Ranges
64+
</label>
65+
</div>
66+
</div>
67+
</li>
5168
</ul>
5269
</div>
5370
);
@@ -61,12 +78,16 @@ const Header = ({
6178
grouppedEvents,
6279
toggleEventsMode,
6380
isEventModeEnabled,
81+
toggleTimeSync,
82+
isTimeSyncEnabled,
6483
}) => (
6584
<div className="period-control">
6685
<SidebarHeading
6786
signalName={dataRun.signal}
6887
toggleEvent={toggleEventsMode}
6988
isEventModeEnabled={isEventModeEnabled}
89+
toggleTimeSync={toggleTimeSync}
90+
isTimeSyncEnabled={isTimeSyncEnabled}
7091
/>
7192
<EventSummary selectedPeriodLevel={selectedPeriodLevel} grouppedEvents={grouppedEvents} />
7293
<div>
@@ -75,6 +96,7 @@ const Header = ({
7596
<li>
7697
<button
7798
type="button"
99+
disabled={isTimeSyncEnabled}
78100
onClick={() => !isEditingEventRange && setReviewRange('year')}
79101
className={reviewRange === 'year' || reviewRange === null ? 'active' : ''}
80102
>
@@ -86,7 +108,7 @@ const Header = ({
86108
type="button"
87109
onClick={() => !isEditingEventRange && setReviewRange('month')}
88110
className={reviewRange === 'month' ? 'active' : ''}
89-
disabled={reviewRange === null}
111+
disabled={reviewRange === null || isTimeSyncEnabled}
90112
>
91113
Month
92114
</button>
@@ -96,7 +118,7 @@ const Header = ({
96118
type="button"
97119
onClick={() => !isEditingEventRange && setReviewRange('day')}
98120
className={reviewRange === 'day' ? 'active' : ''}
99-
disabled={reviewRange === null || selectedPeriodLevel.month === ''}
121+
disabled={reviewRange === null || selectedPeriodLevel.month === '' || isTimeSyncEnabled}
100122
>
101123
Day
102124
</button>
@@ -115,9 +137,11 @@ export default connect(
115137
isEditingEventRange: getIsEditingEventRange(state),
116138
grouppedEvents: getGrouppedDatarunEvents(state),
117139
isEventModeEnabled: getIsEventModeEnabled(state),
140+
isTimeSyncEnabled: getIsTimeSyncModeEnabled(state),
118141
}),
119142
(dispatch) => ({
120143
setReviewRange: (periodLevel) => dispatch(reviewPeriodAction(periodLevel)),
121144
toggleEventsMode: (mode) => dispatch(toggleEventModeAction(mode)),
145+
toggleTimeSync: (mode) => dispatch(toggleTimeSyncModeAction(mode)),
122146
}),
123147
)(Header);

client/src/components/Timeseries/Sidebar/Header.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
}
77

88
li{
9-
margin-right: 15px;
9+
margin-right: 10px;
1010
vertical-align: middle;
1111
&.signal-title{
1212
font-size: 20px;

client/src/components/Timeseries/Sidebar/Sidebar.scss

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,10 @@
6464
background: $btn-blue;
6565
color: #fff;
6666
}
67-
&:disabled{
67+
&:disabled, &.active:disabled{
6868
opacity: 0.4;
69+
background-color: rgba(0, 0, 0, 0.4);
70+
color: rgba(255, 255, 255, 0.5);
6971
cursor: not-allowed;
7072
}
7173
}

client/src/components/Timeseries/Sidebar/index.jsx

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class Sidebar extends Component {
6060

6161
setGlyphRadius() {
6262
const { width, rowSpacing } = this.state;
63-
const { nCols } = this.getColAmount();
63+
const nCols = this.getColAmount();
6464
const { dataRun } = this.props;
6565
const { period } = dataRun;
6666
const { colSpacing } = this.getColSpacing(period);
@@ -70,7 +70,7 @@ class Sidebar extends Component {
7070
let height = nRows * (radius * 2 + rowSpacing);
7171

7272
if (period[0].level === 'day') {
73-
height += radius * 3 + rowSpacing;
73+
height += radius * 3.4 + rowSpacing;
7474
}
7575

7676
this.setState({
@@ -82,7 +82,7 @@ class Sidebar extends Component {
8282

8383
getFeatureCellCoords(currentPeriod, index) {
8484
const { width, colSpacing, rowSpacing, radius } = this.state;
85-
const { nCols } = this.getColAmount();
85+
const nCols = this.getColAmount();
8686
const glyphCell = width / nCols;
8787
const colIteration = index % nCols > 0 ? index % nCols : 0;
8888
const rowIteration = Math.floor(index / nCols);
@@ -107,29 +107,19 @@ class Sidebar extends Component {
107107
}
108108

109109
getColAmount() {
110-
const { selectedPeriodLevel, reviewRange } = this.props;
110+
const { dataRun } = this.props;
111+
const { period } = dataRun;
111112

112-
let nCols = 3;
113-
if (!reviewRange) {
114-
if (selectedPeriodLevel.year) {
115-
nCols = 4;
116-
}
117-
if (selectedPeriodLevel.month) {
118-
nCols = 7;
119-
}
120-
} else {
121-
if (reviewRange === 'year') {
122-
nCols = 3;
123-
}
124-
if (reviewRange === 'month') {
125-
nCols = 4;
126-
}
127-
if (reviewRange === 'day') {
128-
nCols = 7;
129-
}
130-
}
113+
const { level } = period[0];
131114

132-
return { nCols };
115+
switch (level) {
116+
case 'month':
117+
return 4;
118+
case 'day':
119+
return 7;
120+
default:
121+
return 3;
122+
}
133123
}
134124

135125
drawData() {
@@ -192,7 +182,7 @@ class Sidebar extends Component {
192182
const { period } = dataRun;
193183
const { width } = this.state;
194184
const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
195-
const { nCols } = this.getColAmount();
185+
const nCols = this.getColAmount();
196186
const cellWidth = width / nCols;
197187

198188
return (

client/src/model/actions/datarun.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
TOGGLE_EVENT_MODE,
3535
UPLOAD_JSON_EVENTS,
3636
EVENT_UPDATE_STATUS,
37+
TOGGLE_TIME_SYNC_RANGE,
3738
} from '../types';
3839

3940
export function selectDatarun(datarunID: string) {
@@ -53,7 +54,11 @@ export function selectDatarun(datarunID: string) {
5354
};
5455
}
5556

56-
export function setTimeseriesPeriod(eventRange: { eventRange: any; zoomValue: any }) {
57+
export function setTimeseriesPeriod(eventRange: {
58+
eventRange: Array<number>;
59+
zoomValue: any;
60+
timeStamp: Array<number>;
61+
}) {
5762
return function (dispatch, getState) {
5863
const currentRange = getSelectedPeriodRange(getState());
5964
if (JSON.stringify(eventRange.eventRange) === JSON.stringify(currentRange.eventRange)) {
@@ -126,6 +131,15 @@ export function toggleEventModeAction(mode) {
126131
};
127132
}
128133

134+
export function toggleTimeSyncModeAction(syncMode) {
135+
return function (dispatch) {
136+
dispatch({
137+
type: TOGGLE_TIME_SYNC_RANGE,
138+
isTimeSyncModeEnabled: syncMode,
139+
});
140+
};
141+
}
142+
129143
export function updateEventDetailsAction(updatedEventDetails) {
130144
return function (dispatch, getState) {
131145
const isAddingNewEvent = getIsAddingNewEvents(getState());

client/src/model/actions/landing.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
FecthDatarunsByExperimentIDAction,
2020
SELECT_DATARUN,
2121
FETCH_EXPERIMENT_DATA,
22+
SET_TIMESERIES_PERIOD,
2223
} from '../types';
2324

2425
export function fetchExperiments() {
@@ -120,6 +121,16 @@ export function selectExperiment(history: any, experimentID: string) {
120121
type: SELECT_DATARUN,
121122
datarunID: '',
122123
});
124+
125+
dispatch(action);
126+
dispatch({
127+
type: SET_TIMESERIES_PERIOD,
128+
eventRange: {
129+
eventRange: [0, 0],
130+
timeStamp: [0, 0],
131+
zoomValue: 1,
132+
},
133+
});
123134
return dispatch(fetchDatarunsByExperimentID());
124135
};
125136
}

0 commit comments

Comments
 (0)