Merge pull request #11990 from influxdata/feat/time-range-calendar
feat(ui): Add custom time range option in time range dropdownpull/12001/head
commit
d895f5aeb7
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
1. [11954](https://github.com/influxdata/influxdb/pull/11954): Add the ability to run a task manually from tasks page
|
1. [11954](https://github.com/influxdata/influxdb/pull/11954): Add the ability to run a task manually from tasks page
|
||||||
|
1. [11990](https://github.com/influxdata/influxdb/pull/11990): Add the ability to select a custom time range in explorer and dashboard
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
|
|
@ -777,7 +777,6 @@
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.2.0.tgz",
|
||||||
"integrity": "sha512-oouEibCbHMVdZSDlJBO6bZmID/zA/G/Qx3H1d3rSNPTD+L8UNKvCat7aKWSJ74zYbm5zWGh0GQN0hKj8zYFTCg==",
|
"integrity": "sha512-oouEibCbHMVdZSDlJBO6bZmID/zA/G/Qx3H1d3rSNPTD+L8UNKvCat7aKWSJ74zYbm5zWGh0GQN0hKj8zYFTCg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"regenerator-runtime": "^0.12.0"
|
"regenerator-runtime": "^0.12.0"
|
||||||
},
|
},
|
||||||
|
@ -785,8 +784,7 @@
|
||||||
"regenerator-runtime": {
|
"regenerator-runtime": {
|
||||||
"version": "0.12.1",
|
"version": "0.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz",
|
||||||
"integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==",
|
"integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3696,6 +3694,15 @@
|
||||||
"object-assign": "^4.1.1"
|
"object-assign": "^4.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"create-react-context": {
|
||||||
|
"version": "0.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.2.2.tgz",
|
||||||
|
"integrity": "sha512-KkpaLARMhsTsgp0d2NA/R94F/eDLbhXERdIq3LvX2biCAXcDvHYoOqHfWCHf1+OLj+HKBotLG3KqaOOf+C1C+A==",
|
||||||
|
"requires": {
|
||||||
|
"fbjs": "^0.8.0",
|
||||||
|
"gud": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"cross-spawn": {
|
"cross-spawn": {
|
||||||
"version": "6.0.5",
|
"version": "6.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
|
||||||
|
@ -6589,6 +6596,11 @@
|
||||||
"integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
|
"integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"gud": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw=="
|
||||||
|
},
|
||||||
"handlebars": {
|
"handlebars": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.0.tgz",
|
||||||
|
@ -11336,6 +11348,11 @@
|
||||||
"integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==",
|
"integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"popper.js": {
|
||||||
|
"version": "1.14.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.7.tgz",
|
||||||
|
"integrity": "sha512-4q1hNvoUre/8srWsH7hnoSJ5xVmIL4qgz+s4qf2TnJIMyZFUFMGH+9vE7mXynAlHSZ/NdTmmow86muD0myUkVQ=="
|
||||||
|
},
|
||||||
"posix-character-classes": {
|
"posix-character-classes": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
|
||||||
|
@ -12488,6 +12505,25 @@
|
||||||
"prop-types": "^15.5.8"
|
"prop-types": "^15.5.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-datepicker": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-zsPqierShVc0NN+JCyJO18jMFDTbGNSgmekQm+Zr5JYH/aZShsjOBGQmjNiQmIw7nJNQDRzh1oQUND3TY/9Swg==",
|
||||||
|
"requires": {
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"date-fns": "^2.0.0-alpha.23",
|
||||||
|
"prop-types": "^15.6.0",
|
||||||
|
"react-onclickoutside": "^6.7.1",
|
||||||
|
"react-popper": "^1.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"date-fns": {
|
||||||
|
"version": "2.0.0-alpha.27",
|
||||||
|
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.0.0-alpha.27.tgz",
|
||||||
|
"integrity": "sha512-cqfVLS+346P/Mpj2RpDrBv0P4p2zZhWWvfY5fuWrXNR/K38HaAGEkeOwb47hIpQP9Jr/TIxjZ2/sNMQwdXuGMg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-dimensions": {
|
"react-dimensions": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-dimensions/-/react-dimensions-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-dimensions/-/react-dimensions-1.3.1.tgz",
|
||||||
|
@ -12574,6 +12610,34 @@
|
||||||
"xtend": "^4.0.1"
|
"xtend": "^4.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-onclickoutside": {
|
||||||
|
"version": "6.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.7.1.tgz",
|
||||||
|
"integrity": "sha512-p84kBqGaMoa7VYT0vZ/aOYRfJB+gw34yjpda1Z5KeLflg70HipZOT+MXQenEhdkPAABuE2Astq4zEPdMqUQxcg=="
|
||||||
|
},
|
||||||
|
"react-popper": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-ynMZBPkXONPc5K4P5yFWgZx5JGAUIP3pGGLNs58cfAPgK67olx7fmLp+AdpZ0+GoQ+ieFDa/z4cdV6u7sioH6w==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.1.2",
|
||||||
|
"create-react-context": "<=0.2.2",
|
||||||
|
"popper.js": "^1.14.4",
|
||||||
|
"prop-types": "^15.6.1",
|
||||||
|
"typed-styles": "^0.0.7",
|
||||||
|
"warning": "^4.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"warning": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
|
||||||
|
"requires": {
|
||||||
|
"loose-envify": "^1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-redux": {
|
"react-redux": {
|
||||||
"version": "5.0.7",
|
"version": "5.0.7",
|
||||||
"resolved": "http://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz",
|
"resolved": "http://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz",
|
||||||
|
@ -14630,204 +14694,6 @@
|
||||||
"loader-utils": "^1.0.2",
|
"loader-utils": "^1.0.2",
|
||||||
"micromatch": "^3.1.4",
|
"micromatch": "^3.1.4",
|
||||||
"semver": "^5.0.1"
|
"semver": "^5.0.1"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"define-property": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"is-descriptor": "^1.0.2",
|
|
||||||
"isobject": "^3.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"expand-brackets": {
|
|
||||||
"version": "2.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
|
|
||||||
"integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"debug": "^2.3.3",
|
|
||||||
"define-property": "^0.2.5",
|
|
||||||
"extend-shallow": "^2.0.1",
|
|
||||||
"posix-character-classes": "^0.1.0",
|
|
||||||
"regex-not": "^1.0.0",
|
|
||||||
"snapdragon": "^0.8.1",
|
|
||||||
"to-regex": "^3.0.1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"define-property": {
|
|
||||||
"version": "0.2.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
|
|
||||||
"integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"is-descriptor": "^0.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"extend-shallow": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
|
|
||||||
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"is-extendable": "^0.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"is-descriptor": {
|
|
||||||
"version": "0.1.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
|
|
||||||
"integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"is-accessor-descriptor": "^0.1.6",
|
|
||||||
"is-data-descriptor": "^0.1.4",
|
|
||||||
"kind-of": "^5.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"is-extendable": {
|
|
||||||
"version": "0.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
|
|
||||||
"integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"kind-of": {
|
|
||||||
"version": "5.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
|
|
||||||
"integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"extend-shallow": {
|
|
||||||
"version": "3.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
|
|
||||||
"integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"assign-symbols": "^1.0.0",
|
|
||||||
"is-extendable": "^1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"extglob": {
|
|
||||||
"version": "2.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
|
|
||||||
"integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"array-unique": "^0.3.2",
|
|
||||||
"define-property": "^1.0.0",
|
|
||||||
"expand-brackets": "^2.1.4",
|
|
||||||
"extend-shallow": "^2.0.1",
|
|
||||||
"fragment-cache": "^0.2.1",
|
|
||||||
"regex-not": "^1.0.0",
|
|
||||||
"snapdragon": "^0.8.1",
|
|
||||||
"to-regex": "^3.0.1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"define-property": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"is-descriptor": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"extend-shallow": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
|
|
||||||
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"is-extendable": "^0.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"is-extendable": {
|
|
||||||
"version": "0.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
|
|
||||||
"integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"is-accessor-descriptor": {
|
|
||||||
"version": "0.1.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
|
|
||||||
"integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"kind-of": "^3.0.2"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"kind-of": {
|
|
||||||
"version": "3.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
|
|
||||||
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"is-buffer": "^1.1.5"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"is-data-descriptor": {
|
|
||||||
"version": "0.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
|
|
||||||
"integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"kind-of": "^3.0.2"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"kind-of": {
|
|
||||||
"version": "3.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
|
|
||||||
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"is-buffer": "^1.1.5"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"is-extendable": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
|
|
||||||
"integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"is-plain-object": "^2.0.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kind-of": {
|
|
||||||
"version": "6.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
|
|
||||||
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"micromatch": {
|
|
||||||
"version": "3.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
|
|
||||||
"integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"arr-diff": "^4.0.0",
|
|
||||||
"array-unique": "^0.3.2",
|
|
||||||
"braces": "^2.3.1",
|
|
||||||
"define-property": "^2.0.2",
|
|
||||||
"extend-shallow": "^3.0.2",
|
|
||||||
"extglob": "^2.0.4",
|
|
||||||
"fragment-cache": "^0.2.1",
|
|
||||||
"kind-of": "^6.0.2",
|
|
||||||
"nanomatch": "^1.2.9",
|
|
||||||
"object.pick": "^1.3.0",
|
|
||||||
"regex-not": "^1.0.0",
|
|
||||||
"snapdragon": "^0.8.1",
|
|
||||||
"to-regex": "^3.0.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tslib": {
|
"tslib": {
|
||||||
|
@ -14931,6 +14797,11 @@
|
||||||
"mime-types": "~2.1.18"
|
"mime-types": "~2.1.18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"typed-styles": {
|
||||||
|
"version": "0.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz",
|
||||||
|
"integrity": "sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q=="
|
||||||
|
},
|
||||||
"typedarray": {
|
"typedarray": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||||
|
|
|
@ -161,6 +161,7 @@
|
||||||
"react": "^16.8.0",
|
"react": "^16.8.0",
|
||||||
"react-codemirror2": "^4.2.1",
|
"react-codemirror2": "^4.2.1",
|
||||||
"react-copy-to-clipboard": "^5.0.1",
|
"react-copy-to-clipboard": "^5.0.1",
|
||||||
|
"react-datepicker": "^2.1.0",
|
||||||
"react-dimensions": "^1.2.0",
|
"react-dimensions": "^1.2.0",
|
||||||
"react-dnd": "^2.6.0",
|
"react-dnd": "^2.6.0",
|
||||||
"react-dnd-html5-backend": "^2.6.0",
|
"react-dnd-html5-backend": "^2.6.0",
|
||||||
|
|
|
@ -10,11 +10,11 @@ interface Props {
|
||||||
@ErrorHandling
|
@ErrorHandling
|
||||||
export class ClickOutside extends PureComponent<Props> {
|
export class ClickOutside extends PureComponent<Props> {
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
document.addEventListener('click', this.handleClickOutside, true)
|
document.addEventListener('mousedown', this.handleClickOutside, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
document.removeEventListener('click', this.handleClickOutside, true)
|
document.removeEventListener('mousedown', this.handleClickOutside, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
// Libraries
|
// Libraries
|
||||||
import React, {PureComponent} from 'react'
|
import React, {PureComponent, createRef} from 'react'
|
||||||
|
import {get} from 'lodash'
|
||||||
|
import moment from 'moment'
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import {Dropdown} from 'src/clockface'
|
import {Dropdown} from 'src/clockface'
|
||||||
|
import DateRangePicker from 'src/shared/components/dateRangePicker/DateRangePicker'
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
import {TIME_RANGES} from 'src/shared/constants/timeRanges'
|
import {
|
||||||
|
TIME_RANGES,
|
||||||
|
CUSTOM_TIME_RANGE,
|
||||||
|
TIME_RANGE_FORMAT,
|
||||||
|
} from 'src/shared/constants/timeRanges'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import {TimeRange} from 'src/types'
|
import {TimeRange} from 'src/types'
|
||||||
|
@ -15,34 +22,134 @@ interface Props {
|
||||||
onSetTimeRange: (timeRange: TimeRange) => void
|
onSetTimeRange: (timeRange: TimeRange) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
class TimeRangeDropdown extends PureComponent<Props> {
|
interface State {
|
||||||
|
isDatePickerOpen: boolean
|
||||||
|
dropdownPosition: {top: number; right: number}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimeRangeDropdown extends PureComponent<Props, State> {
|
||||||
|
private dropdownRef = createRef<HTMLDivElement>()
|
||||||
|
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = {isDatePickerOpen: false, dropdownPosition: undefined}
|
||||||
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
|
const timeRange = this.timeRange
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{this.isDatePickerVisible && (
|
||||||
|
<DateRangePicker
|
||||||
|
timeRange={timeRange}
|
||||||
|
onSetTimeRange={this.handleApplyTimeRange}
|
||||||
|
onClose={this.handleHideDatePicker}
|
||||||
|
position={this.state.dropdownPosition}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<div ref={this.dropdownRef}>
|
||||||
|
<Dropdown
|
||||||
|
selectedID={timeRange.label}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
widthPixels={this.dropdownWidth}
|
||||||
|
titleText={this.formattedCustomTimeRange}
|
||||||
|
>
|
||||||
|
{TIME_RANGES.map(({label}) => (
|
||||||
|
<Dropdown.Item key={label} value={label} id={label}>
|
||||||
|
{label}
|
||||||
|
</Dropdown.Item>
|
||||||
|
))}
|
||||||
|
</Dropdown>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private get dropdownWidth(): number {
|
||||||
|
if (this.isCustomTimeRange) {
|
||||||
|
return 250
|
||||||
|
}
|
||||||
|
|
||||||
|
return 100
|
||||||
|
}
|
||||||
|
|
||||||
|
private get isCustomTimeRange(): boolean {
|
||||||
const {timeRange} = this.props
|
const {timeRange} = this.props
|
||||||
|
return (
|
||||||
|
get(timeRange, 'label', '') === CUSTOM_TIME_RANGE || !!timeRange.upper
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private get formattedCustomTimeRange(): string {
|
||||||
|
const {timeRange} = this.props
|
||||||
|
if (!this.isCustomTimeRange) {
|
||||||
|
return timeRange.label
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${moment(timeRange.lower).format(TIME_RANGE_FORMAT)} - ${moment(
|
||||||
|
timeRange.upper
|
||||||
|
).format(TIME_RANGE_FORMAT)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
private get timeRange(): TimeRange {
|
||||||
|
const {timeRange} = this.props
|
||||||
|
const {isDatePickerOpen} = this.state
|
||||||
|
|
||||||
|
if (isDatePickerOpen) {
|
||||||
|
const date = new Date().toISOString()
|
||||||
|
const upper =
|
||||||
|
timeRange.upper && this.isCustomTimeRange ? timeRange.upper : date
|
||||||
|
const lower =
|
||||||
|
timeRange.lower && this.isCustomTimeRange ? timeRange.lower : date
|
||||||
|
return {
|
||||||
|
label: CUSTOM_TIME_RANGE,
|
||||||
|
lower,
|
||||||
|
upper,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isCustomTimeRange) {
|
||||||
|
return {
|
||||||
|
...timeRange,
|
||||||
|
label: this.formattedCustomTimeRange,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const selectedTimeRange = TIME_RANGES.find(t => t.lower === timeRange.lower)
|
const selectedTimeRange = TIME_RANGES.find(t => t.lower === timeRange.lower)
|
||||||
|
|
||||||
if (!selectedTimeRange) {
|
if (!selectedTimeRange) {
|
||||||
throw new Error('TimeRangeDropdown passed unknown TimeRange')
|
throw new Error('TimeRangeDropdown passed unknown TimeRange')
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return selectedTimeRange
|
||||||
<Dropdown
|
}
|
||||||
selectedID={selectedTimeRange.label}
|
|
||||||
onChange={this.handleChange}
|
private get isDatePickerVisible() {
|
||||||
widthPixels={100}
|
return this.state.isDatePickerOpen
|
||||||
>
|
}
|
||||||
{TIME_RANGES.map(({label}) => (
|
|
||||||
<Dropdown.Item key={label} value={label} id={label}>
|
private handleApplyTimeRange = (timeRange: TimeRange) => {
|
||||||
{label}
|
this.props.onSetTimeRange(timeRange)
|
||||||
</Dropdown.Item>
|
this.handleHideDatePicker()
|
||||||
))}
|
}
|
||||||
</Dropdown>
|
|
||||||
)
|
private handleHideDatePicker = () => {
|
||||||
|
this.setState({isDatePickerOpen: false, dropdownPosition: null})
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleChange = (label: string): void => {
|
private handleChange = (label: string): void => {
|
||||||
const {onSetTimeRange} = this.props
|
const {onSetTimeRange} = this.props
|
||||||
const timeRange = TIME_RANGES.find(t => t.label === label)
|
const timeRange = TIME_RANGES.find(t => t.label === label)
|
||||||
|
|
||||||
|
if (label === CUSTOM_TIME_RANGE) {
|
||||||
|
const {top, left} = this.dropdownRef.current.getBoundingClientRect()
|
||||||
|
const right = window.innerWidth - left
|
||||||
|
this.setState({isDatePickerOpen: true, dropdownPosition: {top, right}})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
onSetTimeRange(timeRange)
|
onSetTimeRange(timeRange)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
// Libraries
|
||||||
|
import React, {PureComponent} from 'react'
|
||||||
|
import ReactDatePicker from 'react-datepicker'
|
||||||
|
|
||||||
|
// Styles
|
||||||
|
import 'react-datepicker/dist/react-datepicker.css'
|
||||||
|
import {Input} from 'src/clockface'
|
||||||
|
import {ComponentSize} from '@influxdata/clockface'
|
||||||
|
import FormLabel from 'src/clockface/components/form_layout/FormLabel'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
label: string
|
||||||
|
dateTime: string
|
||||||
|
onSelectDate: (date: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
class DatePicker extends PureComponent<Props> {
|
||||||
|
private inCurrentMonth: boolean = false
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
const {dateTime, label} = this.props
|
||||||
|
const date = new Date(dateTime)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormLabel label={label}>
|
||||||
|
<div className="range-picker--date-picker">
|
||||||
|
<ReactDatePicker
|
||||||
|
selected={date}
|
||||||
|
onChange={this.handleSelectDate}
|
||||||
|
startOpen={true}
|
||||||
|
dateFormat="yyyy-MM-dd HH:mm"
|
||||||
|
showTimeSelect={true}
|
||||||
|
timeFormat="HH:mm"
|
||||||
|
shouldCloseOnSelect={false}
|
||||||
|
disabledKeyboardNavigation={true}
|
||||||
|
customInput={this.customInput}
|
||||||
|
popperContainer={this.popperContainer}
|
||||||
|
popperClassName="range-picker--popper"
|
||||||
|
calendarClassName="range-picker--calendar"
|
||||||
|
dayClassName={this.dayClassName}
|
||||||
|
timeIntervals={60}
|
||||||
|
fixedHeight={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</FormLabel>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private get customInput() {
|
||||||
|
return (
|
||||||
|
<Input
|
||||||
|
widthPixels={314}
|
||||||
|
size={ComponentSize.Medium}
|
||||||
|
customClass="range-picker--input react-datepicker-ignore-onclickoutside"
|
||||||
|
titleText="Start"
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private dayClassName = (date: Date) => {
|
||||||
|
const day = date.getDate()
|
||||||
|
|
||||||
|
if (day === 1) {
|
||||||
|
this.inCurrentMonth = !this.inCurrentMonth
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.inCurrentMonth) {
|
||||||
|
return 'range-picker--day-in-month'
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'range-picker--day'
|
||||||
|
}
|
||||||
|
|
||||||
|
private popperContainer({children}): JSX.Element {
|
||||||
|
return <div className="range-picker--popper-container">{children}</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleSelectDate = (date: Date): void => {
|
||||||
|
const {onSelectDate} = this.props
|
||||||
|
|
||||||
|
onSelectDate(date.toISOString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DatePicker
|
|
@ -0,0 +1,204 @@
|
||||||
|
/*
|
||||||
|
Date Range Picker Styles
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import 'src/style/modules';
|
||||||
|
|
||||||
|
.range-picker {
|
||||||
|
position: fixed;
|
||||||
|
text-align: center;
|
||||||
|
background-color: $g1-raven;
|
||||||
|
border: $ix-border solid $c-pool;
|
||||||
|
padding: $ix-marg-b;
|
||||||
|
border-radius: $ix-radius;
|
||||||
|
z-index: 9999;
|
||||||
|
height: 410px;
|
||||||
|
|
||||||
|
.react-datepicker {
|
||||||
|
font-family: $ix-text-font;
|
||||||
|
font-size: $ix-text-base-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-picker--date-pickers {
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin: $ix-marg-b 0;
|
||||||
|
|
||||||
|
.range-picker--date-picker {
|
||||||
|
.range-picker--popper-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-picker--popper {
|
||||||
|
position: relative !important;
|
||||||
|
transform: none !important;
|
||||||
|
@include no-user-select();
|
||||||
|
|
||||||
|
.range-picker--calendar {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
color: $c-pool;
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
.react-datepicker__navigation {
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__navigation--next {
|
||||||
|
border-left-color: $g18-cloud;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__navigation--previous {
|
||||||
|
border-right-color: $g18-cloud;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-picker--day {
|
||||||
|
color: $c-void;
|
||||||
|
font-weight: 400;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $c-laser;
|
||||||
|
color: $g20-white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-picker--day-in-month {
|
||||||
|
color: $c-star;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $c-laser;
|
||||||
|
color: $g20-white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day--selected {
|
||||||
|
background-color: $c-pool;
|
||||||
|
color: $g18-cloud;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__triangle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__header {
|
||||||
|
border-radius: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
|
.react-datepicker__day-name {
|
||||||
|
color: $c-rainforest;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__current-month {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: $ix-radius $ix-radius 0 0;
|
||||||
|
background-color: $g4-onyx;
|
||||||
|
color: $g18-cloud;
|
||||||
|
font-weight: 700;
|
||||||
|
height: $ix-marg-d;
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__time-container {
|
||||||
|
width: 70px;
|
||||||
|
border: none;
|
||||||
|
margin-left: $ix-marg-a;
|
||||||
|
border-radius: $ix-radius;
|
||||||
|
background-color: transparent;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.react-datepicker__header--time {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: $ix-radius $ix-radius 0 0;
|
||||||
|
background-color: $g4-onyx;
|
||||||
|
font-weight: 700;
|
||||||
|
height: $ix-marg-d;
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker-time__header {
|
||||||
|
color: $g18-cloud;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__time {
|
||||||
|
background-color: transparent;
|
||||||
|
|
||||||
|
.react-datepicker__time-box {
|
||||||
|
width: 100%;
|
||||||
|
background-color: $g2-kevlar;
|
||||||
|
color: $g18-cloud;
|
||||||
|
|
||||||
|
.react-datepicker__time-list {
|
||||||
|
font-size: $ix-text-base;
|
||||||
|
|
||||||
|
.react-datepicker__time-list-item:hover {
|
||||||
|
background-color: $c-laser;
|
||||||
|
color: $g20-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__time-list-item--selected {
|
||||||
|
background-color: $c-pool;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-picker--dismiss {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 5000;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
transform: translate(50%,-50%);
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
outline: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: $c-pool;
|
||||||
|
transition: background-color 0.25s ease;
|
||||||
|
border: 0;
|
||||||
|
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
width: 13px;
|
||||||
|
height: 3px;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
border-radius: 1px;
|
||||||
|
background-color: $g20-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
transform: translate(-50%, -50%) rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
transform: translate(-50%, -50%) rotate(-45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $c-laser;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,136 @@
|
||||||
|
// Libraries
|
||||||
|
import React, {PureComponent, createRef, CSSProperties} from 'react'
|
||||||
|
|
||||||
|
// Components
|
||||||
|
import DatePicker from 'src/shared/components/dateRangePicker/DatePicker'
|
||||||
|
import {ClickOutside} from 'src/shared/components/ClickOutside'
|
||||||
|
|
||||||
|
// Styles
|
||||||
|
import 'src/shared/components/dateRangePicker/DateRangePicker.scss'
|
||||||
|
|
||||||
|
// Types
|
||||||
|
import {TimeRange} from 'src/types'
|
||||||
|
import {Button, ComponentColor, ComponentSize} from '@influxdata/clockface'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
timeRange: TimeRange
|
||||||
|
onSetTimeRange: (timeRange: TimeRange) => void
|
||||||
|
position?: {top: number; right: number}
|
||||||
|
onClose: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
lower: string
|
||||||
|
upper: string
|
||||||
|
bottomPosition?: number
|
||||||
|
topPosition?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const PICKER_HEIGHT = 410
|
||||||
|
const HORIZONTAL_PADDING = 2
|
||||||
|
const VERTICAL_PADDING = 15
|
||||||
|
|
||||||
|
class DateRangePicker extends PureComponent<Props, State> {
|
||||||
|
private rangePickerRef = createRef<HTMLDivElement>()
|
||||||
|
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props)
|
||||||
|
const {
|
||||||
|
timeRange: {lower, upper},
|
||||||
|
} = props
|
||||||
|
|
||||||
|
this.state = {lower, upper, bottomPosition: null}
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentDidMount() {
|
||||||
|
const {
|
||||||
|
bottom,
|
||||||
|
top,
|
||||||
|
height,
|
||||||
|
} = this.rangePickerRef.current.getBoundingClientRect()
|
||||||
|
|
||||||
|
if (bottom > window.innerHeight) {
|
||||||
|
this.setState({bottomPosition: height / 2})
|
||||||
|
} else if (top < 0) {
|
||||||
|
this.setState({topPosition: height / 2})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
const {onClose} = this.props
|
||||||
|
const {upper, lower} = this.state
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ClickOutside onClickOutside={onClose}>
|
||||||
|
<div
|
||||||
|
className="range-picker react-datepicker-ignore-onclickoutside"
|
||||||
|
ref={this.rangePickerRef}
|
||||||
|
style={this.stylePosition}
|
||||||
|
>
|
||||||
|
<button className="range-picker--dismiss" onClick={onClose} />
|
||||||
|
<div className="range-picker--date-pickers">
|
||||||
|
<DatePicker
|
||||||
|
dateTime={lower}
|
||||||
|
onSelectDate={this.handleSelectLower}
|
||||||
|
label="Start"
|
||||||
|
/>
|
||||||
|
<DatePicker
|
||||||
|
dateTime={upper}
|
||||||
|
onSelectDate={this.handleSelectUpper}
|
||||||
|
label="Stop"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
color={ComponentColor.Primary}
|
||||||
|
size={ComponentSize.Small}
|
||||||
|
onClick={this.handleSetTimeRange}
|
||||||
|
text="Apply Time Range"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</ClickOutside>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private get stylePosition(): CSSProperties {
|
||||||
|
const {position} = this.props
|
||||||
|
const {bottomPosition, topPosition} = this.state
|
||||||
|
|
||||||
|
if (!position) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const {top, right} = position
|
||||||
|
|
||||||
|
if (topPosition) {
|
||||||
|
return {
|
||||||
|
top: '14px',
|
||||||
|
right: `${right + HORIZONTAL_PADDING}px`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bottomPx =
|
||||||
|
(bottomPosition || window.innerHeight - top - VERTICAL_PADDING) -
|
||||||
|
PICKER_HEIGHT / 2
|
||||||
|
return {
|
||||||
|
bottom: `${bottomPx}px`,
|
||||||
|
right: `${right + HORIZONTAL_PADDING}px`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleSetTimeRange = (): void => {
|
||||||
|
const {onSetTimeRange, timeRange} = this.props
|
||||||
|
const {upper, lower} = this.state
|
||||||
|
|
||||||
|
onSetTimeRange({...timeRange, lower, upper})
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleSelectLower = (lower: string): void => {
|
||||||
|
this.setState({lower})
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleSelectUpper = (upper: string): void => {
|
||||||
|
this.setState({upper})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DateRangePicker
|
|
@ -410,6 +410,7 @@ export const LAYOUT_MARGIN = 4
|
||||||
export const DASHBOARD_LAYOUT_ROW_HEIGHT = 83.5
|
export const DASHBOARD_LAYOUT_ROW_HEIGHT = 83.5
|
||||||
|
|
||||||
export const TIME_RANGE_START = 'timeRangeStart'
|
export const TIME_RANGE_START = 'timeRangeStart'
|
||||||
|
export const TIME_RANGE_STOP = 'timeRangeStop'
|
||||||
export const WINDOW_PERIOD = 'windowPeriod'
|
export const WINDOW_PERIOD = 'windowPeriod'
|
||||||
|
|
||||||
export const DYGRAPH_CONTAINER_H_MARGIN = 16
|
export const DYGRAPH_CONTAINER_H_MARGIN = 16
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
import {TimeRange} from 'src/types'
|
import {TimeRange} from 'src/types'
|
||||||
|
|
||||||
|
export const CUSTOM_TIME_RANGE = 'Custom Time Range'
|
||||||
|
export const TIME_RANGE_FORMAT = 'YYYY-MM-DD HH:mm'
|
||||||
|
|
||||||
export const TIME_RANGES: TimeRange[] = [
|
export const TIME_RANGES: TimeRange[] = [
|
||||||
|
{
|
||||||
|
lower: '',
|
||||||
|
label: CUSTOM_TIME_RANGE,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
seconds: 300,
|
seconds: 300,
|
||||||
lower: 'now() - 5m',
|
lower: 'now() - 5m',
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {TimeRange} from 'src/types/v2'
|
import {TimeRange} from 'src/types/v2'
|
||||||
import {TIME_RANGE_START} from 'src/shared/constants'
|
import {TIME_RANGE_START, TIME_RANGE_STOP} from 'src/shared/constants'
|
||||||
|
|
||||||
export const timeRangeVariables = (
|
export const timeRangeVariables = (
|
||||||
timeRange: TimeRange
|
timeRange: TimeRange
|
||||||
|
@ -10,5 +10,11 @@ export const timeRangeVariables = (
|
||||||
.replace('now()', '')
|
.replace('now()', '')
|
||||||
.replace(/\s/g, '')
|
.replace(/\s/g, '')
|
||||||
|
|
||||||
|
if (timeRange.upper) {
|
||||||
|
result[TIME_RANGE_STOP] = timeRange.upper
|
||||||
|
} else {
|
||||||
|
result[TIME_RANGE_STOP] = 'now()'
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,45 +121,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.flux-functions-toolbar--tooltip-dismiss {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 5000;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
transform: translate(0,-50%);
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
outline: none;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: $c-pool;
|
|
||||||
transition: background-color 0.25s ease;
|
|
||||||
border: 0;
|
|
||||||
|
|
||||||
&:before,
|
|
||||||
&:after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
width: 13px;
|
|
||||||
height: 3px;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
border-radius: 1px;
|
|
||||||
background-color: $g20-white;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
transform: translate(-50%, -50%) rotate(45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
transform: translate(-50%, -50%) rotate(-45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $c-laser;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.flux-functions-toolbar--tooltip-dismiss {
|
.flux-functions-toolbar--tooltip-dismiss {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -11,7 +11,7 @@ describe('buildQuery', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const expected = `from(bucket: "b0")
|
const expected = `from(bucket: "b0")
|
||||||
|> range(start: timeRangeStart)
|
|> range(start: timeRangeStart, stop: timeRangeStop)
|
||||||
|> filter(fn: (r) => r._measurement == "m0")`
|
|> filter(fn: (r) => r._measurement == "m0")`
|
||||||
|
|
||||||
const actual = buildQuery(config)
|
const actual = buildQuery(config)
|
||||||
|
@ -30,7 +30,7 @@ describe('buildQuery', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const expected = `from(bucket: "b0")
|
const expected = `from(bucket: "b0")
|
||||||
|> range(start: timeRangeStart)
|
|> range(start: timeRangeStart, stop: timeRangeStop)
|
||||||
|> filter(fn: (r) => r._measurement == "m0" or r._measurement == "m1")
|
|> filter(fn: (r) => r._measurement == "m0" or r._measurement == "m1")
|
||||||
|> filter(fn: (r) => r._field == "f0" or r._field == "f1")`
|
|> filter(fn: (r) => r._field == "f0" or r._field == "f1")`
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ describe('buildQuery', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const expected = `from(bucket: "b0")
|
const expected = `from(bucket: "b0")
|
||||||
|> range(start: timeRangeStart)
|
|> range(start: timeRangeStart, stop: timeRangeStop)
|
||||||
|> filter(fn: (r) => r._measurement == "m0")
|
|> filter(fn: (r) => r._measurement == "m0")
|
||||||
|> window(period: windowPeriod)
|
|> window(period: windowPeriod)
|
||||||
|> mean()
|
|> mean()
|
||||||
|
@ -55,7 +55,7 @@ describe('buildQuery', () => {
|
||||||
|> yield(name: "mean")
|
|> yield(name: "mean")
|
||||||
|
|
||||||
from(bucket: "b0")
|
from(bucket: "b0")
|
||||||
|> range(start: timeRangeStart)
|
|> range(start: timeRangeStart, stop: timeRangeStop)
|
||||||
|> filter(fn: (r) => r._measurement == "m0")
|
|> filter(fn: (r) => r._measurement == "m0")
|
||||||
|> window(period: windowPeriod)
|
|> window(period: windowPeriod)
|
||||||
|> toFloat()
|
|> toFloat()
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
import {BuilderConfig} from 'src/types/v2'
|
import {BuilderConfig} from 'src/types/v2'
|
||||||
import {FUNCTIONS} from 'src/timeMachine/constants/queryBuilder'
|
import {FUNCTIONS} from 'src/timeMachine/constants/queryBuilder'
|
||||||
import {TIME_RANGE_START, WINDOW_PERIOD} from 'src/shared/constants'
|
import {
|
||||||
|
TIME_RANGE_START,
|
||||||
|
WINDOW_PERIOD,
|
||||||
|
TIME_RANGE_STOP,
|
||||||
|
} from 'src/shared/constants'
|
||||||
|
|
||||||
export function isConfigValid(builderConfig: BuilderConfig): boolean {
|
export function isConfigValid(builderConfig: BuilderConfig): boolean {
|
||||||
const {buckets, tags} = builderConfig
|
const {buckets, tags} = builderConfig
|
||||||
|
@ -35,7 +39,7 @@ function buildQueryHelper(
|
||||||
const fnCall = fn ? formatFunctionCall(fn) : ''
|
const fnCall = fn ? formatFunctionCall(fn) : ''
|
||||||
|
|
||||||
const query = `from(bucket: "${bucket}")
|
const query = `from(bucket: "${bucket}")
|
||||||
|> range(start: ${TIME_RANGE_START})${tagFilterCall}${fnCall}`
|
|> range(start: ${TIME_RANGE_START}, stop: ${TIME_RANGE_STOP})${tagFilterCall}${fnCall}`
|
||||||
|
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue