Skip to content

Commit 3bc8bed

Browse files
authored
Merge pull request #126 from BHP-DevHub/master
Release v1.0.7
2 parents c761503 + ff420b4 commit 3bc8bed

File tree

5 files changed

+75
-113
lines changed

5 files changed

+75
-113
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-timeline-9000",
3-
"version": "1.0.6",
3+
"version": "1.0.7",
44
"description": "Performance focused timeline for react",
55
"private": false,
66
"scripts": {

src/components/timebar.js

Lines changed: 61 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -131,107 +131,50 @@ export default class Timebar extends React.Component {
131131
let timeIncrements = [];
132132
let pixelsLeft = width;
133133
let labelSizeLimit = 60;
134-
if (resolution.type === 'year') {
134+
135+
function _addTimeIncrement(initialOffset, offsetType, stepFunc) {
136+
let offset = null;
135137
while (currentDate.isBefore(end) && pixelsLeft > 0) {
136-
let offset = 0;
137138
// if this is the first 'block' it may be cut off at the start
138139
if (pixelsLeft === width) {
139-
offset = currentDate.month(); // month
140-
}
141-
let pixelIncrements = Math.min(this.getPixelIncrement(currentDate, resolution.type, offset), pixelsLeft);
142-
const labelSize = pixelIncrements < labelSizeLimit ? 'short' : 'long';
143-
let label = currentDate.format(resolution.format[labelSize]);
144-
let isSelected = _.some(selectedRanges, s => {
145-
return (
146-
currentDate.isSameOrAfter(s.start.clone().startOf('year')) &&
147-
currentDate.isSameOrBefore(s.end.clone().startOf('year'))
148-
);
149-
});
150-
timeIncrements.push({label, isSelected, size: pixelIncrements, key: pixelsLeft});
151-
currentDate.add(1, 'year').add(-1 * offset, 'months');
152-
pixelsLeft -= pixelIncrements;
153-
}
154-
}
155-
if (resolution.type === 'month') {
156-
while (currentDate.isBefore(end) && pixelsLeft > 0) {
157-
let offset = 0;
158-
if (pixelsLeft === width) {
159-
offset = currentDate.date() - 1; // day of month [date is 1 indexed]
140+
offset = initialOffset;
141+
} else {
142+
offset = moment.duration(0);
160143
}
161-
let pixelIncrements = Math.min(this.getPixelIncrement(currentDate, resolution.type, offset), pixelsLeft);
144+
let pixelIncrements = Math.min(
145+
this.getPixelIncrement(currentDate, resolution.type, offset.as(offsetType)),
146+
pixelsLeft
147+
);
162148
const labelSize = pixelIncrements < labelSizeLimit ? 'short' : 'long';
163149
let label = currentDate.format(resolution.format[labelSize]);
164150
let isSelected = _.some(selectedRanges, s => {
165151
return (
166-
currentDate.isSameOrAfter(s.start.clone().startOf('month')) &&
167-
currentDate.isSameOrBefore(s.end.clone().startOf('month'))
152+
currentDate.isSameOrAfter(s.start.clone().startOf(resolution.type)) &&
153+
currentDate.isSameOrBefore(s.end.clone().startOf(resolution.type))
168154
);
169155
});
170156
timeIncrements.push({label, isSelected, size: pixelIncrements, key: pixelsLeft});
171-
currentDate.add(-1 * offset, 'days').add(1, 'month');
157+
stepFunc(currentDate, offset);
172158
pixelsLeft -= pixelIncrements;
173159
}
174160
}
175-
if (resolution.type === 'day') {
176-
let offset = 0;
177-
// if this is the first 'block' it may be cut off at the start
178-
if (pixelsLeft === width) {
179-
offset = currentDate.hour(); // hour of day
180-
}
181-
let pixelIncrements = Math.min(this.getPixelIncrement(currentDate, resolution.type, offset), pixelsLeft);
182-
const labelSize = pixelIncrements < labelSizeLimit ? 'short' : 'long';
183-
while (currentDate.isBefore(end) && pixelsLeft > 0) {
184-
let label = currentDate.format(resolution.format[labelSize]);
185-
let isSelected = _.some(selectedRanges, s => {
186-
return (
187-
currentDate.isSameOrAfter(s.start.clone().startOf('day')) &&
188-
currentDate.isSameOrBefore(s.end.clone().startOf('day'))
189-
);
190-
});
191-
timeIncrements.push({label, isSelected, size: pixelIncrements, key: pixelsLeft});
192-
currentDate.add(1, 'days').add(-1 * offset, 'hours');
193-
pixelsLeft -= pixelIncrements;
194-
}
161+
162+
const addTimeIncrement = _addTimeIncrement.bind(this);
163+
164+
if (resolution.type === 'year') {
165+
const offset = moment.duration(currentDate.diff(currentDate.clone().startOf('year')));
166+
addTimeIncrement(offset, 'months', (currentDt, offst) => currentDt.subtract(offst).add(1, 'year'));
167+
} else if (resolution.type === 'month') {
168+
const offset = moment.duration(currentDate.diff(currentDate.clone().startOf('month')));
169+
addTimeIncrement(offset, 'days', (currentDt, offst) => currentDt.subtract(offst).add(1, 'month'));
170+
} else if (resolution.type === 'day') {
171+
const offset = moment.duration(currentDate.diff(currentDate.clone().startOf('day')));
172+
addTimeIncrement(offset, 'hours', (currentDt, offst) => currentDt.subtract(offst).add(1, 'days'));
195173
} else if (resolution.type === 'hour') {
196-
let offset = 0;
197-
// if this is the first 'block' it may be cut off at the start
198-
if (pixelsLeft === width) {
199-
offset = currentDate.minute(); // minute of hour
200-
}
201-
let pixelIncrements = Math.min(this.getPixelIncrement(currentDate, resolution.type, offset), pixelsLeft);
202-
const labelSize = pixelIncrements < labelSizeLimit ? 'short' : 'long';
203-
while (currentDate.isBefore(end) && pixelsLeft > 0) {
204-
let label = currentDate.format(resolution.format[labelSize]);
205-
let isSelected = _.some(selectedRanges, s => {
206-
return (
207-
currentDate.isSameOrAfter(s.start.clone().startOf('hour')) &&
208-
currentDate.isSameOrBefore(s.end.clone().startOf('hour'))
209-
);
210-
});
211-
timeIncrements.push({label, isSelected, size: pixelIncrements, key: pixelsLeft});
212-
currentDate.add(1, 'hours').add(-1 * offset, 'minutes');
213-
pixelsLeft -= pixelIncrements;
214-
}
174+
const offset = moment.duration(currentDate.diff(currentDate.clone().startOf('hour')));
175+
addTimeIncrement(offset, 'minutes', (currentDt, offst) => currentDt.subtract(offst).add(1, 'hours'));
215176
} else if (resolution.type === 'minute') {
216-
let pixelIncrements = Math.min(this.getPixelIncrement(currentDate, resolution.type), pixelsLeft);
217-
const labelSize = pixelIncrements < labelSizeLimit ? 'short' : 'long';
218-
while (currentDate.isBefore(end) && pixelsLeft > 0) {
219-
let label = currentDate.format(resolution.format[labelSize]);
220-
let isSelected = _.some(selectedRanges, s => {
221-
return (
222-
currentDate.isSameOrAfter(s.start.clone().startOf('minute')) &&
223-
currentDate.isSameOrBefore(s.end.clone().startOf('minute'))
224-
);
225-
});
226-
timeIncrements.push({
227-
label,
228-
isSelected,
229-
size: pixelIncrements,
230-
key: pixelsLeft
231-
});
232-
currentDate.add(1, 'minutes');
233-
pixelsLeft -= pixelIncrements;
234-
}
177+
addTimeIncrement(moment.duration(0), 'minutes', (currentDt, offst) => currentDt.add(1, 'minutes'));
235178
}
236179
return timeIncrements;
237180
}
@@ -244,6 +187,7 @@ export default class Timebar extends React.Component {
244187
const {cursorTime} = this.props;
245188
const topBarComponent = this.renderTopBar();
246189
const bottomBarComponent = this.renderBottomBar();
190+
const GroupTitleRenderer = this.props.groupTitleRenderer;
247191

248192
// Only show the cursor on 1 of the top bar segments
249193
// Pick the segment that has the biggest size
@@ -253,32 +197,37 @@ export default class Timebar extends React.Component {
253197
else if (topBarComponent.length > 0) topBarCursorKey = topBarComponent[0].key;
254198

255199
return (
256-
<div className="rct9k-timebar-outer" style={{width: this.props.width, paddingLeft: this.props.leftOffset}}>
257-
<div className="rct9k-timebar-inner rct9k-timebar-inner-top">
258-
{_.map(topBarComponent, i => {
259-
let topLabel = i.label;
260-
if (cursorTime && i.key === topBarCursorKey) {
261-
topLabel += ` [${cursorTime}]`;
262-
}
263-
let className = 'rct9k-timebar-item';
264-
if (i.isSelected) className += ' rct9k-timebar-item-selected';
265-
return (
266-
<span className={className} key={i.key} style={{width: intToPix(i.size)}}>
267-
{topLabel}
268-
</span>
269-
);
270-
})}
200+
<div>
201+
<div className="rct9k-timebar-group-title" style={{width: this.props.leftOffset}}>
202+
<GroupTitleRenderer />
271203
</div>
272-
<div className="rct9k-timebar-inner rct9k-timebar-inner-bottom">
273-
{_.map(bottomBarComponent, i => {
274-
let className = 'rct9k-timebar-item';
275-
if (i.isSelected) className += ' rct9k-timebar-item-selected';
276-
return (
277-
<span className={className} key={i.key} style={{width: intToPix(i.size)}}>
278-
{i.label}
279-
</span>
280-
);
281-
})}
204+
<div className="rct9k-timebar-outer" style={{width: this.props.width, paddingLeft: this.props.leftOffset}}>
205+
<div className="rct9k-timebar-inner rct9k-timebar-inner-top">
206+
{_.map(topBarComponent, i => {
207+
let topLabel = i.label;
208+
if (cursorTime && i.key === topBarCursorKey) {
209+
topLabel += ` [${cursorTime}]`;
210+
}
211+
let className = 'rct9k-timebar-item';
212+
if (i.isSelected) className += ' rct9k-timebar-item-selected';
213+
return (
214+
<span className={className} key={i.key} style={{width: intToPix(i.size)}}>
215+
{topLabel}
216+
</span>
217+
);
218+
})}
219+
</div>
220+
<div className="rct9k-timebar-inner rct9k-timebar-inner-bottom">
221+
{_.map(bottomBarComponent, i => {
222+
let className = 'rct9k-timebar-item';
223+
if (i.isSelected) className += ' rct9k-timebar-item-selected';
224+
return (
225+
<span className={className} key={i.key} style={{width: intToPix(i.size)}}>
226+
{i.label}
227+
</span>
228+
);
229+
})}
230+
</div>
282231
</div>
283232
</div>
284233
);
@@ -287,6 +236,7 @@ export default class Timebar extends React.Component {
287236

288237
Timebar.propTypes = {
289238
cursorTime: PropTypes.any,
239+
groupTitleRenderer: PropTypes.func,
290240
start: PropTypes.object.isRequired, //moment
291241
end: PropTypes.object.isRequired, //moment
292242
width: PropTypes.number.isRequired,
@@ -298,6 +248,7 @@ Timebar.propTypes = {
298248
};
299249
Timebar.defaultProps = {
300250
selectedRanges: [],
251+
groupTitleRenderer: () => <div />,
301252
leftOffset: 0,
302253
timeFormats: defaultTimebarFormat
303254
};

src/demo.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ export default class DemoTimeline extends Component {
329329
onRowDoubleClick={this.handleRowDoubleClick}
330330
itemRenderer={useCustomRenderers ? customItemRenderer : undefined}
331331
groupRenderer={useCustomRenderers ? customGroupRenderer : undefined}
332+
groupTitleRenderer={useCustomRenderers ? () => <div>Group title</div> : undefined}
332333
/>
333334
</Layout.Content>
334335
</Layout>

src/style.css

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
position: absolute;
2929
width: 2px;
3030
background: red;
31-
pointer-events: none
31+
pointer-events: none;
3232
}
3333
.rct9k-row {
3434
/* white-space: nowrap; */
@@ -85,8 +85,15 @@
8585
background-color: lightblue;
8686
}
8787

88+
.rct9k-timebar-group-title {
89+
display: inline-block;
90+
position: absolute;
91+
height: 4em;
92+
}
93+
8894
/* Multi-select box */
8995
.rct9k-selector-outer {
96+
display: inline-block;
9097
background-color: #5bb3ff80;
9198
width: 1px;
9299
height: 1px;

src/timeline.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export default class Timeline extends React.Component {
5757
onRowDoubleClick: PropTypes.func,
5858
itemRenderer: PropTypes.func,
5959
groupRenderer: PropTypes.func,
60+
groupTitleRenderer: PropTypes.func,
6061
onItemHover: PropTypes.func,
6162
onItemLeave: PropTypes.func
6263
};
@@ -70,6 +71,7 @@ export default class Timeline extends React.Component {
7071
showCursorTime: true,
7172
groupRenderer: DefaultGroupRenderer,
7273
itemRenderer: DefaultItemRenderer,
74+
groupTitleRenderer: () => <div />,
7375
timelineMode: Timeline.TIMELINE_MODES.SELECT | Timeline.TIMELINE_MODES.DRAG | Timeline.TIMELINE_MODES.RESIZE,
7476
onItemHover() {},
7577
onItemLeave() {}
@@ -752,7 +754,7 @@ export default class Timeline extends React.Component {
752754
}
753755

754756
render() {
755-
const {onInteraction, groupOffset, timebarFormat, componentId} = this.props;
757+
const {onInteraction, groupOffset, timebarFormat, componentId, groupTitleRenderer} = this.props;
756758

757759
const divCssClass = `rct9k-timeline-div rct9k-id-${componentId}`;
758760
let varTimebarProps = {};
@@ -778,6 +780,7 @@ export default class Timeline extends React.Component {
778780
width={width}
779781
leftOffset={groupOffset}
780782
selectedRanges={this.state.selection}
783+
groupTitleRenderer={groupTitleRenderer}
781784
{...varTimebarProps}
782785
/>
783786
<Grid

0 commit comments

Comments
 (0)