mirror of
https://github.com/prymitive/karma
synced 2026-05-07 03:26:52 +00:00
Merge pull request #46 from prymitive/silence-form-tweaks
refactor(ui): refactor silence form
This commit is contained in:
163
ui/package-lock.json
generated
163
ui/package-lock.json
generated
@@ -202,14 +202,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"add-dom-event-listener": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/add-dom-event-listener/-/add-dom-event-listener-1.0.2.tgz",
|
||||
"integrity": "sha1-j67SxBAIchzxEdodMNmVuFvkK+0=",
|
||||
"requires": {
|
||||
"object-assign": "4.1.1"
|
||||
}
|
||||
},
|
||||
"address": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/address/-/address-1.0.3.tgz",
|
||||
@@ -2322,24 +2314,11 @@
|
||||
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.3.0.tgz",
|
||||
"integrity": "sha512-MAAAIOdi2s4Gl6rZ76PNcUa9IOYB+5ICdT41o5uMRf09aEu/F9RK+qhe8RjXNPwcTjGV7KU7h2P/fljThFVqyQ=="
|
||||
},
|
||||
"component-classes": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/component-classes/-/component-classes-1.2.6.tgz",
|
||||
"integrity": "sha1-xkI5TDYYpNiwuJGe/Mu9kw5c1pE=",
|
||||
"requires": {
|
||||
"component-indexof": "0.0.3"
|
||||
}
|
||||
},
|
||||
"component-emitter": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
|
||||
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
|
||||
},
|
||||
"component-indexof": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/component-indexof/-/component-indexof-0.0.3.tgz",
|
||||
"integrity": "sha1-EdCRMSI5648yyPJa6csAL/6NPCQ="
|
||||
},
|
||||
"compressible": {
|
||||
"version": "2.0.14",
|
||||
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.14.tgz",
|
||||
@@ -2625,15 +2604,6 @@
|
||||
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
|
||||
"integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4="
|
||||
},
|
||||
"css-animation": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/css-animation/-/css-animation-1.4.1.tgz",
|
||||
"integrity": "sha1-W4gTEl3g+7uwu+G0cq6EIhRpt6g=",
|
||||
"requires": {
|
||||
"babel-runtime": "6.26.0",
|
||||
"component-classes": "1.2.6"
|
||||
}
|
||||
},
|
||||
"css-color-names": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
|
||||
@@ -3104,11 +3074,6 @@
|
||||
"esutils": "2.0.2"
|
||||
}
|
||||
},
|
||||
"dom-align": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.8.0.tgz",
|
||||
"integrity": "sha512-B85D4ef2Gj5lw0rK0KM2+D5/pH7yqNxg2mB+E8uzFaolpm7RQmsxEfjyEuNiF8UBBkffumYDeKRzTzc3LePP+w=="
|
||||
},
|
||||
"dom-converter": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.1.4.tgz",
|
||||
@@ -6949,11 +6914,6 @@
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
|
||||
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
|
||||
},
|
||||
"lodash._getnative": {
|
||||
"version": "3.9.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
|
||||
"integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U="
|
||||
},
|
||||
"lodash._reinterpolate": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
|
||||
@@ -7002,11 +6962,6 @@
|
||||
"integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.isarguments": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
|
||||
"integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo="
|
||||
},
|
||||
"lodash.isarray": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-4.0.0.tgz",
|
||||
@@ -7022,23 +6977,6 @@
|
||||
"resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz",
|
||||
"integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0="
|
||||
},
|
||||
"lodash.keys": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
|
||||
"integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
|
||||
"requires": {
|
||||
"lodash._getnative": "3.9.1",
|
||||
"lodash.isarguments": "3.1.0",
|
||||
"lodash.isarray": "3.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash.isarray": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
|
||||
"integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U="
|
||||
}
|
||||
}
|
||||
},
|
||||
"lodash.memoize": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
||||
@@ -9811,77 +9749,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"rc-align": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/rc-align/-/rc-align-2.4.3.tgz",
|
||||
"integrity": "sha512-h5KgyB5IXYR7iKpYFcMr54cuQ2eozPCZ11kbXPG5+6CWvmyJ+c0R/yjndVndiNk2G3MKcTMbJNdDv5DIckLAxQ==",
|
||||
"requires": {
|
||||
"babel-runtime": "6.26.0",
|
||||
"dom-align": "1.8.0",
|
||||
"prop-types": "15.6.2",
|
||||
"rc-util": "4.5.1"
|
||||
}
|
||||
},
|
||||
"rc-animate": {
|
||||
"version": "2.4.4",
|
||||
"resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-2.4.4.tgz",
|
||||
"integrity": "sha512-DjJLTUQj7XKKcuS8cczN0uOLfuSmgrVXFGieP1SZc87xUUTFGh8B/KjNmEtlfvxkSrSuVfb2rrEPER4SqKUtEA==",
|
||||
"requires": {
|
||||
"babel-runtime": "6.26.0",
|
||||
"css-animation": "1.4.1",
|
||||
"prop-types": "15.6.2"
|
||||
}
|
||||
},
|
||||
"rc-calendar": {
|
||||
"version": "9.7.0",
|
||||
"resolved": "https://registry.npmjs.org/rc-calendar/-/rc-calendar-9.7.0.tgz",
|
||||
"integrity": "sha512-067i3TC0H/6N6ZIhtbe9o/+F955n9nujNxn6Hoi6dJNr0LXc6F7305EI8N9k3zycx9JAliFQ1LF+MeFQwWRwpw==",
|
||||
"requires": {
|
||||
"babel-runtime": "6.26.0",
|
||||
"classnames": "2.2.6",
|
||||
"create-react-class": "15.6.3",
|
||||
"moment": "2.22.2",
|
||||
"prop-types": "15.6.2",
|
||||
"rc-trigger": "2.5.4",
|
||||
"rc-util": "4.5.1"
|
||||
}
|
||||
},
|
||||
"rc-time-picker": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/rc-time-picker/-/rc-time-picker-3.4.0.tgz",
|
||||
"integrity": "sha512-BgF0Fu/d36AK0h8jYBa01VWCm5vHWtYCh4DXBQhNazPLSH9hMP6JHLMJPSYMJ9jKttdE18O+F3j0mVQCL8JpDg==",
|
||||
"requires": {
|
||||
"babel-runtime": "6.26.0",
|
||||
"classnames": "2.2.6",
|
||||
"moment": "2.22.2",
|
||||
"prop-types": "15.6.2",
|
||||
"rc-trigger": "2.5.4"
|
||||
}
|
||||
},
|
||||
"rc-trigger": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-2.5.4.tgz",
|
||||
"integrity": "sha512-clgXOdazDW2qg4vTZSAExpvOuojPNuMoamG+SxAm5Ih+rpVcrtEiDlDZWY4yUHyfEWJZBzgbrr4np/z2FK6RfA==",
|
||||
"requires": {
|
||||
"babel-runtime": "6.26.0",
|
||||
"classnames": "2.2.6",
|
||||
"prop-types": "15.6.2",
|
||||
"rc-align": "2.4.3",
|
||||
"rc-animate": "2.4.4",
|
||||
"rc-util": "4.5.1"
|
||||
}
|
||||
},
|
||||
"rc-util": {
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/rc-util/-/rc-util-4.5.1.tgz",
|
||||
"integrity": "sha512-PdCmHyBBodZdw6Oaikt0l+/R79IcRXpYkTrqD/Rbl4ZdoOi61t5TtEe40Q+A7rkWG5U1xjcN+h8j9H6GdtnICw==",
|
||||
"requires": {
|
||||
"add-dom-event-listener": "1.0.2",
|
||||
"babel-runtime": "6.26.0",
|
||||
"prop-types": "15.6.2",
|
||||
"shallowequal": "0.2.2"
|
||||
}
|
||||
},
|
||||
"react": {
|
||||
"version": "16.4.2",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-16.4.2.tgz",
|
||||
@@ -9913,6 +9780,28 @@
|
||||
"section-iterator": "2.0.0"
|
||||
}
|
||||
},
|
||||
"react-datepicker": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-1.6.0.tgz",
|
||||
"integrity": "sha512-wfFfw3Tn+CCTtP7PPPhSAfkfVT3UTifFb8BmuhtwWKK3g4S83EEPRQE18XFtxd22dKGqp336NVtDTTyUJ1p9+g==",
|
||||
"requires": {
|
||||
"classnames": "2.2.6",
|
||||
"prop-types": "15.6.2",
|
||||
"react-onclickoutside": "6.7.1",
|
||||
"react-popper": "0.9.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-popper": {
|
||||
"version": "0.9.5",
|
||||
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-0.9.5.tgz",
|
||||
"integrity": "sha1-AqJO8+7DOvnlToNYq3DrDjMe3QU=",
|
||||
"requires": {
|
||||
"popper.js": "1.14.4",
|
||||
"prop-types": "15.6.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-dev-utils": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-5.0.1.tgz",
|
||||
@@ -11006,14 +10895,6 @@
|
||||
"resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.0.0.tgz",
|
||||
"integrity": "sha1-UI0YOLPeWQq4dXsBGyXkMJAJRfc="
|
||||
},
|
||||
"shallowequal": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-0.2.2.tgz",
|
||||
"integrity": "sha1-HjL9W8q2rWiKSBLLDMBO/HXHAU4=",
|
||||
"requires": {
|
||||
"lodash.keys": "3.1.2"
|
||||
}
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
|
||||
|
||||
@@ -25,10 +25,9 @@
|
||||
"prop-types": "15.6.2",
|
||||
"qs": "6.5.2",
|
||||
"raven-js": "3.26.4",
|
||||
"rc-calendar": "9.7.0",
|
||||
"rc-time-picker": "3.4.0",
|
||||
"react": "16.4.2",
|
||||
"react-autosuggest": "9.3.4",
|
||||
"react-datepicker": "1.6.0",
|
||||
"react-dom": "16.4.2",
|
||||
"react-highlighter": "0.4.2",
|
||||
"react-input-range": "1.3.0",
|
||||
|
||||
66
ui/src/Components/SilenceModal/DateTimeSelect/Duration.js
Normal file
66
ui/src/Components/SilenceModal/DateTimeSelect/Duration.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { observer } from "mobx-react";
|
||||
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faAngleUp } from "@fortawesome/free-solid-svg-icons/faAngleUp";
|
||||
import { faAngleDown } from "@fortawesome/free-solid-svg-icons/faAngleDown";
|
||||
|
||||
const Duration = observer(
|
||||
class Duration extends Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.number.isRequired,
|
||||
label: PropTypes.string,
|
||||
onInc: PropTypes.func.isRequired,
|
||||
onDec: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
render() {
|
||||
const { value, label, onInc, onDec } = this.props;
|
||||
|
||||
return (
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="text-center">
|
||||
<span onClick={onInc}>
|
||||
<FontAwesomeIcon
|
||||
icon={faAngleUp}
|
||||
size="2x"
|
||||
className="text-muted cursor-pointer"
|
||||
/>
|
||||
</span>
|
||||
</td>
|
||||
<td width="50%" />
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-center">
|
||||
<h2>{value}</h2>
|
||||
</td>
|
||||
<td width="50%">
|
||||
{label ? (
|
||||
<span className="text-muted ml-2">{label}</span>
|
||||
) : null}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-center">
|
||||
<span onClick={onDec}>
|
||||
<FontAwesomeIcon
|
||||
icon={faAngleDown}
|
||||
size="2x"
|
||||
className="text-muted cursor-pointer"
|
||||
/>
|
||||
</span>
|
||||
</td>
|
||||
<td width="50%" />
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export { Duration };
|
||||
81
ui/src/Components/SilenceModal/DateTimeSelect/HourMinute.js
Normal file
81
ui/src/Components/SilenceModal/DateTimeSelect/HourMinute.js
Normal file
@@ -0,0 +1,81 @@
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { observer } from "mobx-react";
|
||||
|
||||
import moment from "moment";
|
||||
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faAngleUp } from "@fortawesome/free-solid-svg-icons/faAngleUp";
|
||||
import { faAngleDown } from "@fortawesome/free-solid-svg-icons/faAngleDown";
|
||||
|
||||
const IconTd = ({ icon, onClick }) => (
|
||||
<td>
|
||||
<span onClick={onClick}>
|
||||
<FontAwesomeIcon
|
||||
icon={icon}
|
||||
size="2x"
|
||||
className="text-muted cursor-pointer"
|
||||
/>
|
||||
</span>
|
||||
</td>
|
||||
);
|
||||
IconTd.propTypes = {
|
||||
icon: PropTypes.object.isRequired,
|
||||
onClick: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
const HourMinute = observer(
|
||||
class HourMinute extends Component {
|
||||
static propTypes = {
|
||||
dateValue: PropTypes.instanceOf(moment).isRequired,
|
||||
onHourInc: PropTypes.func.isRequired,
|
||||
onHourDec: PropTypes.func.isRequired,
|
||||
onMinuteInc: PropTypes.func.isRequired,
|
||||
onMinuteDec: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
dateValue,
|
||||
onHourInc,
|
||||
onHourDec,
|
||||
onMinuteInc,
|
||||
onMinuteDec
|
||||
} = this.props;
|
||||
|
||||
const hour = dateValue.hour();
|
||||
const minute = dateValue.minute();
|
||||
|
||||
return (
|
||||
<table className="text-center border-0 my-auto">
|
||||
<tbody>
|
||||
<tr>
|
||||
<IconTd icon={faAngleUp} onClick={onHourInc} />
|
||||
<td />
|
||||
<IconTd icon={faAngleUp} onClick={onMinuteInc} />
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<h2>{hour > 9 ? hour : `0${hour}`}</h2>
|
||||
</td>
|
||||
<td>
|
||||
<h2 className="mx-2">:</h2>
|
||||
</td>
|
||||
<td>
|
||||
<h2>{minute > 9 ? minute : `0${minute}`}</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<IconTd icon={faAngleDown} onClick={onHourDec} />
|
||||
<td />
|
||||
<IconTd icon={faAngleDown} onClick={onMinuteDec} />
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export { HourMinute };
|
||||
484
ui/src/Components/SilenceModal/DateTimeSelect/index.css
Normal file
484
ui/src/Components/SilenceModal/DateTimeSelect/index.css
Normal file
@@ -0,0 +1,484 @@
|
||||
.react-datepicker-popper[data-placement^="bottom"] .react-datepicker__triangle, .react-datepicker-popper[data-placement^="top"] .react-datepicker__triangle, .react-datepicker__year-read-view--down-arrow,
|
||||
.react-datepicker__month-read-view--down-arrow,
|
||||
.react-datepicker__month-year-read-view--down-arrow {
|
||||
margin-left: -8px;
|
||||
position: absolute; }
|
||||
.react-datepicker-popper[data-placement^="bottom"] .react-datepicker__triangle, .react-datepicker-popper[data-placement^="top"] .react-datepicker__triangle, .react-datepicker__year-read-view--down-arrow,
|
||||
.react-datepicker__month-read-view--down-arrow,
|
||||
.react-datepicker__month-year-read-view--down-arrow, .react-datepicker-popper[data-placement^="bottom"] .react-datepicker__triangle::before, .react-datepicker-popper[data-placement^="top"] .react-datepicker__triangle::before, .react-datepicker__year-read-view--down-arrow::before,
|
||||
.react-datepicker__month-read-view--down-arrow::before,
|
||||
.react-datepicker__month-year-read-view--down-arrow::before {
|
||||
box-sizing: content-box;
|
||||
position: absolute;
|
||||
border: 8px solid transparent;
|
||||
height: 0;
|
||||
width: 1px; }
|
||||
.react-datepicker-popper[data-placement^="bottom"] .react-datepicker__triangle::before, .react-datepicker-popper[data-placement^="top"] .react-datepicker__triangle::before, .react-datepicker__year-read-view--down-arrow::before,
|
||||
.react-datepicker__month-read-view--down-arrow::before,
|
||||
.react-datepicker__month-year-read-view--down-arrow::before {
|
||||
content: "";
|
||||
z-index: -1;
|
||||
border-width: 8px;
|
||||
left: -8px;
|
||||
border-bottom-color: #dee2e6; }
|
||||
|
||||
.react-datepicker-popper[data-placement^="bottom"] .react-datepicker__triangle {
|
||||
top: 0;
|
||||
margin-top: -8px; }
|
||||
.react-datepicker-popper[data-placement^="bottom"] .react-datepicker__triangle, .react-datepicker-popper[data-placement^="bottom"] .react-datepicker__triangle::before {
|
||||
border-top: none;
|
||||
border-bottom-color: #fff; }
|
||||
.react-datepicker-popper[data-placement^="bottom"] .react-datepicker__triangle::before {
|
||||
top: -1px;
|
||||
border-bottom-color: #dee2e6; }
|
||||
|
||||
.react-datepicker-popper[data-placement^="top"] .react-datepicker__triangle, .react-datepicker__year-read-view--down-arrow,
|
||||
.react-datepicker__month-read-view--down-arrow,
|
||||
.react-datepicker__month-year-read-view--down-arrow {
|
||||
bottom: 0;
|
||||
margin-bottom: -8px; }
|
||||
.react-datepicker-popper[data-placement^="top"] .react-datepicker__triangle, .react-datepicker__year-read-view--down-arrow,
|
||||
.react-datepicker__month-read-view--down-arrow,
|
||||
.react-datepicker__month-year-read-view--down-arrow, .react-datepicker-popper[data-placement^="top"] .react-datepicker__triangle::before, .react-datepicker__year-read-view--down-arrow::before,
|
||||
.react-datepicker__month-read-view--down-arrow::before,
|
||||
.react-datepicker__month-year-read-view--down-arrow::before {
|
||||
border-bottom: none;
|
||||
border-top-color: #fff; }
|
||||
.react-datepicker-popper[data-placement^="top"] .react-datepicker__triangle::before, .react-datepicker__year-read-view--down-arrow::before,
|
||||
.react-datepicker__month-read-view--down-arrow::before,
|
||||
.react-datepicker__month-year-read-view--down-arrow::before {
|
||||
bottom: -1px;
|
||||
border-top-color: #dee2e6; }
|
||||
|
||||
.react-datepicker-wrapper {
|
||||
display: inline-block; }
|
||||
|
||||
.react-datepicker {
|
||||
font-family: "Lato", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
font-size: 0.9375rem;
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 0.25rem;
|
||||
display: inline-block;
|
||||
position: relative; }
|
||||
|
||||
.react-datepicker--time-only .react-datepicker__triangle {
|
||||
left: 35px; }
|
||||
|
||||
.react-datepicker--time-only .react-datepicker__time-container {
|
||||
border-left: 0; }
|
||||
|
||||
.react-datepicker--time-only .react-datepicker__time {
|
||||
border-radius: 0.3rem; }
|
||||
|
||||
.react-datepicker--time-only .react-datepicker__time-box {
|
||||
border-radius: 0.3rem; }
|
||||
|
||||
.react-datepicker__triangle {
|
||||
position: absolute;
|
||||
left: 50px; }
|
||||
|
||||
.react-datepicker-popper {
|
||||
z-index: 1; }
|
||||
.react-datepicker-popper[data-placement^="bottom"] {
|
||||
margin-top: 10px; }
|
||||
.react-datepicker-popper[data-placement^="top"] {
|
||||
margin-bottom: 10px; }
|
||||
.react-datepicker-popper[data-placement^="right"] {
|
||||
margin-left: 8px; }
|
||||
.react-datepicker-popper[data-placement^="right"] .react-datepicker__triangle {
|
||||
left: auto;
|
||||
right: 42px; }
|
||||
.react-datepicker-popper[data-placement^="left"] {
|
||||
margin-right: 8px; }
|
||||
.react-datepicker-popper[data-placement^="left"] .react-datepicker__triangle {
|
||||
left: 42px;
|
||||
right: auto; }
|
||||
|
||||
.react-datepicker__header {
|
||||
text-align: center;
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
border-top-left-radius: 0.25rem;
|
||||
border-top-right-radius: 0.25rem;
|
||||
padding-top: 8px;
|
||||
position: relative; }
|
||||
.react-datepicker__header--time {
|
||||
padding-bottom: 8px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px; }
|
||||
|
||||
.react-datepicker__year-dropdown-container--select,
|
||||
.react-datepicker__month-dropdown-container--select,
|
||||
.react-datepicker__month-year-dropdown-container--select,
|
||||
.react-datepicker__year-dropdown-container--scroll,
|
||||
.react-datepicker__month-dropdown-container--scroll,
|
||||
.react-datepicker__month-year-dropdown-container--scroll {
|
||||
display: inline-block;
|
||||
margin: 0 2px; }
|
||||
|
||||
.react-datepicker__current-month,
|
||||
.react-datepicker-time__header {
|
||||
margin-top: 0;
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
font-size: 1.10625rem; }
|
||||
|
||||
.react-datepicker-time__header {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden; }
|
||||
|
||||
.react-datepicker__navigation {
|
||||
background: none;
|
||||
line-height: 1.7rem;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
width: 0;
|
||||
padding: 0;
|
||||
border: 0.45rem solid transparent;
|
||||
z-index: 1;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
text-indent: -999em;
|
||||
overflow: hidden; }
|
||||
.react-datepicker__navigation--previous {
|
||||
left: 10px;
|
||||
border-right-color: #95a5a6; }
|
||||
.react-datepicker__navigation--previous:hover {
|
||||
border-right-color: #798d8f; }
|
||||
.react-datepicker__navigation--previous--disabled, .react-datepicker__navigation--previous--disabled:hover {
|
||||
border-right-color: #95a5a6;
|
||||
cursor: default; }
|
||||
.react-datepicker__navigation--next {
|
||||
right: 10px;
|
||||
border-left-color: #95a5a6; }
|
||||
.react-datepicker__navigation--next--with-time:not(.react-datepicker__navigation--next--with-today-button) {
|
||||
right: 80px; }
|
||||
.react-datepicker__navigation--next:hover {
|
||||
border-left-color: #798d8f; }
|
||||
.react-datepicker__navigation--next--disabled, .react-datepicker__navigation--next--disabled:hover {
|
||||
border-left-color: #95a5a6;
|
||||
cursor: default; }
|
||||
.react-datepicker__navigation--years {
|
||||
position: relative;
|
||||
top: 0;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto; }
|
||||
.react-datepicker__navigation--years-previous {
|
||||
top: 4px;
|
||||
border-top-color: #95a5a6; }
|
||||
.react-datepicker__navigation--years-previous:hover {
|
||||
border-top-color: #798d8f; }
|
||||
.react-datepicker__navigation--years-upcoming {
|
||||
top: -4px;
|
||||
border-bottom-color: #95a5a6; }
|
||||
.react-datepicker__navigation--years-upcoming:hover {
|
||||
border-bottom-color: #798d8f; }
|
||||
|
||||
.react-datepicker__month-container {
|
||||
float: left; }
|
||||
|
||||
.react-datepicker__month {
|
||||
margin: 0.4rem;
|
||||
text-align: center; }
|
||||
|
||||
.react-datepicker__time-container {
|
||||
float: right;
|
||||
border-left: 1px solid #dee2e6;
|
||||
width: 70px; }
|
||||
.react-datepicker__time-container--with-today-button {
|
||||
display: inline;
|
||||
border: 1px solid #aeaeae;
|
||||
border-radius: 0.3rem;
|
||||
position: absolute;
|
||||
right: -72px;
|
||||
top: 0; }
|
||||
.react-datepicker__time-container .react-datepicker__time {
|
||||
position: relative;
|
||||
background: white; }
|
||||
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box {
|
||||
width: 70px;
|
||||
overflow-x: hidden;
|
||||
margin: 0 auto;
|
||||
text-align: center; }
|
||||
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
height: calc(195px + (1.7rem / 2));
|
||||
overflow-y: scroll;
|
||||
padding-right: 30px;
|
||||
width: 100%;
|
||||
box-sizing: content-box; }
|
||||
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item {
|
||||
padding: 5px 10px; }
|
||||
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item:hover {
|
||||
cursor: pointer;
|
||||
background-color: #fff; }
|
||||
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--selected {
|
||||
background-color: #2C3E50;
|
||||
color: white;
|
||||
font-weight: bold; }
|
||||
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--selected:hover {
|
||||
background-color: #2C3E50; }
|
||||
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--disabled {
|
||||
color: #95a5a6; }
|
||||
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--disabled:hover {
|
||||
cursor: default;
|
||||
background-color: transparent; }
|
||||
|
||||
.react-datepicker__week-number {
|
||||
color: #95a5a6;
|
||||
display: inline-block;
|
||||
width: 1.7rem;
|
||||
line-height: 1.7rem;
|
||||
text-align: center;
|
||||
margin: 0.166rem; }
|
||||
.react-datepicker__week-number.react-datepicker__week-number--clickable {
|
||||
cursor: pointer; }
|
||||
.react-datepicker__week-number.react-datepicker__week-number--clickable:hover {
|
||||
border-radius: 0.25rem;
|
||||
background-color: #fff; }
|
||||
|
||||
.react-datepicker__day-names,
|
||||
.react-datepicker__week {
|
||||
white-space: nowrap; }
|
||||
|
||||
.react-datepicker__day-name,
|
||||
.react-datepicker__day,
|
||||
.react-datepicker__time-name {
|
||||
color: #000;
|
||||
display: inline-block;
|
||||
width: 1.7rem;
|
||||
line-height: 1.7rem;
|
||||
text-align: center;
|
||||
margin: 0.166rem; }
|
||||
|
||||
.react-datepicker__day {
|
||||
cursor: pointer; }
|
||||
.react-datepicker__day:hover {
|
||||
border-radius: 0.25rem;
|
||||
background-color: #fff; }
|
||||
.react-datepicker__day--today {
|
||||
font-weight: bold; }
|
||||
.react-datepicker__day--highlighted {
|
||||
border-radius: 0.25rem;
|
||||
background-color: #95a5a6;
|
||||
color: #fff; }
|
||||
.react-datepicker__day--highlighted:hover {
|
||||
background-color: #87999a; }
|
||||
.react-datepicker__day--highlighted-custom-1 {
|
||||
color: magenta; }
|
||||
.react-datepicker__day--highlighted-custom-2 {
|
||||
color: green; }
|
||||
.react-datepicker__day--selected, .react-datepicker__day--in-selecting-range, .react-datepicker__day--in-range {
|
||||
border-radius: 0.25rem;
|
||||
background-color: #2C3E50;
|
||||
color: #fff; }
|
||||
.react-datepicker__day--selected:hover, .react-datepicker__day--in-selecting-range:hover, .react-datepicker__day--in-range:hover {
|
||||
background-color: #233140; }
|
||||
.react-datepicker__day--keyboard-selected {
|
||||
border-radius: 0.25rem;
|
||||
background-color: #3e5871;
|
||||
color: #fff; }
|
||||
.react-datepicker__day--keyboard-selected:hover {
|
||||
background-color: #233140; }
|
||||
.react-datepicker__day--in-selecting-range:not(.react-datepicker__day--in-range) {
|
||||
background-color: rgba(44, 62, 80, 0.5); }
|
||||
.react-datepicker__month--selecting-range .react-datepicker__day--in-range:not(.react-datepicker__day--in-selecting-range) {
|
||||
background-color: #fff;
|
||||
color: #000; }
|
||||
.react-datepicker__day--disabled {
|
||||
cursor: default;
|
||||
color: #95a5a6; }
|
||||
.react-datepicker__day--disabled:hover {
|
||||
background-color: transparent; }
|
||||
|
||||
.react-datepicker__input-container {
|
||||
position: relative;
|
||||
display: inline-block; }
|
||||
|
||||
.react-datepicker__year-read-view,
|
||||
.react-datepicker__month-read-view,
|
||||
.react-datepicker__month-year-read-view {
|
||||
border: 1px solid transparent;
|
||||
border-radius: 0.25rem; }
|
||||
.react-datepicker__year-read-view:hover,
|
||||
.react-datepicker__month-read-view:hover,
|
||||
.react-datepicker__month-year-read-view:hover {
|
||||
cursor: pointer; }
|
||||
.react-datepicker__year-read-view:hover .react-datepicker__year-read-view--down-arrow,
|
||||
.react-datepicker__year-read-view:hover .react-datepicker__month-read-view--down-arrow,
|
||||
.react-datepicker__month-read-view:hover .react-datepicker__year-read-view--down-arrow,
|
||||
.react-datepicker__month-read-view:hover .react-datepicker__month-read-view--down-arrow,
|
||||
.react-datepicker__month-year-read-view:hover .react-datepicker__year-read-view--down-arrow,
|
||||
.react-datepicker__month-year-read-view:hover .react-datepicker__month-read-view--down-arrow {
|
||||
border-top-color: #798d8f; }
|
||||
.react-datepicker__year-read-view--down-arrow,
|
||||
.react-datepicker__month-read-view--down-arrow,
|
||||
.react-datepicker__month-year-read-view--down-arrow {
|
||||
border-top-color: #95a5a6;
|
||||
float: right;
|
||||
margin-left: 20px;
|
||||
top: 8px;
|
||||
position: relative;
|
||||
border-width: 0.45rem; }
|
||||
|
||||
.react-datepicker__year-dropdown,
|
||||
.react-datepicker__month-dropdown,
|
||||
.react-datepicker__month-year-dropdown {
|
||||
background-color: #fff;
|
||||
position: absolute;
|
||||
width: 50%;
|
||||
left: 25%;
|
||||
top: 30px;
|
||||
z-index: 1;
|
||||
text-align: center;
|
||||
border-radius: 0.25rem;
|
||||
border: 1px solid #dee2e6; }
|
||||
.react-datepicker__year-dropdown:hover,
|
||||
.react-datepicker__month-dropdown:hover,
|
||||
.react-datepicker__month-year-dropdown:hover {
|
||||
cursor: pointer; }
|
||||
.react-datepicker__year-dropdown--scrollable,
|
||||
.react-datepicker__month-dropdown--scrollable,
|
||||
.react-datepicker__month-year-dropdown--scrollable {
|
||||
height: 150px;
|
||||
overflow-y: scroll; }
|
||||
|
||||
.react-datepicker__year-option,
|
||||
.react-datepicker__month-option,
|
||||
.react-datepicker__month-year-option {
|
||||
line-height: 20px;
|
||||
width: 100%;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto; }
|
||||
.react-datepicker__year-option:first-of-type,
|
||||
.react-datepicker__month-option:first-of-type,
|
||||
.react-datepicker__month-year-option:first-of-type {
|
||||
border-top-left-radius: 0.25rem;
|
||||
border-top-right-radius: 0.25rem; }
|
||||
.react-datepicker__year-option:last-of-type,
|
||||
.react-datepicker__month-option:last-of-type,
|
||||
.react-datepicker__month-year-option:last-of-type {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
border-bottom-left-radius: 0.25rem;
|
||||
border-bottom-right-radius: 0.25rem; }
|
||||
.react-datepicker__year-option:hover,
|
||||
.react-datepicker__month-option:hover,
|
||||
.react-datepicker__month-year-option:hover {
|
||||
background-color: #95a5a6; }
|
||||
.react-datepicker__year-option:hover .react-datepicker__navigation--years-upcoming,
|
||||
.react-datepicker__month-option:hover .react-datepicker__navigation--years-upcoming,
|
||||
.react-datepicker__month-year-option:hover .react-datepicker__navigation--years-upcoming {
|
||||
border-bottom-color: #798d8f; }
|
||||
.react-datepicker__year-option:hover .react-datepicker__navigation--years-previous,
|
||||
.react-datepicker__month-option:hover .react-datepicker__navigation--years-previous,
|
||||
.react-datepicker__month-year-option:hover .react-datepicker__navigation--years-previous {
|
||||
border-top-color: #798d8f; }
|
||||
.react-datepicker__year-option--selected,
|
||||
.react-datepicker__month-option--selected,
|
||||
.react-datepicker__month-year-option--selected {
|
||||
position: absolute;
|
||||
left: 15px; }
|
||||
|
||||
.react-datepicker__close-icon {
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
outline: 0;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
position: absolute;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
top: 25%;
|
||||
right: 7px; }
|
||||
.react-datepicker__close-icon::after {
|
||||
background-color: #2C3E50;
|
||||
border-radius: 50%;
|
||||
bottom: 0;
|
||||
box-sizing: border-box;
|
||||
color: #fff;
|
||||
content: "\00d7";
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
line-height: 1;
|
||||
margin: -8px auto 0;
|
||||
padding: 2px;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
text-align: center; }
|
||||
|
||||
.react-datepicker__today-button {
|
||||
background: #fff;
|
||||
border-top: 1px solid #dee2e6;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
padding: 5px 0;
|
||||
clear: left; }
|
||||
|
||||
.react-datepicker__portal {
|
||||
position: fixed;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
left: 0;
|
||||
top: 0;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
z-index: 2147483647; }
|
||||
.react-datepicker__portal .react-datepicker__day-name,
|
||||
.react-datepicker__portal .react-datepicker__day,
|
||||
.react-datepicker__portal .react-datepicker__time-name {
|
||||
width: 3rem;
|
||||
line-height: 3rem; }
|
||||
@media (max-width: 400px), (max-height: 550px) {
|
||||
.react-datepicker__portal .react-datepicker__day-name,
|
||||
.react-datepicker__portal .react-datepicker__day,
|
||||
.react-datepicker__portal .react-datepicker__time-name {
|
||||
width: 2rem;
|
||||
line-height: 2rem; } }
|
||||
.react-datepicker__portal .react-datepicker__current-month,
|
||||
.react-datepicker__portal .react-datepicker-time__header {
|
||||
font-size: 1.6875rem; }
|
||||
.react-datepicker__portal .react-datepicker__navigation {
|
||||
border: 0.81rem solid transparent; }
|
||||
.react-datepicker__portal .react-datepicker__navigation--previous {
|
||||
border-right-color: #95a5a6; }
|
||||
.react-datepicker__portal .react-datepicker__navigation--previous:hover {
|
||||
border-right-color: #798d8f; }
|
||||
.react-datepicker__portal .react-datepicker__navigation--previous--disabled, .react-datepicker__portal .react-datepicker__navigation--previous--disabled:hover {
|
||||
border-right-color: #95a5a6;
|
||||
cursor: default; }
|
||||
.react-datepicker__portal .react-datepicker__navigation--next {
|
||||
border-left-color: #95a5a6; }
|
||||
.react-datepicker__portal .react-datepicker__navigation--next:hover {
|
||||
border-left-color: #798d8f; }
|
||||
.react-datepicker__portal .react-datepicker__navigation--next--disabled, .react-datepicker__portal .react-datepicker__navigation--next--disabled:hover {
|
||||
border-left-color: #95a5a6;
|
||||
cursor: default; }
|
||||
|
||||
.react-datepicker__day:not(.react-datepicker__day--disabled) {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: transparent; }
|
||||
|
||||
.react-datepicker__day:hover:not(.react-datepicker__day--disabled) {
|
||||
border-color: #dee2e6; }
|
||||
|
||||
.react-datepicker__today-button {
|
||||
border-bottom-left-radius: 0.25rem;
|
||||
border-bottom-right-radius: 0.25rem; }
|
||||
181
ui/src/Components/SilenceModal/DateTimeSelect/index.js
Normal file
181
ui/src/Components/SilenceModal/DateTimeSelect/index.js
Normal file
@@ -0,0 +1,181 @@
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { observable, action } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
|
||||
import moment from "moment";
|
||||
|
||||
import DatePicker from "react-datepicker";
|
||||
|
||||
import { Duration } from "./Duration";
|
||||
import { HourMinute } from "./HourMinute";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
const Tab = ({ title, active, onClick }) => (
|
||||
<li className="nav-item">
|
||||
<a
|
||||
className={`nav-link cursor-pointer ${
|
||||
active ? "active text-white" : "text-primary"
|
||||
}`}
|
||||
onClick={onClick}
|
||||
>
|
||||
{title}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
Tab.propTypes = {
|
||||
title: PropTypes.node.isRequired,
|
||||
active: PropTypes.bool,
|
||||
onClick: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
const TabNames = Object.freeze({
|
||||
Start: "start",
|
||||
End: "end",
|
||||
Duration: "duration"
|
||||
});
|
||||
|
||||
const TabContentStart = observer(({ silenceFormStore }) => {
|
||||
return (
|
||||
<div className="d-flex flex-sm-row flex-column justify-content-around mx-3 mt-2 ">
|
||||
<DatePicker
|
||||
inline
|
||||
todayButton={"Now"}
|
||||
minDate={moment()}
|
||||
selected={silenceFormStore.data.startsAt}
|
||||
onChange={val => {
|
||||
silenceFormStore.data.startsAt = moment(val);
|
||||
silenceFormStore.data.verifyStarEnd();
|
||||
}}
|
||||
/>
|
||||
<HourMinute
|
||||
dateValue={silenceFormStore.data.startsAt}
|
||||
onHourInc={() => silenceFormStore.data.incStart(60)}
|
||||
onHourDec={() => silenceFormStore.data.decStart(60)}
|
||||
onMinuteInc={() => silenceFormStore.data.incStart(1)}
|
||||
onMinuteDec={() => silenceFormStore.data.decStart(1)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const TabContentEnd = observer(({ silenceFormStore }) => {
|
||||
return (
|
||||
<div className="d-flex flex-sm-row flex-column justify-content-around mx-3 mt-2 ">
|
||||
<DatePicker
|
||||
inline
|
||||
todayButton={"Now"}
|
||||
minDate={moment()}
|
||||
selected={silenceFormStore.data.endsAt}
|
||||
onChange={val => {
|
||||
silenceFormStore.data.endsAt = moment(val);
|
||||
silenceFormStore.data.verifyStarEnd();
|
||||
}}
|
||||
/>
|
||||
<HourMinute
|
||||
dateValue={silenceFormStore.data.endsAt}
|
||||
onHourInc={() => silenceFormStore.data.incEnd(60)}
|
||||
onHourDec={() => silenceFormStore.data.decEnd(60)}
|
||||
onMinuteInc={() => silenceFormStore.data.incEnd(1)}
|
||||
onMinuteDec={() => silenceFormStore.data.decEnd(1)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const TabContentDuration = observer(({ silenceFormStore }) => {
|
||||
return (
|
||||
<div className="d-flex flex-sm-row flex-column justify-content-around mt-2 mx-3">
|
||||
<Duration
|
||||
label="days"
|
||||
value={silenceFormStore.data.toDuration.days}
|
||||
onInc={() => silenceFormStore.data.incDuration(60 * 24)}
|
||||
onDec={() => silenceFormStore.data.decDuration(60 * 24)}
|
||||
/>
|
||||
<Duration
|
||||
label="hours"
|
||||
value={silenceFormStore.data.toDuration.hours}
|
||||
onInc={() => silenceFormStore.data.incDuration(60)}
|
||||
onDec={() => silenceFormStore.data.decDuration(60)}
|
||||
/>
|
||||
<Duration
|
||||
label="minutes"
|
||||
value={silenceFormStore.data.toDuration.minutes}
|
||||
onInc={() => silenceFormStore.data.incDuration(1)}
|
||||
onDec={() => silenceFormStore.data.decDuration(1)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
TabContentDuration.propTypes = {
|
||||
silenceFormStore: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
const DateTimeSelect = observer(
|
||||
class DateTimeSelect extends Component {
|
||||
static propTypes = {
|
||||
silenceFormStore: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
tab = observable(
|
||||
{
|
||||
current: TabNames.Duration,
|
||||
setStart() {
|
||||
this.current = TabNames.Start;
|
||||
},
|
||||
setEnd() {
|
||||
this.current = TabNames.End;
|
||||
},
|
||||
setDuration() {
|
||||
this.current = TabNames.Duration;
|
||||
}
|
||||
},
|
||||
{
|
||||
setStart: action.bound,
|
||||
setEnd: action.bound,
|
||||
setDuration: action.bound
|
||||
}
|
||||
);
|
||||
|
||||
render() {
|
||||
const { silenceFormStore } = this.props;
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<ul className="nav nav-tabs nav-fill">
|
||||
<Tab
|
||||
title="Start"
|
||||
active={this.tab.current === TabNames.Start}
|
||||
onClick={this.tab.setStart}
|
||||
/>
|
||||
<Tab
|
||||
title="End"
|
||||
active={this.tab.current === TabNames.End}
|
||||
onClick={this.tab.setEnd}
|
||||
/>
|
||||
<Tab
|
||||
title="Duration"
|
||||
active={this.tab.current === TabNames.Duration}
|
||||
onClick={this.tab.setDuration}
|
||||
/>
|
||||
</ul>
|
||||
<div className="tab-content mb-3">
|
||||
{this.tab.current === TabNames.Duration ? (
|
||||
<TabContentDuration silenceFormStore={silenceFormStore} />
|
||||
) : null}
|
||||
{this.tab.current === TabNames.Start ? (
|
||||
<TabContentStart silenceFormStore={silenceFormStore} />
|
||||
) : null}
|
||||
{this.tab.current === TabNames.End ? (
|
||||
<TabContentEnd silenceFormStore={silenceFormStore} />
|
||||
) : null}
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export { DateTimeSelect };
|
||||
29
ui/src/Components/SilenceModal/DateTimeSelect/index.scss
Normal file
29
ui/src/Components/SilenceModal/DateTimeSelect/index.scss
Normal file
@@ -0,0 +1,29 @@
|
||||
@import "../../../../node_modules/bootswatch/dist/flatly/variables";
|
||||
|
||||
$datepicker__background-color: $white;
|
||||
$datepicker__border-color: $gray-300;
|
||||
$datepicker__highlighted-color: $secondary;
|
||||
$datepicker__muted-color: $gray-600;
|
||||
$datepicker__selected-color: $primary;
|
||||
$datepicker__text-color: $black;
|
||||
$datepicker__header-color: $black;
|
||||
$datepicker__navigation-disabled-color: $gray-600;
|
||||
$datepicker__font-size: $font-size-base;
|
||||
$datepicker__font-family: $font-family-sans-serif;
|
||||
$datepicker__border-radius: 0.25rem;
|
||||
|
||||
@import "../../../../node_modules/react-datepicker/src/stylesheets/datepicker.scss";
|
||||
|
||||
.react-datepicker__day:not(.react-datepicker__day--disabled) {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: transparent;
|
||||
}
|
||||
.react-datepicker__day:hover:not(.react-datepicker__day--disabled) {
|
||||
border-color: $datepicker__border-color;
|
||||
}
|
||||
|
||||
.react-datepicker__today-button {
|
||||
border-bottom-left-radius: $datepicker__border-radius;
|
||||
border-bottom-right-radius: $datepicker__border-radius;
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown";
|
||||
|
||||
import { AlertManagerInput } from "./AlertManagerInput";
|
||||
import { SilenceMatch } from "./SilenceMatch";
|
||||
import { SilenceStartEnd } from "./SilenceStartEnd";
|
||||
import { DateTimeSelect } from "./DateTimeSelect";
|
||||
import { SilencePreview } from "./SilencePreview";
|
||||
|
||||
const IconInput = ({ icon, placeholder, value, onChange }) => (
|
||||
@@ -124,7 +124,7 @@ const SilenceForm = observer(
|
||||
>
|
||||
<FontAwesomeIcon icon={faPlus} />
|
||||
</button>
|
||||
<SilenceStartEnd silenceFormStore={silenceFormStore} />
|
||||
<DateTimeSelect silenceFormStore={silenceFormStore} />
|
||||
<IconInput
|
||||
placeholder="Author"
|
||||
icon={faUser}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
.rc-calendar {
|
||||
font-family: inherit;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.rc-calendar-picker {
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.rc-calendar-selected-day > .rc-calendar-date {
|
||||
border: 0;
|
||||
color: #fff;
|
||||
background-color: #455a64;
|
||||
}
|
||||
|
||||
.rc-calendar-today .rc-calendar-date {
|
||||
border-color: #7b8a8b;
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { observable, action, toJS } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
|
||||
import moment from "moment";
|
||||
|
||||
import Picker from "rc-calendar/lib/Picker";
|
||||
import RangeCalendar from "rc-calendar/lib/RangeCalendar";
|
||||
import "rc-calendar/assets/index.css";
|
||||
|
||||
import TimePickerPanel from "rc-time-picker/lib/Panel";
|
||||
import "rc-time-picker/assets/index.css";
|
||||
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faCalendarAlt } from "@fortawesome/free-solid-svg-icons/faCalendarAlt";
|
||||
|
||||
import "./SilenceStartEnd.css";
|
||||
|
||||
function disabledDate(current) {
|
||||
if (!current) return false;
|
||||
|
||||
const date = moment();
|
||||
date.hour(0);
|
||||
date.minute(0);
|
||||
date.second(0);
|
||||
return current.isBefore(date);
|
||||
}
|
||||
|
||||
function isValidRange(v) {
|
||||
return v && v[0] && v[1];
|
||||
}
|
||||
|
||||
const format = "YYYY-MM-DD HH:mm";
|
||||
function formatTimestamp(v) {
|
||||
return v ? v.format(format) : "";
|
||||
}
|
||||
|
||||
const timePickerElement = (
|
||||
<TimePickerPanel
|
||||
defaultValue={[
|
||||
moment().second(0),
|
||||
moment()
|
||||
.second(0)
|
||||
.add(1, "minute")
|
||||
]}
|
||||
showSecond={false}
|
||||
/>
|
||||
);
|
||||
|
||||
const SilenceStartEnd = observer(
|
||||
class SilenceStartEnd extends Component {
|
||||
static propTypes = {
|
||||
silenceFormStore: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
data = observable({
|
||||
hoverValue: []
|
||||
});
|
||||
|
||||
onChange = action(value => {
|
||||
const { silenceFormStore } = this.props;
|
||||
|
||||
if (value && value[0]) {
|
||||
silenceFormStore.data.startsAt = value[0];
|
||||
}
|
||||
if (value && value[1]) {
|
||||
silenceFormStore.data.endsAt = value[1];
|
||||
}
|
||||
});
|
||||
|
||||
onHoverChange = action(value => {
|
||||
this.data.hoverValue = value;
|
||||
});
|
||||
|
||||
render() {
|
||||
const { silenceFormStore } = this.props;
|
||||
|
||||
const now = moment().second(0);
|
||||
|
||||
const calendar = (
|
||||
<RangeCalendar
|
||||
hoverValue={toJS(this.data.hoverValue)}
|
||||
onHoverChange={this.onHoverChange}
|
||||
showWeekNumber={false}
|
||||
dateInputPlaceholder={["start", "end"]}
|
||||
defaultValue={[now, now.clone().add(1, "hour")]}
|
||||
timePicker={timePickerElement}
|
||||
disabledDate={disabledDate}
|
||||
format={format}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<Picker
|
||||
value={[silenceFormStore.data.startsAt, silenceFormStore.data.endsAt]}
|
||||
onChange={this.onChange}
|
||||
calendar={calendar}
|
||||
>
|
||||
{({ value }) => {
|
||||
return (
|
||||
<div className="input-group mb-3">
|
||||
<div className="input-group-prepend">
|
||||
<span className="input-group-text">
|
||||
<FontAwesomeIcon icon={faCalendarAlt} />
|
||||
</span>
|
||||
</div>
|
||||
<input
|
||||
placeholder="Silence start and end"
|
||||
className="form-control bg-white"
|
||||
value={
|
||||
(isValidRange(value) &&
|
||||
`${formatTimestamp(value[0])} - ${formatTimestamp(
|
||||
value[1]
|
||||
)}`) ||
|
||||
""
|
||||
}
|
||||
readOnly
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</Picker>
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export { SilenceStartEnd };
|
||||
@@ -50,20 +50,24 @@ class SilenceFormStore {
|
||||
endsAt: moment().add(1, "hour"),
|
||||
comment: "",
|
||||
author: "",
|
||||
|
||||
resetProgress() {
|
||||
this.inProgress = false;
|
||||
},
|
||||
|
||||
// append a new empty matcher to the list
|
||||
addEmptyMatcher() {
|
||||
let m = NewEmptyMatcher();
|
||||
this.matchers.push(m);
|
||||
},
|
||||
|
||||
deleteMatcher(id) {
|
||||
// only delete matchers if we have more than 1
|
||||
if (this.matchers.length > 1) {
|
||||
this.matchers = this.matchers.filter(m => m.id !== id);
|
||||
}
|
||||
},
|
||||
|
||||
fillMatchersFromGroup(group) {
|
||||
let matchers = [];
|
||||
|
||||
@@ -108,6 +112,40 @@ class SilenceFormStore {
|
||||
|
||||
this.matchers = matchers;
|
||||
},
|
||||
|
||||
verifyStarEnd() {
|
||||
if (this.endsAt.isSameOrBefore(this.startsAt)) {
|
||||
this.endsAt = moment(this.startsAt).add(1, "minutes");
|
||||
}
|
||||
},
|
||||
incStart(minutes) {
|
||||
this.startsAt = moment(this.startsAt).add(minutes, "minutes");
|
||||
this.verifyStarEnd();
|
||||
},
|
||||
decStart(minutes) {
|
||||
this.startsAt = moment(this.startsAt).subtract(minutes, "minutes");
|
||||
this.verifyStarEnd();
|
||||
},
|
||||
|
||||
incEnd(minutes) {
|
||||
this.endsAt = moment(this.endsAt).add(minutes, "minutes");
|
||||
this.verifyStarEnd();
|
||||
},
|
||||
decEnd(minutes) {
|
||||
this.endsAt = moment(this.endsAt).subtract(minutes, "minutes");
|
||||
this.verifyStarEnd();
|
||||
},
|
||||
|
||||
incDuration(minutes) {
|
||||
this.endsAt = moment(this.endsAt).add(minutes, "minutes");
|
||||
},
|
||||
decDuration(minutes) {
|
||||
const newEndsAt = moment(this.endsAt).subtract(minutes, "minutes");
|
||||
if (newEndsAt.isAfter(this.startsAt)) {
|
||||
this.endsAt = newEndsAt;
|
||||
}
|
||||
},
|
||||
|
||||
get toAlertmanagerPayload() {
|
||||
const payload = {
|
||||
matchers: this.matchers.map(m => ({
|
||||
@@ -132,6 +170,14 @@ class SilenceFormStore {
|
||||
comment: this.comment
|
||||
};
|
||||
return payload;
|
||||
},
|
||||
get toDuration() {
|
||||
const data = {
|
||||
days: this.endsAt.diff(this.startsAt, "days"),
|
||||
hours: this.endsAt.diff(this.startsAt, "hours") % 24,
|
||||
minutes: this.endsAt.diff(this.startsAt, "minutes") % 60
|
||||
};
|
||||
return data;
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -139,7 +185,15 @@ class SilenceFormStore {
|
||||
addEmptyMatcher: action.bound,
|
||||
deleteMatcher: action.bound,
|
||||
fillMatchersFromGroup: action.bound,
|
||||
toAlertmanagerPayload: computed
|
||||
verifyStarEnd: action.bound,
|
||||
incStart: action.bound,
|
||||
decStart: action.bound,
|
||||
incEnd: action.bound,
|
||||
decEnd: action.bound,
|
||||
incDuration: action.bound,
|
||||
decDuration: action.bound,
|
||||
toAlertmanagerPayload: computed,
|
||||
toDuration: computed
|
||||
},
|
||||
{ name: "Silence form store" }
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user