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()}