From a803455cb25557667e2adf0574c9fe1f06c9fc98 Mon Sep 17 00:00:00 2001 From: Ahmad Ilaiwi Date: Sun, 14 Oct 2018 11:59:47 +0300 Subject: [PATCH 01/65] add tests --- .../components/Headers/TimelineHeader.test.js | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 __tests__/components/Headers/TimelineHeader.test.js diff --git a/__tests__/components/Headers/TimelineHeader.test.js b/__tests__/components/Headers/TimelineHeader.test.js new file mode 100644 index 000000000..b24c7f824 --- /dev/null +++ b/__tests__/components/Headers/TimelineHeader.test.js @@ -0,0 +1,97 @@ +import { render } from 'react-testing-library' +import Timeline from 'lib/Timeline' +import SidebarHeader from 'lib/headers/SidebarHeader' +import DateHeader from 'lib/headers/DateHeader' +import TimelineHeaders from 'lib/headers/TimelineHeaders' +import 'jest-dom/extend-expect' + +import 'react-testing-library/cleanup-after-each' +import React from 'react' +import moment from 'moment' + +const groups = [ + { id: 2, title: 'group 2' }, + { id: 1, title: 'group 1' }, + { id: 3, title: 'group 3' } +] + +const items = [ + { + id: 1, + group: 1, + title: 'item 1', + start_time: moment('1995-12-25'), + end_time: moment('1995-12-25').add(1, 'hour') + }, + { + id: 2, + group: 2, + title: 'item 2', + start_time: moment('1995-12-25').add(-0.5, 'hour'), + end_time: moment('1995-12-25').add(0.5, 'hour') + }, + { + id: 3, + group: 3, + title: 'item 3', + start_time: moment('1995-12-25').add(2, 'hour'), + end_time: moment('1995-12-25').add(3, 'hour') + } +] + +describe('TimelineHeader', () => { + xit('renders headers correctly', () => { + const container = render( + + ) + }) + it('renders headers in TimelineHeaders correctly', () => { + const { getByText, debug, rerender, getByTestId } = render( + + + + {({ getRootProps }) => { + return
Left
+ }} +
+ + {({ getRootProps }) => { + return
Right
+ }} +
+ +
+
+ ) + expect(getByText('Left')).toBeInTheDocument() + expect(getByTestId('right')).toBeInTheDocument() + rerender( + + + + {({ getRootProps }) => { + return
Left
+ }} +
+ +
+
+ ) + expect(getByTestId('right')).toThrowError() + }) +}) From 048aff28ed336e7da952af1c11ec1259c35aa113 Mon Sep 17 00:00:00 2001 From: Ahmad Ilaiwi Date: Thu, 18 Oct 2018 16:01:19 +0300 Subject: [PATCH 02/65] fix TimelineHeader tests + add error to getNextUnit helper --- .../components/Headers/TimelineHeader.test.js | 14 +-- __tests__/utils/calendar/get-next-unit.js | 9 +- package.json | 4 +- src/lib/headers/DateHeader.js | 3 +- src/lib/headers/HeadersContext.js | 2 - src/lib/utility/calendar.js | 114 ++++++++++-------- 6 files changed, 75 insertions(+), 71 deletions(-) diff --git a/__tests__/components/Headers/TimelineHeader.test.js b/__tests__/components/Headers/TimelineHeader.test.js index b24c7f824..c48ecc410 100644 --- a/__tests__/components/Headers/TimelineHeader.test.js +++ b/__tests__/components/Headers/TimelineHeader.test.js @@ -1,11 +1,10 @@ -import { render } from 'react-testing-library' +import { render, cleanup } from 'react-testing-library' import Timeline from 'lib/Timeline' import SidebarHeader from 'lib/headers/SidebarHeader' import DateHeader from 'lib/headers/DateHeader' import TimelineHeaders from 'lib/headers/TimelineHeaders' import 'jest-dom/extend-expect' -import 'react-testing-library/cleanup-after-each' import React from 'react' import moment from 'moment' @@ -39,8 +38,9 @@ const items = [ } ] -describe('TimelineHeader', () => { - xit('renders headers correctly', () => { +describe('TimelineHeader', () => { + afterEach(cleanup) + it('renders headers correctly', () => { const container = render( { ) }) it('renders headers in TimelineHeaders correctly', () => { - const { getByText, debug, rerender, getByTestId } = render( + const { getByText, debug, rerender, queryByTestId } = render( { ) expect(getByText('Left')).toBeInTheDocument() - expect(getByTestId('right')).toBeInTheDocument() + expect(queryByTestId('right')).toBeInTheDocument() rerender( { ) - expect(getByTestId('right')).toThrowError() + expect(queryByTestId('right')).toBeNull() }) }) diff --git a/__tests__/utils/calendar/get-next-unit.js b/__tests__/utils/calendar/get-next-unit.js index 40b19bb81..c594bc890 100644 --- a/__tests__/utils/calendar/get-next-unit.js +++ b/__tests__/utils/calendar/get-next-unit.js @@ -23,12 +23,11 @@ describe('getNextUnit', () => { const result = getNextUnit('month') expect(result).toBe('year') }) - it('year to empty string', () => { + it('year to year', () => { const result = getNextUnit('year') - expect(result).toBe('') + expect(result).toBe('year') }) - it('unknown value to empty string', () => { - const result = getNextUnit('foo') - expect(result).toBe('') + it('unknown value to throw error', () => { + expect(getNextUnit('foo')).toThrowErrorMatchingSnapshot() }) }) diff --git a/package.json b/package.json index 6b147f456..32904d417 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "url": "https://github.com/dkarnutsch" }, { - "name":"Alex Maclean", + "name": "Alex Maclean", "url": "https://github.com/acemac" }, { @@ -126,7 +126,7 @@ "eslint-plugin-standard": "^2.0.1", "faker": "^4.1.0", "interactjs": "^1.3.4", - "jest": "^23.1.0", + "jest": "^23.6.0", "jest-dom": "^1.12.1", "jest-watch-typeahead": "^0.1.0", "jsdom": "^11.5.1", diff --git a/src/lib/headers/DateHeader.js b/src/lib/headers/DateHeader.js index 7afb326dd..29f33b49a 100644 --- a/src/lib/headers/DateHeader.js +++ b/src/lib/headers/DateHeader.js @@ -28,9 +28,8 @@ class DateHeader extends React.Component { return this.props.unit } else if (this.props.primaryHeader) { return getNextUnit(this.props.timelineUnit) - } else { - return this.props.timelineUnit } + return this.props.timelineUnit } render() { diff --git a/src/lib/headers/HeadersContext.js b/src/lib/headers/HeadersContext.js index 5bcc61053..d2a6830fe 100644 --- a/src/lib/headers/HeadersContext.js +++ b/src/lib/headers/HeadersContext.js @@ -2,8 +2,6 @@ import React from 'react' import PropTypes from 'prop-types' import createReactContext from 'create-react-context' import { noop } from '../utility/generic' -import { LEFT_SIDEBAR_ID, RIGHT_SIDEBAR_ID } from './constants' -import { getNextUnit } from '../utility/calendar' const defaultContextState = { registerScroll: () => { diff --git a/src/lib/utility/calendar.js b/src/lib/utility/calendar.js index 947ef01c9..c431ba3c4 100644 --- a/src/lib/utility/calendar.js +++ b/src/lib/utility/calendar.js @@ -64,7 +64,7 @@ export function iterateTimes(start, end, unit, timeSteps, callback) { if (timeSteps[unit] && timeSteps[unit] > 1) { let value = time.get(unit) - time.set(unit, value - value % timeSteps[unit]) + time.set(unit, value - (value % timeSteps[unit])) } while (time.valueOf() < end) { @@ -148,10 +148,13 @@ export function getNextUnit(unit) { minute: 'hour', hour: 'day', day: 'month', - month: 'year' + month: 'year', + year: 'year' } - - return nextUnits[unit] || '' + if (!nextUnits[unit]) { + throw new Error(`unit ${unit} in not acceptable`) + } + return nextUnits[unit] } export function calculateDimensions({ @@ -258,7 +261,7 @@ export function stack(items, groupOrders, lineHeight, groups) { var groupedItems = getGroupedItems(items, groupOrders) groupedItems.forEach(function(group) { - var groupVal = groups[k++]; + var groupVal = groups[k++] // calculate new, non-overlapping positions groupTops.push(totalHeight) @@ -317,7 +320,9 @@ export function stack(items, groupOrders, lineHeight, groups) { } export function nostack(items, groupOrders, lineHeight, groups) { - var i, j=0, iMax + var i, + j = 0, + iMax var totalHeight = 0 @@ -327,7 +332,7 @@ export function nostack(items, groupOrders, lineHeight, groups) { var groupedItems = getGroupedItems(items, groupOrders) groupedItems.forEach(function(group) { - var groupVal = groups[j++]; + var groupVal = groups[j++] // calculate new, non-overlapping positions groupTops.push(totalHeight) @@ -344,8 +349,8 @@ export function nostack(items, groupOrders, lineHeight, groups) { } if (groupVal.height) { - groupHeights.push(groupVal.height); - totalHeight += groupVal.height; + groupHeights.push(groupVal.height) + totalHeight += groupVal.height } else { groupHeights.push(Math.max(groupHeight, lineHeight)) totalHeight += Math.max(groupHeight, lineHeight) @@ -361,24 +366,24 @@ export function nostack(items, groupOrders, lineHeight, groups) { /** * Stack the items that will be visible * within the canvas area - * @param {item[]} items - * @param {group[]} groups - * @param {number} canvasTimeStart - * @param {number} visibleTimeStart - * @param {number} visibleTimeEnd - * @param {number} width - * @param {*} props - * @param {*} state + * @param {item[]} items + * @param {group[]} groups + * @param {number} canvasTimeStart + * @param {number} visibleTimeStart + * @param {number} visibleTimeEnd + * @param {number} width + * @param {*} props + * @param {*} state */ export function stackItems( -items, -groups, -canvasTimeStart, -visibleTimeStart, -visibleTimeEnd, -width, -props, -state + items, + groups, + canvasTimeStart, + visibleTimeStart, + visibleTimeEnd, + width, + props, + state ) { // if there are no groups return an empty array of dimensions if (groups.length === 0) { @@ -416,13 +421,11 @@ state // Get the order of groups based on their id key const groupOrders = getGroupOrders(groups, keys) - let dimensionItems = visibleItems.reduce((memo, item) => { const itemId = _get(item, keys.itemIdKey) const isDragging = itemId === draggingItem const isResizing = itemId === resizingItem - let dimension = calculateDimensions({ itemTimeStart: _get(item, keys.itemTimeStartKey), itemTimeEnd: _get(item, keys.itemTimeEndKey), @@ -471,22 +474,23 @@ state * Get the the canvas area for a given visible time * Will shift the start/end of the canvas if the visible time * does not fit within the existing - * @param {number} visibleTimeStart - * @param {number} visibleTimeEnd - * @param {boolean} forceUpdateDimensions - * @param {*} items - * @param {*} groups - * @param {*} props - * @param {*} state + * @param {number} visibleTimeStart + * @param {number} visibleTimeEnd + * @param {boolean} forceUpdateDimensions + * @param {*} items + * @param {*} groups + * @param {*} props + * @param {*} state */ export function calculateScrollCanvas( -visibleTimeStart, -visibleTimeEnd, -forceUpdateDimensions, -items, -groups, -props, -state) { + visibleTimeStart, + visibleTimeEnd, + forceUpdateDimensions, + items, + groups, + props, + state +) { const oldCanvasTimeStart = state.canvasTimeStart const oldZoom = state.visibleTimeEnd - state.visibleTimeStart @@ -498,20 +502,24 @@ state) { visibleTimeStart <= oldCanvasTimeStart + oldZoom * 1.5 && visibleTimeEnd >= oldCanvasTimeStart + oldZoom * 1.5 && visibleTimeEnd <= oldCanvasTimeStart + oldZoom * 2.5 - + if (!canKeepCanvas || forceUpdateDimensions) { - newState.canvasTimeStart = visibleTimeStart - (visibleTimeEnd - visibleTimeStart) + newState.canvasTimeStart = + visibleTimeStart - (visibleTimeEnd - visibleTimeStart) // The canvas cannot be kept, so calculate the new items position - Object.assign(newState, stackItems( - items, - groups, - newState.canvasTimeStart, - visibleTimeStart, - visibleTimeEnd, - state.width, - props, - state - )) + Object.assign( + newState, + stackItems( + items, + groups, + newState.canvasTimeStart, + visibleTimeStart, + visibleTimeEnd, + state.width, + props, + state + ) + ) } return newState } From 15a7a5358394c5290e03435fc998ceb6229837a8 Mon Sep 17 00:00:00 2001 From: ilaiwi Date: Fri, 19 Oct 2018 15:11:18 +0300 Subject: [PATCH 03/65] add error snapshot --- __tests__/utils/calendar/__snapshots__/get-next-unit.js.snap | 3 +++ __tests__/utils/calendar/get-next-unit.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 __tests__/utils/calendar/__snapshots__/get-next-unit.js.snap diff --git a/__tests__/utils/calendar/__snapshots__/get-next-unit.js.snap b/__tests__/utils/calendar/__snapshots__/get-next-unit.js.snap new file mode 100644 index 000000000..b56de34c6 --- /dev/null +++ b/__tests__/utils/calendar/__snapshots__/get-next-unit.js.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`getNextUnit unknown value to throw error 1`] = `"unit foo in not acceptable"`; diff --git a/__tests__/utils/calendar/get-next-unit.js b/__tests__/utils/calendar/get-next-unit.js index c594bc890..306e4353f 100644 --- a/__tests__/utils/calendar/get-next-unit.js +++ b/__tests__/utils/calendar/get-next-unit.js @@ -28,6 +28,6 @@ describe('getNextUnit', () => { expect(result).toBe('year') }) it('unknown value to throw error', () => { - expect(getNextUnit('foo')).toThrowErrorMatchingSnapshot() + expect(() => getNextUnit('foo')).toThrowErrorMatchingSnapshot() }) }) From e4381a7ed3d375c744571ace48eb8fe6a7df08d4 Mon Sep 17 00:00:00 2001 From: ilaiwi Date: Sat, 20 Oct 2018 21:44:51 +0300 Subject: [PATCH 04/65] add tests senarios --- .../components/Headers/TimelineHeader.test.js | 43 +++++++++++++------ src/lib/headers/DateHeader.js | 1 + src/lib/headers/SidebarHeader.js | 2 +- src/lib/headers/TimelineHeaders.js | 1 + 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/__tests__/components/Headers/TimelineHeader.test.js b/__tests__/components/Headers/TimelineHeader.test.js index c48ecc410..edce0f09e 100644 --- a/__tests__/components/Headers/TimelineHeader.test.js +++ b/__tests__/components/Headers/TimelineHeader.test.js @@ -38,20 +38,27 @@ const items = [ } ] -describe('TimelineHeader', () => { +const defaultProps = { + groups, + items, + defaultTimeStart: moment('1995-12-25').add(-12, 'hour'), + defaultTimeEnd: moment('1995-12-25').add(12, 'hour') +} + +describe('TimelineHeader', () => { afterEach(cleanup) - it('renders headers correctly', () => { - const container = render( - - ) + describe('renders default headers correctly', () => { + it('renders two dateHeaders by default', () => { + const { getAllByTestId, getByTestId } = renderDefaultTimeline() + expect(getAllByTestId('dateHeader')).toHaveLength(2) + expect(getByTestId('headerContainer').children).toHaveLength(2) + }) + it('renders default sidebar header', () => {}) + it('renders two default sidebar headers if rightSidebarWidth is passed', () => {}) + it('renders two dateHeaders one primary and one secondary', () => {}) }) it('renders headers in TimelineHeaders correctly', () => { - const { getByText, debug, rerender, queryByTestId } = render( + const { getByText, rerender, queryByTestId } = render( { {({ getRootProps }) => { - return
Right
+ return ( +
+ Right +
+ ) }}
@@ -95,3 +106,11 @@ describe('TimelineHeader', () => { expect(queryByTestId('right')).toBeNull() }) }) + +function renderDefaultTimeline(props = {}) { + const timelineProps = { + ...defaultProps, + ...props + } + return render() +} diff --git a/src/lib/headers/DateHeader.js b/src/lib/headers/DateHeader.js index 29f33b49a..4f85ffeae 100644 --- a/src/lib/headers/DateHeader.js +++ b/src/lib/headers/DateHeader.js @@ -47,6 +47,7 @@ class DateHeader extends React.Component { return (
diff --git a/src/lib/headers/SidebarHeader.js b/src/lib/headers/SidebarHeader.js index 840f1d54b..3ad4aa603 100644 --- a/src/lib/headers/SidebarHeader.js +++ b/src/lib/headers/SidebarHeader.js @@ -62,7 +62,7 @@ SidebarWrapper.propTypes = { SidebarWrapper.defaultProps = { variant: LEFT_VARIANT, - children: ({ getRootProps }) =>
+ children: ({ getRootProps }) =>
} export default SidebarWrapper diff --git a/src/lib/headers/TimelineHeaders.js b/src/lib/headers/TimelineHeaders.js index 7dc24530c..ce5a12638 100644 --- a/src/lib/headers/TimelineHeaders.js +++ b/src/lib/headers/TimelineHeaders.js @@ -71,6 +71,7 @@ class TimelineHeaders extends React.Component { ref={this.props.registerScroll} style={this.getCalendarHeaderStyle()} className={this.props.calendarHeaderClassName} + data-testid="headerContainer" > {calendarHeaders}
From bf5b9dcfe5553d6c3a82f9a7dc11393206147d90 Mon Sep 17 00:00:00 2001 From: ilaiwi Date: Fri, 16 Nov 2018 19:02:32 +0200 Subject: [PATCH 05/65] update codesandbox --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- CHANGELOG.md | 2 ++ examples/README.md | 16 ++++++++-------- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index db4bd8305..21a24e280 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -10,7 +10,7 @@ A clear and concise description of what the bug is. _Please provide one or both of the following:_ -Code (If you have a branch somewhere that shows your issue) or link to codesandbox example. [Here's a base template for this library](https://codesandbox.io/s/lyjr9p0119): +Code (If you have a branch somewhere that shows your issue) or link to codesandbox example. [Here's a base template for this library](https://codesandbox.io/s/w6xvqzno4w): OR diff --git a/CHANGELOG.md b/CHANGELOG.md index 97cb27c0e..3a391f3c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres (more or less) to [Semantic Versioning](http://semver.o ## Unreleased +## 0.22.0 + ### Fixed * Provided a new key `groupLabelKey` to allow splitting of the key used to render the Sidebar and the InfoLabel visible during drag operations. `groupTitleKey` continues to be used to render the Sidebar. #442 @thiagosatoshi diff --git a/examples/README.md b/examples/README.md index c05551b01..13bdcad66 100644 --- a/examples/README.md +++ b/examples/README.md @@ -6,19 +6,19 @@ Below are links to Codesandbox instances for examples of how to use this repo. F Basic functionality of the timeline, included panning, zooming and rendering of items -[Example Codesandbox](https://codesandbox.io/s/zr5r289rm4) +[Example Codesandbox](https://codesandbox.io/s/w6xvqzno4w) ## Item Moving and Resizing Moving and Resizing examples. Clicking and dragging can move items into different groups. Notice the `handleItemMove` and `handleItemResize` handlers passed to the Timeline. -[Example Codesandbox](https://codesandbox.io/s/6vo2jkov23) +[Example Codesandbox](https://codesandbox.io/s/q3rkx1478q) ## Custom Item Rendering The `itemRenderer` component allows you to customize what contents are shown in the item on the calendar. -[Example Codesandbox](https://codesandbox.io/s/1p8m477w7) +[Example Codesandbox](https://codesandbox.io/s/k0wn41y0o7) + +## License +[MIT licensed](/LICENSE.md). From f98c7381c4a3e6ae63d964802cbd59688e650870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20B=C3=BCschel?= Date: Thu, 14 Feb 2019 02:35:54 +0800 Subject: [PATCH 55/65] docs: correct invalid JavaScript syntax in examples --- README.md | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 52b50a5d5..eccc0e3f9 100644 --- a/README.md +++ b/README.md @@ -711,10 +711,10 @@ const twoSeconds = 2000 {({ styles, date }) => - // date is value of current date. Use this to render special styles for the marker - // or any other custom logic based on date: - // e.g. styles = {...styles, backgroundColor: isDateInAfternoon(date) ? 'red' : 'limegreen'} - return
+ // date is value of current date. Use this to render special styles for the marker + // or any other custom logic based on date: + // e.g. styles = {...styles, backgroundColor: isDateInAfternoon(date) ? 'red' : 'limegreen'} +
} ``` @@ -737,9 +737,7 @@ const today = Date.now() //custom renderer - {({ styles, date }) => - return
- } + {({ styles, date }) =>
} // multiple CustomMarkers @@ -769,10 +767,10 @@ Custom renderer for this marker. Ensure that you always pass `styles` to the roo //custom renderer {({ styles, date }) => - // date is value of current date. Use this to render special styles for the marker - // or any other custom logic based on date: - // e.g. styles = {...styles, backgroundColor: isDateInAfternoon(date) ? 'red' : 'limegreen'} - return
+ // date is value of current date. Use this to render special styles for the marker + // or any other custom logic based on date: + // e.g. styles = {...styles, backgroundColor: isDateInAfternoon(date) ? 'red' : 'limegreen'} +
} ``` @@ -785,7 +783,7 @@ You need to include the `Timeline.css` file, either via static file reference or ## How can I have items with different colors? -Now you can use item renderer for rendering items with different colors [itemRenderer](https://github.com/namespace-ee/react-calendar-timeline#itemrenderer). +Now you can use item renderer for rendering items with different colors [itemRenderer](https://github.com/namespace-ee/react-calendar-timeline#itemrenderer). Please refer to [examples](https://github.com/namespace-ee/react-calendar-timeline/tree/master/examples#custom-item-rendering) for a sandbox example ## How can I add a sidebar on the right? From cfe279453de0769589b26a96f2b0fbdb3768922f Mon Sep 17 00:00:00 2001 From: Ilaiwi Date: Tue, 19 Feb 2019 19:06:46 +0200 Subject: [PATCH 56/65] stack --- README.md | 7 +- __fixtures__/stateAndProps.js | 2 +- __tests__/index.js | 2 +- .../__snapshots__/stack-group.js.snap | 14 + __tests__/utils/calendar/stack-group.js | 7 +- demo/app/demo-custom-items/index.js | 2 +- demo/app/demo-element-resize/index.js | 2 +- demo/app/demo-headers/index.js | 405 ++++++++++++++++++ demo/app/demo-linked-timelines/index.js | 4 +- demo/app/demo-main/index.js | 150 ++++++- demo/app/demo-performance/index.js | 2 +- demo/app/demo-renderers/index.js | 2 +- demo/app/demo-sticky-header/index.js | 4 +- demo/app/demo-tree-groups/index.js | 2 +- demo/app/demo-vertical-classes/index.js | 2 +- src/lib/Timeline.js | 2 +- src/lib/utility/calendar.js | 60 ++- 17 files changed, 637 insertions(+), 32 deletions(-) create mode 100644 demo/app/demo-headers/index.js diff --git a/README.md b/README.md index 52b50a5d5..fd2665c0e 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ Expects either a vanilla JS array or an immutableJS array, consisting of objects id: 1, title: 'group 1', rightTitle: 'title in the right sidebar', - stackItems?: true, + stackItems?: false or 'space' or 'line', height?: 30 } ``` @@ -238,6 +238,11 @@ Append a special `.rct-drag-right` handle to the elements and only resize if dra Stack items under each other, so there is no visual overlap when times collide. Can be overridden in the `groups` array. Defaults to `false`. +can be assigned to +- false +- space (saves space in stacking) +- line (stack each item in a line) + ## traditionalZoom Zoom in when scrolling the mouse up/down. Defaults to `false` diff --git a/__fixtures__/stateAndProps.js b/__fixtures__/stateAndProps.js index 20bf62783..6427947ec 100644 --- a/__fixtures__/stateAndProps.js +++ b/__fixtures__/stateAndProps.js @@ -3,7 +3,7 @@ import {items} from './itemsAndGroups' export const props = { keys: defaultKeys, lineHeight: 30, - stackItems: true, + stackItems: 'space', itemHeightRatio: 0.75 } diff --git a/__tests__/index.js b/__tests__/index.js index 3122950ba..b93609565 100644 --- a/__tests__/index.js +++ b/__tests__/index.js @@ -132,7 +132,7 @@ xdescribe('Timeline', () => { diff --git a/__tests__/utils/calendar/__snapshots__/stack-group.js.snap b/__tests__/utils/calendar/__snapshots__/stack-group.js.snap index bbe832509..0438f72d0 100644 --- a/__tests__/utils/calendar/__snapshots__/stack-group.js.snap +++ b/__tests__/utils/calendar/__snapshots__/stack-group.js.snap @@ -13,3 +13,17 @@ Object { "verticalMargin": 7.5, } `; + +exports[`stackGroup should stack list of items lines 1`] = ` +Object { + "groupHeight": 180, + "verticalMargin": 7.5, +} +`; + +exports[`stackGroup should stack list of items space 1`] = ` +Object { + "groupHeight": 0, + "verticalMargin": 7.5, +} +`; diff --git a/__tests__/utils/calendar/stack-group.js b/__tests__/utils/calendar/stack-group.js index be91fa399..678cf455d 100644 --- a/__tests__/utils/calendar/stack-group.js +++ b/__tests__/utils/calendar/stack-group.js @@ -2,8 +2,11 @@ import { stackGroup } from 'lib/utility/calendar' import { dimensionItems } from '../../../__fixtures__/groupOrderAndItemDimentions' describe('stackGroup', ()=>{ - it('should stack list of items', ()=>{ - expect(stackGroup(dimensionItems, true, 30, 0)).toMatchSnapshot() + it('should stack list of items space', ()=>{ + expect(stackGroup(dimensionItems, 'space', 30, 0)).toMatchSnapshot() + }) + it('should stack list of items lines', ()=>{ + expect(stackGroup(dimensionItems, 'lines', 30, 0)).toMatchSnapshot() }) it('should not stack list of items', ()=>{ expect(stackGroup(dimensionItems, false, 30, 0)).toMatchSnapshot() diff --git a/demo/app/demo-custom-items/index.js b/demo/app/demo-custom-items/index.js index 73a3e8d10..bf598b8a9 100644 --- a/demo/app/demo-custom-items/index.js +++ b/demo/app/demo-custom-items/index.js @@ -207,7 +207,7 @@ export default class App extends Component { canSelect itemsSorted itemTouchSendsClick={false} - stackItems + stackItems="space" itemHeightRatio={0.75} lineHeight={40} showCursorLine diff --git a/demo/app/demo-element-resize/index.js b/demo/app/demo-element-resize/index.js index ff25558fe..ca74a17d2 100644 --- a/demo/app/demo-element-resize/index.js +++ b/demo/app/demo-element-resize/index.js @@ -69,7 +69,7 @@ export default class App extends Component { canSelect itemsSorted itemTouchSendsClick={false} - stackItems + stackItems="space" itemHeightRatio={0.75} resizeDetector={containerResizeDetector} defaultTimeStart={defaultTimeStart} diff --git a/demo/app/demo-headers/index.js b/demo/app/demo-headers/index.js new file mode 100644 index 000000000..5d160e6d0 --- /dev/null +++ b/demo/app/demo-headers/index.js @@ -0,0 +1,405 @@ +/* eslint-disable no-console */ +import React, { Component } from 'react' +import moment from 'moment' + +import Timeline, { + TimelineMarkers, + TodayMarker, + CustomMarker, + CursorMarker, + SidebarHeader, + CustomHeader, + TimelineHeaders, + DateHeader, + ItemHeader +} from 'react-calendar-timeline' + +import generateFakeData from '../generate-fake-data' + +var minTime = moment() + .add(-6, 'months') + .valueOf() +var maxTime = moment() + .add(6, 'months') + .valueOf() + +var keys = { + groupIdKey: 'id', + groupTitleKey: 'title', + groupRightTitleKey: 'rightTitle', + itemIdKey: 'id', + itemTitleKey: 'title', + itemDivTitleKey: 'title', + itemGroupKey: 'group', + itemTimeStartKey: 'start', + itemTimeEndKey: 'end' +} + +export default class App extends Component { + constructor(props) { + super(props) + + const { groups, items } = generateFakeData() + const {items: headerItems } = generateFakeData(2, 5, 1) + const defaultTimeStart = moment() + .startOf('day') + .toDate() + const defaultTimeEnd = moment() + .startOf('day') + .add(1, 'day') + .toDate() + + this.state = { + groups, + items, + defaultTimeStart, + defaultTimeEnd, + format: false, + showHeaders: false, + headerItems, + } + } + + handleClick = () => { + this.setState({ format: true }) + } + + handleCanvasClick = (groupId, time) => { + console.log('Canvas clicked', groupId, moment(time).format()) + } + + handleCanvasDoubleClick = (groupId, time) => { + console.log('Canvas double clicked', groupId, moment(time).format()) + } + + handleCanvasContextMenu = (group, time) => { + console.log('Canvas context menu', group, moment(time).format()) + } + + handleItemClick = (itemId, _, time) => { + console.log('Clicked: ' + itemId, moment(time).format()) + } + + handleItemSelect = (itemId, _, time) => { + console.log('Selected: ' + itemId, moment(time).format()) + } + + handleItemDoubleClick = (itemId, _, time) => { + console.log('Double Click: ' + itemId, moment(time).format()) + } + + handleItemContextMenu = (itemId, _, time) => { + console.log('Context Menu: ' + itemId, moment(time).format()) + } + + handleItemMove = (itemId, dragTime, newGroupOrder) => { + const { items, groups } = this.state + + const group = groups[newGroupOrder] + + this.setState({ + items: items.map( + item => + item.id === itemId + ? Object.assign({}, item, { + start: dragTime, + end: dragTime + (item.end - item.start), + group: group.id + }) + : item + ) + }) + + console.log('Moved', itemId, dragTime, newGroupOrder) + } + + handleItemResize = (itemId, time, edge) => { + const { items } = this.state + + this.setState({ + items: items.map( + item => + item.id === itemId + ? Object.assign({}, item, { + start: edge === 'left' ? time : item.start, + end: edge === 'left' ? item.end : time + }) + : item + ) + }) + + console.log('Resized', itemId, time, edge) + } + + // this limits the timeline to -6 months ... +6 months + handleTimeChange = (visibleTimeStart, visibleTimeEnd, updateScrollCanvas) => { + if (visibleTimeStart < minTime && visibleTimeEnd > maxTime) { + updateScrollCanvas(minTime, maxTime) + } else if (visibleTimeStart < minTime) { + updateScrollCanvas(minTime, minTime + (visibleTimeEnd - visibleTimeStart)) + } else if (visibleTimeEnd > maxTime) { + updateScrollCanvas(maxTime - (visibleTimeEnd - visibleTimeStart), maxTime) + } else { + updateScrollCanvas(visibleTimeStart, visibleTimeEnd) + } + } + + moveResizeValidator = (action, item, time) => { + if (time < new Date().getTime()) { + var newTime = + Math.ceil(new Date().getTime() / (15 * 60 * 1000)) * (15 * 60 * 1000) + return newTime + } + + return time + } + + handleClickChangeHeaders = () => { + this.setState(state => ({ + showHeaders: !state.showHeaders + })) + } + + render() { + const { groups, items, defaultTimeStart, defaultTimeEnd } = this.state + + return ( +
+ + + Above The Left
} + canMove + canResize="right" + canSelect + itemsSorted + itemTouchSendsClick={false} + itemHeightRatio={0.75} + defaultTimeStart={defaultTimeStart} + defaultTimeEnd={defaultTimeEnd} + onCanvasClick={this.handleCanvasClick} + onCanvasDoubleClick={this.handleCanvasDoubleClick} + onCanvasContextMenu={this.handleCanvasContextMenu} + onItemClick={this.handleItemClick} + onItemSelect={this.handleItemSelect} + onItemContextMenu={this.handleItemContextMenu} + onItemMove={this.handleItemMove} + onItemResize={this.handleItemResize} + onItemDoubleClick={this.handleItemDoubleClick} + onTimeChange={this.handleTimeChange} + // moveResizeValidator={this.moveResizeValidator} + rightSidebarWidth={150} + rightSidebarContent={
Above The Right
} + stackItems="space" + > + + + {({ getRootProps }) => { + return
Left
+ }} +
+ + {({ getRootProps }) => { + return
Right
+ }} +
+ { + return ( +
+ {item.title} +
+ ) + }} + /> + + + + + + {( + { + headerContext: { intervals }, + getRootProps, + getIntervalProps, + showPeriod + }, + props + ) => { + return ( +
+ {intervals.map(interval => { + const intervalStyle = { + // height: 30, + lineHeight: '30px', + textAlign: 'center', + borderLeft: '1px solid black', + cursor: 'pointer', + backgroundColor: 'Turquoise', + color: 'white' + } + return ( +
{ + showPeriod(interval.startTime, interval.endTime) + }} + {...getIntervalProps({ + interval, + style: intervalStyle + })} + > +
+ {interval.startTime.format('YYYY')} +
+
+ ) + })} +
+ ) + }} +
+ + {({ + headerContext: { intervals }, + getRootProps, + getIntervalProps, + showPeriod + }) => { + return ( +
+ {intervals.map(interval => { + const intervalStyle = { + // height: 30, + lineHeight: '30px', + textAlign: 'center', + borderLeft: '1px solid black', + cursor: 'pointer', + backgroundColor: 'indianred', + color: 'white' + } + return ( +
{ + showPeriod(interval.startTime, interval.endTime) + }} + {...getIntervalProps({ + interval, + style: intervalStyle + })} + > +
+ {interval.startTime.format('MM/DD')} +
+
+ ) + })} +
+ ) + }} +
+ + {({ + headerContext: { intervals }, + getRootProps, + getIntervalProps, + showPeriod + }) => { + return ( +
+ {intervals.map(interval => { + const intervalStyle = { + lineHeight: '30px', + textAlign: 'center', + borderLeft: '1px solid black', + cursor: 'pointer' + } + return ( +
{ + showPeriod(interval.startTime, interval.endTime) + }} + {...getIntervalProps({ + interval, + style: intervalStyle + })} + > + {interval.startTime.format('HH')} +
+ ) + })} +
+ ) + }} +
+ { + return ( +
+ {intervalContext.intervalText} +
+ ) + }} + /> + {this.state.showHeaders + ? [ + , + + ] + : null} +
+ + + + + {({ styles }) => { + const newStyles = { ...styles, backgroundColor: 'blue' } + return
+ }} + + + + +
+ ) + } +} diff --git a/demo/app/demo-linked-timelines/index.js b/demo/app/demo-linked-timelines/index.js index 8ec0af119..b68a3a5d6 100644 --- a/demo/app/demo-linked-timelines/index.js +++ b/demo/app/demo-linked-timelines/index.js @@ -70,7 +70,7 @@ export default class App extends Component { canSelect itemsSorted itemTouchSendsClick={false} - stackItems + stackItems="space" itemHeightRatio={0.75} visibleTimeStart={visibleTimeStart} visibleTimeEnd={visibleTimeEnd} @@ -94,7 +94,7 @@ export default class App extends Component { canSelect itemsSorted itemTouchSendsClick={false} - stackItems + stackItems="space" itemHeightRatio={0.75} visibleTimeStart={visibleTimeStart} visibleTimeEnd={visibleTimeEnd} diff --git a/demo/app/demo-main/index.js b/demo/app/demo-main/index.js index e18cc0b40..eec5d9ab0 100644 --- a/demo/app/demo-main/index.js +++ b/demo/app/demo-main/index.js @@ -34,15 +34,151 @@ export default class App extends Component { constructor(props) { super(props) - const { groups, items } = generateFakeData() - const defaultTimeStart = moment() + const items = [ + // { + // id: '4', + // group: '1', + // title: + // '4', + // start: 1550538000000, + // end: 1550560702870, + // canResize: false, + // className: '', + // bgColor: 'rgba(209, 154, 237, 0.6)', + // selectedBgColor: 'rgba(209, 154, 237, 1)', + // color: '#55077c', + // itemProps: { + // 'data-tip': + // 'The AGP bus is down, calculate the multi-byte alarm so we can generate the THX driver!' + // } + // }, + // { + // id: '5', + // group: '1', + // title: + // '5', + // start: 1550549700000, + // end: 1550569678295, + // canMove: true, + // canResize: 'both', + // className: '', + // bgColor: 'rgba(235, 171, 242, 0.6)', + // selectedBgColor: 'rgba(235, 171, 242, 1)', + // color: '#ad0fbf', + // itemProps: { + // 'data-tip': + // "I'll parse the virtual AI monitor, that should microchip the SDD circuit!" + // } + // }, + { + id: '1', + group: '1', + title: + '1', + start: 1550562300000, + end: 1550566800000, + canMove: true, + canResize: 'both', + className: '', + bgColor: 'rgba(119, 126, 249, 0.6)', + selectedBgColor: 'rgba(119, 126, 249, 1)', + color: '#010887', + itemProps: { + 'data-tip': + 'The IB alarm is down, parse the virtual driver so we can copy the COM bus!' + } + }, + { + id: '3', + group: '2', + title: '3', + start: 1550538000000, + end: 1550557157371, + canResize: false, + className: '', + bgColor: 'rgba(184, 141, 239, 0.6)', + selectedBgColor: 'rgba(184, 141, 239, 1)', + color: '#3c0584', + itemProps: { + 'data-tip': + 'Try to synthesize the AI circuit, maybe it will calculate the cross-platform interface!' + } + }, + + + { + id: '6', + group: '2', + title: '6', + start: 1550551500000, + end: 1550571478295, + canResize: false, + className: '', + bgColor: 'rgba(252, 191, 243, 0.6)', + selectedBgColor: 'rgba(252, 191, 243, 1)', + color: '#ea15ca', + itemProps: { + 'data-tip': 'We need to input the haptic USB panel!' + } + }, + { + id: '7', + group: '2', + title: + "7", + start: 1550539800000, + end: 1550559571292, + canResize: false, + className: '', + bgColor: 'rgba(247, 116, 197, 0.6)', + selectedBgColor: 'rgba(247, 116, 197, 1)', + color: '#db0288', + itemProps: { + 'data-tip': + "bypassing the driver won't do anything, we need to compress the haptic XML monitor!" + } + }, + { + id: '8', + group: '2', + title: '8', + start: 1550535300000, + end: 1550550380987, + canResize: false, + className: '', + bgColor: 'rgba(244, 129, 173, 0.6)', + selectedBgColor: 'rgba(244, 129, 173, 1)', + color: '#99043d', + itemProps: { + 'data-tip': + "copying the system won't do anything, we need to quantify the neural SCSI protocol!" + } + } + ] + + const groups = [ + { + id: '1', + title: 'Dee', + rightTitle: 'Kuhn', + label: 'Label Amari', + bgColor: '#c0d0f9' + }, + { + id: '2', + title: 'Brennon', + rightTitle: 'Cronin', + label: 'Label Maude', + bgColor: '#777ef9' + } + ] + + const defaultTimeStart = moment('19/2/2019', 'dd/mm/yyyy') .startOf('day') .toDate() - const defaultTimeEnd = moment() - .startOf('day') - .add(1, 'day') + const defaultTimeEnd = moment('19/2/2019', 'dd/mm/yyyy') + .endOf('day') .toDate() - this.state = { groups, items, @@ -156,7 +292,7 @@ export default class App extends Component { canSelect itemsSorted itemTouchSendsClick={false} - stackItems + stackItems='lines' itemHeightRatio={0.75} defaultTimeStart={defaultTimeStart} defaultTimeEnd={defaultTimeEnd} diff --git a/demo/app/demo-performance/index.js b/demo/app/demo-performance/index.js index 97c940d00..147db94a9 100644 --- a/demo/app/demo-performance/index.js +++ b/demo/app/demo-performance/index.js @@ -168,7 +168,7 @@ export default class App extends Component { canSelect itemsSorted itemTouchSendsClick={false} - stackItems + stackItems="space" itemHeightRatio={0.75} // resizeDetector={containerResizeDetector} diff --git a/demo/app/demo-renderers/index.js b/demo/app/demo-renderers/index.js index 898dfb426..7a3229647 100644 --- a/demo/app/demo-renderers/index.js +++ b/demo/app/demo-renderers/index.js @@ -187,7 +187,7 @@ export default class App extends Component { canSelect itemsSorted itemTouchSendsClick={false} - stackItems + stackItems="space" itemHeightRatio={0.75} // resizeDetector={containerResizeDetector} diff --git a/demo/app/demo-sticky-header/index.js b/demo/app/demo-sticky-header/index.js index adb26d533..d0685849e 100644 --- a/demo/app/demo-sticky-header/index.js +++ b/demo/app/demo-sticky-header/index.js @@ -65,7 +65,7 @@ export default class App extends Component { canSelect itemsSorted itemTouchSendsClick={false} - stackItems + stackItems="space" itemHeightRatio={0.75} resizeDetector={containerResizeDetector} defaultTimeStart={defaultTimeStart} @@ -113,7 +113,7 @@ export default class App extends Component { canSelect itemsSorted itemTouchSendsClick={false} - stackItems + stackItems="space" itemHeightRatio={0.75} resizeDetector={containerResizeDetector} defaultTimeStart={defaultTimeStart} diff --git a/demo/app/demo-tree-groups/index.js b/demo/app/demo-tree-groups/index.js index 63cb3ea2e..41dafbcea 100644 --- a/demo/app/demo-tree-groups/index.js +++ b/demo/app/demo-tree-groups/index.js @@ -111,7 +111,7 @@ export default class App extends Component { canSelect itemsSorted itemTouchSendsClick={false} - stackItems + stackItems="space" itemHeightRatio={0.75} defaultTimeStart={defaultTimeStart} defaultTimeEnd={defaultTimeEnd} diff --git a/demo/app/demo-vertical-classes/index.js b/demo/app/demo-vertical-classes/index.js index c8f0fbc5f..8d023e3b5 100644 --- a/demo/app/demo-vertical-classes/index.js +++ b/demo/app/demo-vertical-classes/index.js @@ -93,7 +93,7 @@ export default class App extends Component { canSelect itemsSorted itemTouchSendsClick={false} - stackItems + stackItems="space" itemHeightRatio={0.75} defaultTimeStart={defaultTimeStart} defaultTimeEnd={defaultTimeEnd} diff --git a/src/lib/Timeline.js b/src/lib/Timeline.js index 4d30fd4ff..28ef4a242 100644 --- a/src/lib/Timeline.js +++ b/src/lib/Timeline.js @@ -60,7 +60,7 @@ export default class ReactCalendarTimeline extends Component { useResizeHandle: PropTypes.bool, canSelect: PropTypes.bool, - stackItems: PropTypes.bool, + stackItems: PropTypes.oneOf([false,'space', 'lines']), traditionalZoom: PropTypes.bool, diff --git a/src/lib/utility/calendar.js b/src/lib/utility/calendar.js index 7d68cff41..174b3c6bc 100644 --- a/src/lib/utility/calendar.js +++ b/src/lib/utility/calendar.js @@ -296,6 +296,30 @@ export function collision(a, b, lineHeight, collisionPadding = EPSILON) { ) } +/** + * Calculate the position of a given item for a group that each in a line + * is being stacked + */ +export function groupStackInLines( + lineHeight, + item, + items, + groupHeight, + groupTop, + itemIndex +) { + // calculate non-overlapping positions + let verticalMargin = lineHeight - item.dimensions.height + if (item.dimensions.stack && item.dimensions.top === null) { + item.dimensions.top = groupTop + verticalMargin + itemIndex * lineHeight + } + return { + groupHeight: lineHeight * items.length, + verticalMargin, + itemTop: item.dimensions.top + } +} + /** * Calculate the position of a given item for a group that * is being stacked @@ -346,7 +370,6 @@ export function groupStack( verticalMargin, itemTop: item.dimensions.top } - } // Calculate the position of this item for a group that is not being stacked @@ -407,19 +430,24 @@ export function stackAll(itemsDimensions, groupOrders, lineHeight, stackItems) { } /** - * - * @param {*} itemsDimensions - * @param {*} isGroupStacked - * @param {*} lineHeight - * @param {*} groupTop + * + * @param {*} itemsDimensions + * @param {*} isGroupStacked + * @param {*} lineHeight + * @param {*} groupTop */ -export function stackGroup(itemsDimensions, isGroupStacked, lineHeight, groupTop) { +export function stackGroup( + itemsDimensions, + isGroupStacked, + lineHeight, + groupTop +) { var groupHeight = 0 var verticalMargin = 0 // Find positions for each item in group for (let itemIndex = 0; itemIndex < itemsDimensions.length; itemIndex++) { let r = {} - if (isGroupStacked) { + if (isGroupStacked === 'space') { r = groupStack( lineHeight, itemsDimensions[itemIndex], @@ -428,8 +456,22 @@ export function stackGroup(itemsDimensions, isGroupStacked, lineHeight, groupTop groupTop, itemIndex ) + } else if (isGroupStacked === 'lines') { + r = groupStackInLines( + lineHeight, + itemsDimensions[itemIndex], + itemsDimensions, + groupHeight, + groupTop, + itemIndex + ) } else { - r = groupNoStack(lineHeight, itemsDimensions[itemIndex], groupHeight, groupTop) + r = groupNoStack( + lineHeight, + itemsDimensions[itemIndex], + groupHeight, + groupTop + ) } groupHeight = r.groupHeight verticalMargin = r.verticalMargin From 6b193301c2e9fc82dcc8530d04fc2c9475a07693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20B=C3=BCschel?= Date: Tue, 26 Feb 2019 11:37:38 +0800 Subject: [PATCH 57/65] docs: fix minor spelling mistakes + update links for react and react-native --- README.md | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 52b50a5d5..46a69fb58 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # React Calendar Timeline -A modern and responsive react timeline component. +A modern and responsive React timeline component. ![calendar demo](https://raw.githubusercontent.com/namespace-ee/react-calendar-timeline/master/demo.gif) @@ -16,7 +16,7 @@ yarn add react-calendar-timeline npm install --save react-calendar-timeline ``` -`react-calendar-timeline` has `react`, `react-dom`, [`moment`](http://momentjs.com/) and [`interactjs`](http://interactjs.io/docs/) as peer dependencies. +`react-calendar-timeline` has [react](https://reactjs.org/), [react-dom](https://reactjs.org/docs/react-dom.html), [`moment`](http://momentjs.com/) and [`interactjs`](http://interactjs.io/docs/) as peer dependencies. # Usage @@ -88,7 +88,7 @@ Expects either a vanilla JS array or an immutableJS array, consisting of objects } ``` -If you use right sidebar, you can pass optional `rightTitle` property here. +If you use the right sidebar, you can pass optional `rightTitle` property here. If you want to overwrite the calculated height with a custom height, you can pass a `height` property as an int in pixels here. This can be very useful for categorized groups. ## items @@ -118,7 +118,7 @@ Expects either a vanilla JS array or an immutableJS array, consisting of objects } ``` -The preferred (fastest) option is to give unix timestamps in milliseconds for `start_time` and `end_time`. Objects that convert to them (JavaScript Date or moment()) will also work, but will be a lot slower. +The preferred (fastest) option is to give Unix timestamps in milliseconds for `start_time` and `end_time`. Objects that convert to them (JavaScript `Date` or `moment()`) will also work, but will be a lot slower. ## defaultTimeStart and defaultTimeEnd @@ -126,7 +126,7 @@ Unless overridden by `visibleTimeStart` and `visibleTimeEnd`, specify where the ## visibleTimeStart and visibleTimeEnd -The exact viewport of the calendar. When these are specified, scrolling in the calendar must be orchestrated by the `onTimeChange` function. This parameter expects a unix timestamp in milliseconds. +The exact viewport of the calendar. When these are specified, scrolling in the calendar must be orchestrated by the `onTimeChange` function. This parameter expects a Unix timestamp in milliseconds. **Note that you need to provide either `defaultTimeStart/End` or `visibleTimeStart/End` for the timeline to function** @@ -179,8 +179,7 @@ The minimum width, in pixels, of a timeline entry when it's possible to resize. ## stickyOffset -At what height from the top of the screen should we start "sticking" the header (i.e. position: sticky)? This is useful if for example you already have -a sticky navbar and want to push the timeline header down further. Defaults `0`. +At what height from the top of the screen should we start "sticking" the header (i.e. position: sticky)? This is useful if for example you already have a sticky navbar and want to push the timeline header down further. Defaults `0`. ## stickyHeader @@ -216,7 +215,7 @@ Largest time the calendar can zoom to in milliseconds. Default `5 * 365.24 * 864 ## clickTolerance -How many pixels we can drag the background for it to be counted as a click on the background. Defualt: `3` +How many pixels we can drag the background for it to be counted as a click on the background. Default `3` ## canMove @@ -435,9 +434,9 @@ Called when the bounds in the calendar's canvas change. Use it for example to lo ## itemRenderer -Render prop function used to render a customized item. The function provides multiple paramerters that can be used to render each item. +Render prop function used to render a customized item. The function provides multiple parameters that can be used to render each item. -Paramters provided to the function has two types: context params which have the state of the item and timeline, and prop getters functions +Parameters provided to the function has two types: context params which have the state of the item and timeline, and prop getters functions #### Render props params @@ -490,7 +489,7 @@ Rather than applying props on the element yourself and to avoid your props being * `getItemProps` returns the props you should apply to the root item element. The returned props are: * key: item id - * ref: function to get item referance + * ref: function to get item reference * className: classnames to be applied to the item * onMouseDown: event handler * onMouseUp: event handler @@ -500,9 +499,9 @@ Rather than applying props on the element yourself and to avoid your props being * onContextMenu: event handler * style: inline object style - \*\* _the given styles will only override the styles that are not a requirement for postioning the item. Other styles like `color`, `radius` and others_ + \*\* _the given styles will only override the styles that are not a requirement for positioning the item. Other styles like `color`, `radius` and others_ - These properties can be override using the prop argument with proprties: + These properties can be override using the prop argument with properties: * className: class names to be added * onMouseDown: event handler will be called after the component's event handler @@ -785,7 +784,7 @@ You need to include the `Timeline.css` file, either via static file reference or ## How can I have items with different colors? -Now you can use item renderer for rendering items with different colors [itemRenderer](https://github.com/namespace-ee/react-calendar-timeline#itemrenderer). +Now you can use item renderer for rendering items with different colors [itemRenderer](https://github.com/namespace-ee/react-calendar-timeline#itemrenderer). Please refer to [examples](https://github.com/namespace-ee/react-calendar-timeline/tree/master/examples#custom-item-rendering) for a sandbox example ## How can I add a sidebar on the right? From 730ec0da627288486b7134a5fc7d629d530b79fb Mon Sep 17 00:00:00 2001 From: ilaiwi Date: Fri, 8 Mar 2019 14:51:28 +0200 Subject: [PATCH 58/65] pump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4f9d9ce51..bf8af2c48 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@r365/react-calendar-timeline", - "version": "0.25.0-beta.17", + "version": "0.25.0-beta.18", "description": "react calendar timeline", "main": "lib/index.js", "scripts": { From ce237392d8ec7f9b24e9af22131003879281e0f4 Mon Sep 17 00:00:00 2001 From: Ilaiwi Date: Sun, 10 Mar 2019 14:18:40 +0200 Subject: [PATCH 59/65] improve click handlers --- demo/app/demo-headers/index.js | 6 ++++++ package.json | 2 +- src/lib/Timeline.js | 2 -- src/lib/items/Item.js | 24 +++++------------------- 4 files changed, 12 insertions(+), 22 deletions(-) diff --git a/demo/app/demo-headers/index.js b/demo/app/demo-headers/index.js index 5d160e6d0..9f8fc2498 100644 --- a/demo/app/demo-headers/index.js +++ b/demo/app/demo-headers/index.js @@ -65,6 +65,9 @@ export default class App extends Component { } handleCanvasClick = (groupId, time) => { + this.setState(state => ({ + groups: state.groups + })) console.log('Canvas clicked', groupId, moment(time).format()) } @@ -82,6 +85,9 @@ export default class App extends Component { handleItemSelect = (itemId, _, time) => { console.log('Selected: ' + itemId, moment(time).format()) + this.setState((state)=>({ + groups: state.groups.filter(_ => Math.random() > 0.5 ) + })) } handleItemDoubleClick = (itemId, _, time) => { diff --git a/package.json b/package.json index bf8af2c48..af1658f5e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@r365/react-calendar-timeline", - "version": "0.25.0-beta.18", + "version": "0.25.0-alpha.20", "description": "react calendar timeline", "main": "lib/index.js", "scripts": { diff --git a/src/lib/Timeline.js b/src/lib/Timeline.js index ead5470c8..e059451e4 100644 --- a/src/lib/Timeline.js +++ b/src/lib/Timeline.js @@ -1039,8 +1039,6 @@ export default class ReactCalendarTimeline extends Component { height: `${height}px` } - console.log("render", width) - return ( { - this.actualClick(e, e.pointerType === 'mouse' ? 'click' : 'touch') + if(e.pointerType !== 'mouse'){ + this.actualClick(e, 'touch') + } }) this.setState({ @@ -462,20 +463,6 @@ export default class Item extends Component { } - onMouseDown = e => { - if (!this.state.interactMounted) { - e.preventDefault() - this.startedClicking = true - } - } - - onMouseUp = e => { - if (!this.state.interactMounted && this.startedClicking) { - this.startedClicking = false - this.actualClick(e, 'click') - } - } - onTouchStart = e => { if (!this.state.interactMounted) { e.preventDefault() @@ -526,13 +513,12 @@ export default class Item extends Component { ref: this.getItemRef, title: this.itemDivTitle, className: classNames + ` ${props.className ? props.className : ''}`, - onMouseDown: composeEvents(this.onMouseDown, props.onMouseDown), - onMouseUp: composeEvents(this.onMouseUp, props.onMouseUp), onTouchStart: composeEvents(this.onTouchStart, props.onTouchStart), onTouchEnd: composeEvents(this.onTouchEnd, props.onTouchEnd), onDoubleClick: composeEvents(this.handleDoubleClick, props.onDoubleClick), onContextMenu: composeEvents(this.handleContextMenu, props.onContextMenu), - style: Object.assign({}, this.getItemStyle(props)) + style: Object.assign({}, this.getItemStyle(props)), + onClick : (e) => {this.actualClick(e, 'click')} } } From 8550a3e5a6b546f07fa68b9eaeec06238b8d7d78 Mon Sep 17 00:00:00 2001 From: Ilaiwi Date: Sun, 10 Mar 2019 14:19:02 +0200 Subject: [PATCH 60/65] beta --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index af1658f5e..db5c72f2f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@r365/react-calendar-timeline", - "version": "0.25.0-alpha.20", + "version": "0.25.0-beta.20", "description": "react calendar timeline", "main": "lib/index.js", "scripts": { From e88de29352f8b9b0bebcb159d37e71d996d1c28a Mon Sep 17 00:00:00 2001 From: Ilaiwi Date: Mon, 18 Mar 2019 11:01:13 +0200 Subject: [PATCH 61/65] fix height calculation of stacked items inconsistant --- .../calculate-scroll-canvas.js.snap | 44 +++++----- .../__snapshots__/group-stack.js.snap | 2 +- .../__snapshots__/stack-group.js.snap | 2 +- .../__snapshots__/stack-items.js.snap | 88 +++++++++---------- src/lib/utility/calendar.js | 6 +- 5 files changed, 71 insertions(+), 71 deletions(-) diff --git a/__tests__/utils/calendar/__snapshots__/calculate-scroll-canvas.js.snap b/__tests__/utils/calendar/__snapshots__/calculate-scroll-canvas.js.snap index 0d4c752b1..757fcc868 100644 --- a/__tests__/utils/calendar/__snapshots__/calculate-scroll-canvas.js.snap +++ b/__tests__/utils/calendar/__snapshots__/calculate-scroll-canvas.js.snap @@ -18,7 +18,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 78.74857638888886, }, "id": "0", @@ -36,7 +36,7 @@ Object { "index": 0, }, "stack": true, - "top": 37.5, + "top": 33.75, "width": 245.4152430555556, }, "id": "5", @@ -54,7 +54,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 287.08190972222224, }, "id": "6", @@ -72,7 +72,7 @@ Object { "index": 0, }, "stack": true, - "top": 37.5, + "top": 33.75, "width": 172.1749884259259, }, "id": "1", @@ -90,7 +90,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 236.08273148148123, }, "id": "2", @@ -108,23 +108,23 @@ Object { "index": 2, }, "stack": true, - "top": 105, + "top": 93.75, "width": 236.08273148148146, }, "id": "3", }, ], "groupHeights": Array [ - 67.5, + 60, + 30, 30, - 37.5, ], "groupTops": Array [ 0, - 67.5, - 97.5, + 60, + 90, ], - "height": 135, + "height": 120, "visibleTimeEnd": 1540634400000, "visibleTimeStart": 1540548000000, } @@ -148,7 +148,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 75.59863333333351, }, "id": "0", @@ -166,7 +166,7 @@ Object { "index": 0, }, "stack": true, - "top": 37.5, + "top": 33.75, "width": 235.5986333333335, }, "id": "5", @@ -184,7 +184,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 275.5986333333335, }, "id": "6", @@ -202,7 +202,7 @@ Object { "index": 0, }, "stack": true, - "top": 37.5, + "top": 33.75, "width": 165.28798888888878, }, "id": "1", @@ -220,7 +220,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 226.6394222222225, }, "id": "2", @@ -238,23 +238,23 @@ Object { "index": 2, }, "stack": true, - "top": 105, + "top": 93.75, "width": 226.6394222222225, }, "id": "3", }, ], "groupHeights": Array [ - 67.5, + 60, + 30, 30, - 37.5, ], "groupTops": Array [ 0, - 67.5, - 97.5, + 60, + 90, ], - "height": 135, + "height": 120, "visibleTimeEnd": 1540591200000, "visibleTimeStart": 1540501200000, } diff --git a/__tests__/utils/calendar/__snapshots__/group-stack.js.snap b/__tests__/utils/calendar/__snapshots__/group-stack.js.snap index 6f22034d7..bf2b6c159 100644 --- a/__tests__/utils/calendar/__snapshots__/group-stack.js.snap +++ b/__tests__/utils/calendar/__snapshots__/group-stack.js.snap @@ -4,6 +4,6 @@ exports[`groupStack works as expected 1`] = ` Object { "groupHeight": 0, "itemTop": 7.5, - "verticalMargin": 37.5, + "verticalMargin": 18.75, } `; diff --git a/__tests__/utils/calendar/__snapshots__/stack-group.js.snap b/__tests__/utils/calendar/__snapshots__/stack-group.js.snap index bbe832509..759f9e9f0 100644 --- a/__tests__/utils/calendar/__snapshots__/stack-group.js.snap +++ b/__tests__/utils/calendar/__snapshots__/stack-group.js.snap @@ -10,6 +10,6 @@ Object { exports[`stackGroup should stack list of items 1`] = ` Object { "groupHeight": 0, - "verticalMargin": 7.5, + "verticalMargin": 3.75, } `; diff --git a/__tests__/utils/calendar/__snapshots__/stack-items.js.snap b/__tests__/utils/calendar/__snapshots__/stack-items.js.snap index 8d27dc42d..9d0000a46 100644 --- a/__tests__/utils/calendar/__snapshots__/stack-items.js.snap +++ b/__tests__/utils/calendar/__snapshots__/stack-items.js.snap @@ -16,7 +16,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 236.24572916666602, }, "id": "0", @@ -34,7 +34,7 @@ Object { "index": 0, }, "stack": true, - "top": 37.5, + "top": 33.75, "width": 736.245729166666, }, "id": "5", @@ -52,7 +52,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 861.245729166666, }, "id": "6", @@ -70,7 +70,7 @@ Object { "index": 0, }, "stack": true, - "top": 37.5, + "top": 33.75, "width": 516.5249652777784, }, "id": "1", @@ -88,7 +88,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 708.2481944444444, }, "id": "2", @@ -106,23 +106,23 @@ Object { "index": 2, }, "stack": true, - "top": 105, + "top": 93.75, "width": 625, }, "id": "3", }, ], "groupHeights": Array [ - 67.5, + 60, + 30, 30, - 37.5, ], "groupTops": Array [ 0, - 67.5, - 97.5, + 60, + 90, ], - "height": 135, + "height": 120, } `; @@ -142,7 +142,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 111.24572916666602, }, "id": "0", @@ -160,7 +160,7 @@ Object { "index": 0, }, "stack": true, - "top": 37.5, + "top": 33.75, "width": 736.245729166666, }, "id": "5", @@ -178,7 +178,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 861.245729166666, }, "id": "6", @@ -196,7 +196,7 @@ Object { "index": 0, }, "stack": true, - "top": 37.5, + "top": 33.75, "width": 516.5249652777784, }, "id": "1", @@ -214,7 +214,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 708.2481944444444, }, "id": "2", @@ -232,23 +232,23 @@ Object { "index": 2, }, "stack": true, - "top": 105, + "top": 93.75, "width": 625, }, "id": "3", }, ], "groupHeights": Array [ - 67.5, + 60, + 30, 30, - 37.5, ], "groupTops": Array [ 0, - 67.5, - 97.5, + 60, + 90, ], - "height": 135, + "height": 120, } `; @@ -268,7 +268,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 361.245729166666, }, "id": "0", @@ -286,7 +286,7 @@ Object { "index": 0, }, "stack": true, - "top": 37.5, + "top": 33.75, "width": 736.245729166666, }, "id": "5", @@ -304,7 +304,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 861.245729166666, }, "id": "6", @@ -322,7 +322,7 @@ Object { "index": 0, }, "stack": true, - "top": 37.5, + "top": 33.75, "width": 516.5249652777784, }, "id": "1", @@ -340,7 +340,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 708.2481944444444, }, "id": "2", @@ -358,23 +358,23 @@ Object { "index": 2, }, "stack": true, - "top": 105, + "top": 93.75, "width": 625, }, "id": "3", }, ], "groupHeights": Array [ - 67.5, + 60, + 30, 30, - 37.5, ], "groupTops": Array [ 0, - 67.5, - 97.5, + 60, + 90, ], - "height": 135, + "height": 120, } `; @@ -394,7 +394,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 236.24572916666602, }, "id": "0", @@ -412,7 +412,7 @@ Object { "index": 0, }, "stack": true, - "top": 37.5, + "top": 33.75, "width": 736.245729166666, }, "id": "5", @@ -430,7 +430,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 861.245729166666, }, "id": "6", @@ -448,7 +448,7 @@ Object { "index": 0, }, "stack": true, - "top": 37.5, + "top": 33.75, "width": 516.5249652777784, }, "id": "1", @@ -466,7 +466,7 @@ Object { "index": 0, }, "stack": true, - "top": 7.5, + "top": 3.75, "width": 708.2481944444444, }, "id": "2", @@ -484,23 +484,23 @@ Object { "index": 2, }, "stack": true, - "top": 105, + "top": 93.75, "width": 625, }, "id": "3", }, ], "groupHeights": Array [ - 67.5, + 60, + 30, 30, - 37.5, ], "groupTops": Array [ 0, - 67.5, - 97.5, + 60, + 90, ], - "height": 135, + "height": 120, } `; diff --git a/src/lib/utility/calendar.js b/src/lib/utility/calendar.js index 7d68cff41..7edf95708 100644 --- a/src/lib/utility/calendar.js +++ b/src/lib/utility/calendar.js @@ -310,7 +310,7 @@ export function groupStack( ) { // calculate non-overlapping positions let curHeight = groupHeight - let verticalMargin = lineHeight - item.dimensions.height + let verticalMargin = (lineHeight - item.dimensions.height) / 2 if (item.dimensions.stack && item.dimensions.top === null) { item.dimensions.top = groupTop + verticalMargin curHeight = Math.max(curHeight, lineHeight) @@ -336,7 +336,7 @@ export function groupStack( item.dimensions.top = collidingItem.dimensions.top + lineHeight curHeight = Math.max( curHeight, - item.dimensions.top + item.dimensions.height - groupTop + item.dimensions.top + item.dimensions.height + verticalMargin - groupTop ) } } while (collidingItem) @@ -396,7 +396,7 @@ export function stackAll(itemsDimensions, groupOrders, lineHeight, stackItems) { if (group.height) { groupHeights.push(group.height) } else { - groupHeights.push(Math.max(groupHeight + verticalMargin, lineHeight)) + groupHeights.push(Math.max(groupHeight, lineHeight)) } } return { From e3e3d06e935ef0ae70be84f01859bbbb4946762b Mon Sep 17 00:00:00 2001 From: Ilaiwi Date: Mon, 18 Mar 2019 13:31:13 +0200 Subject: [PATCH 62/65] 0.25.21 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index db5c72f2f..ea8764ba9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@r365/react-calendar-timeline", - "version": "0.25.0-beta.20", + "version": "0.25.0-beta.21", "description": "react calendar timeline", "main": "lib/index.js", "scripts": { From 289a6773e57d92504d18ca8f1e907f9203f2ac6b Mon Sep 17 00:00:00 2001 From: Faisal Alfaddaghi Date: Thu, 19 Sep 2019 11:06:48 +0300 Subject: [PATCH 63/65] change homepage and git URL changed these so that the npm page directs to the correct repository. --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 8b22265ed..3dfda0b87 100644 --- a/package.json +++ b/package.json @@ -18,10 +18,10 @@ "lib", "src" ], - "homepage": "https://github.com/namespace-ee/react-calendar-timeline", + "homepage": "https://github.com/FoothillSolutions/react-calendar-timeline", "repository": { "type": "git", - "url": "https://github.com/namespace-ee/react-calendar-timeline.git" + "url": "https://github.com/FoothillSolutions/react-calendar-timeline.git" }, "author": "Marius Andra ", "contributors": [ From 42ebee8e298bc10b1fd5f8b64eac1f4316c4ba7d Mon Sep 17 00:00:00 2001 From: Abdallatif Date: Tue, 3 Mar 2020 12:58:16 +0200 Subject: [PATCH 64/65] fix start of day in daylight saving --- src/lib/utility/calendar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/utility/calendar.js b/src/lib/utility/calendar.js index 39af9798a..12d8a68cb 100644 --- a/src/lib/utility/calendar.js +++ b/src/lib/utility/calendar.js @@ -68,7 +68,7 @@ export function iterateTimes(start, end, unit, timeSteps, callback) { } while (time.valueOf() < end) { - let nextTime = moment(time).add(timeSteps[unit] || 1, `${unit}s`) + let nextTime = moment(time).add(timeSteps[unit] || 1, `${unit}s`).startOf(`${unit}s`); let endTime = moment(time).endOf(`${unit}s`) callback(time, endTime) time = nextTime From a6c33797f17dd5590999ce5d43287dc6473df4f2 Mon Sep 17 00:00:00 2001 From: Abdallatif Date: Wed, 4 Mar 2020 16:55:23 +0200 Subject: [PATCH 65/65] 0.25.0-beta.22 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e32a89ad8..7242ece7f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@r365/react-calendar-timeline", - "version": "0.25.0-beta.21", + "version": "0.25.0-beta.22", "description": "react calendar timeline", "main": "lib/index.js", "scripts": {