diff --git a/demo-app/src/stories/TimelineScenarios.ts b/demo-app/src/stories/TimelineScenarios.ts index 5f5814e3..4bc56136 100644 --- a/demo-app/src/stories/TimelineScenarios.ts +++ b/demo-app/src/stories/TimelineScenarios.ts @@ -12,4 +12,5 @@ export const timelineScenarios = { propertyMinDate: 'PROPERTY minDate', propertyMaxDate: 'PROPERTY maxDate', propertyShowZoomShortcuts: 'PROPERTY showZoomShortcuts', + givenIlegalDataThenShowWarning: "GIVEN illegal data, THEN show warning icon", }; diff --git a/demo-app/src/stories/basic/Basic.stories.tsx b/demo-app/src/stories/basic/Basic.stories.tsx index 38b1c354..6206cbc0 100644 --- a/demo-app/src/stories/basic/Basic.stories.tsx +++ b/demo-app/src/stories/basic/Basic.stories.tsx @@ -136,4 +136,15 @@ HorizontalScroll.parameters = { timelineScenarios.propertyMinDate, timelineScenarios.propertyMaxDate ] -}; \ No newline at end of file +}; + +export const IllegalData = () => { + + return (); +}; + +IllegalData.parameters = { + scenarios: [ + timelineScenarios.givenIlegalDataThenShowWarning + ] +} diff --git a/src/style.css b/src/style.css index 30c3cdc7..72f9b1b1 100644 --- a/src/style.css +++ b/src/style.css @@ -414,6 +414,12 @@ top: 1px; } +.rct9k-warning-div { + position: absolute; + right: 30px; + top: 3px; +} + .rct9k-menu.ui.popup { padding: 0 !important; margin: 0 !important; diff --git a/src/timeline.js b/src/timeline.js index 9488337c..bf643367 100644 --- a/src/timeline.js +++ b/src/timeline.js @@ -7,7 +7,7 @@ import Measure from 'react-measure'; import interact from 'interactjs'; import _ from 'lodash'; -import {Button, Popup} from 'semantic-ui-react'; +import {Button, Popup, Icon} from 'semantic-ui-react'; import {Group, InteractOption, Item, RowLayer} from './index'; import {TestsAreDemoCheat, createTestids} from '@famiprog-foundation/tests-are-demo'; @@ -613,7 +613,8 @@ export default class Timeline extends React.Component { touchPositionX: undefined, fadeEffectOpen: false, fadeEffectContent: undefined, - fadeEffectOpacity: 0 + fadeEffectOpacity: 0, + illegalInputData: false }; // These functions need to be bound because they are passed as parameters. @@ -1036,6 +1037,7 @@ export default class Timeline extends React.Component { let fillInGroups = []; + let illegalInputData = false; let groupId = groups.length; while (heightToFillIn > 0) { // create new empty group; @@ -1047,10 +1049,17 @@ export default class Timeline extends React.Component { } fillInGroups.push(emptyGroup); + if (this.rowItemMap[groupId] && this.rowItemMap[groupId].length) { + const itemKeys = this.rowItemMap[groupId].map(item => item.key).join(', '); + console.error( + `The items with keys: [${itemKeys}] has row = ${groupId} but there's no group with index ${groupId}. Please check if the groups property or the items with keys [${itemKeys}] are well defined.` + ); + illegalInputData = true; + } heightToFillIn -= this.props.itemHeight; groupId++; } - this.setState({groups: [...groups, ...fillInGroups]}); + this.setState({groups: [...groups, ...fillInGroups], illegalInputData}); } /** @@ -2025,6 +2034,17 @@ export default class Timeline extends React.Component { } } + /** + * @returns { JSX.Element } + */ + renderWarningIcon() { + return ( + }> +
Some of the input data are illegal. More info in the console.
+
+ ); + } + /** * @returns { JSX.Element } */ @@ -2336,6 +2356,7 @@ export default class Timeline extends React.Component { topOffset: timebarHeight, verticalGridLines: this.state.verticalGridLines })} + {this.state.illegalInputData &&
{this.renderWarningIcon()}
}
{this.renderMenuButton()}