diff --git a/ui/.storybook/config.js b/ui/.storybook/config.js
index 8f4f72309..7a2448751 100644
--- a/ui/.storybook/config.js
+++ b/ui/.storybook/config.js
@@ -11,7 +11,10 @@ import createPercyAddon from "@percy-io/percy-storybook";
import { advanceTo } from "jest-date-mock";
import { ThemeContext } from "Components/Theme";
-import { ReactSelectColors, ReactSelectStyles } from "Components/MultiSelect";
+import {
+ ReactSelectColors,
+ ReactSelectStyles
+} from "Components/Theme/ReactSelect";
const { percyAddon, serializeStories } = createPercyAddon();
setAddon(percyAddon);
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 2f7bc9767..a0cb2ae31 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -2918,6 +2918,12 @@
"@babel/types": "^7.3.0"
}
},
+ "@types/color-name": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
+ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
+ "dev": true
+ },
"@types/eslint-visitor-keys": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
@@ -4890,6 +4896,12 @@
"node-int64": "^0.4.0"
}
},
+ "btoa": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz",
+ "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==",
+ "dev": true
+ },
"buffer": {
"version": "4.9.2",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
@@ -11652,7 +11664,8 @@
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
- "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
+ "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
+ "dev": true
},
"lodash.differencewith": {
"version": "4.5.0",
@@ -11724,7 +11737,8 @@
"lodash.throttle": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
- "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
+ "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=",
+ "dev": true
},
"lodash.unescape": {
"version": "4.0.1",
@@ -11736,11 +11750,6 @@
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
"integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M="
},
- "lodash.uniqueid": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/lodash.uniqueid/-/lodash.uniqueid-4.0.1.tgz",
- "integrity": "sha1-MmjyanyI5PSxdY1nknGBTjH6WyY="
- },
"loglevel": {
"version": "1.6.6",
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.6.tgz",
@@ -17038,6 +17047,150 @@
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
},
+ "source-map-explorer": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/source-map-explorer/-/source-map-explorer-2.1.1.tgz",
+ "integrity": "sha512-GSHrlyGFhcXhjdWgM+ysY7d11eZMN2gvLsW56qFOdV3ZCsZCM/tl8tt3PXu5BUvllNKPRCGyv2mbWjbZrvEdmA==",
+ "dev": true,
+ "requires": {
+ "btoa": "^1.2.1",
+ "chalk": "^3.0.0",
+ "convert-source-map": "^1.7.0",
+ "ejs": "^2.7.2",
+ "escape-html": "^1.0.3",
+ "glob": "^7.1.6",
+ "lodash": "^4.17.15",
+ "open": "^7.0.0",
+ "source-map": "^0.7.3",
+ "temp": "^0.9.1",
+ "yargs": "^14.2.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.0.tgz",
+ "integrity": "sha512-7kFQgnEaMdRtwf6uSfUnVr9gSGC7faurn+J/Mv90/W+iTtN0405/nLdopfMWwchyxhbGYl6TC4Sccn9TUkGAgg==",
+ "dev": true,
+ "requires": {
+ "@types/color-name": "^1.1.1",
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "is-wsl": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz",
+ "integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==",
+ "dev": true
+ },
+ "open": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-7.0.0.tgz",
+ "integrity": "sha512-K6EKzYqnwQzk+/dzJAQSBORub3xlBTxMz+ntpZpH/LyCa1o6KjXhuN+2npAaI9jaSmU3R1Q8NWf4KUWcyytGsQ==",
+ "dev": true,
+ "requires": {
+ "is-wsl": "^2.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "supports-color": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+ "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "yargs": {
+ "version": "14.2.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.2.tgz",
+ "integrity": "sha512-/4ld+4VV5RnrynMhPZJ/ZpOCGSCeghMykZ3BhdFBDa9Wy/RH6uEGNWDJog+aUlq+9OM1CFTgtYRW5Is1Po9NOA==",
+ "dev": true,
+ "requires": {
+ "cliui": "^5.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^15.0.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "15.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.0.tgz",
+ "integrity": "sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
"source-map-resolve": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
@@ -17713,6 +17866,15 @@
}
}
},
+ "temp": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.1.tgz",
+ "integrity": "sha512-WMuOgiua1xb5R56lE0eH6ivpVmg/lq2OHm4+LtT/xtEtPQ+sz6N3bBM6WZ5FvO1lO4IKIOb43qnhoc4qxP5OeA==",
+ "dev": true,
+ "requires": {
+ "rimraf": "~2.6.2"
+ }
+ },
"term-size": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz",
diff --git a/ui/package.json b/ui/package.json
index 3a509b4c2..14ff3adab 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -22,10 +22,7 @@
"fast-deep-equal": "2.0.1",
"favico.js": "0.3.10",
"fontfaceobserver": "2.1.0",
- "lodash.debounce": "4.0.8",
- "lodash.merge": "4.6.2",
- "lodash.throttle": "4.1.1",
- "lodash.uniqueid": "4.0.1",
+ "lodash": "4.17.15",
"mobx": "5.15.0",
"mobx-react": "6.1.4",
"mobx-stored": "1.1.0",
@@ -65,7 +62,8 @@
"build": "react-scripts build",
"test": "react-scripts test",
"storybook": "start-storybook",
- "snapshot": "build-storybook --quiet -s public && percy-storybook --widths=700,1280 --minimum_height=200"
+ "snapshot": "build-storybook --quiet -s public && percy-storybook --widths=700,1280 --minimum_height=200",
+ "analyze": "source-map-explorer 'build/static/js/*.js'"
},
"jest": {
"collectCoverageFrom": [
@@ -87,7 +85,8 @@
"jest-fetch-mock": "2.1.2",
"markdownlint-cli": "0.19.0",
"node-sass": "4.13.0",
- "prettier": "1.19.1"
+ "prettier": "1.19.1",
+ "source-map-explorer": "2.1.1"
},
"browserslist": [
">= 1%",
diff --git a/ui/src/App.tsx b/ui/src/App.tsx
index f961e3d2a..a560c3cd5 100644
--- a/ui/src/App.tsx
+++ b/ui/src/App.tsx
@@ -5,17 +5,30 @@ import { observer } from "mobx-react";
import { AlertStore, DecodeLocationSearch } from "Stores/AlertStore";
import { Settings } from "Stores/Settings";
import { SilenceFormStore } from "Stores/SilenceFormStore";
-import { NavBar } from "Components/NavBar";
-import { Grid } from "Components/Grid";
import { Fetcher } from "Components/Fetcher";
import { FaviconBadge } from "Components/FaviconBadge";
-import { ReactSelectColors, ReactSelectStyles } from "Components/MultiSelect";
+import {
+ ReactSelectColors,
+ ReactSelectStyles
+} from "Components/Theme/ReactSelect";
import { Theme, ThemeContext } from "Components/Theme";
import { ErrorBoundary } from "./ErrorBoundary";
import "Styles/ResetCSS.scss";
import "Styles/App.scss";
+// https://github.com/facebook/react/issues/14603
+const Grid = React.lazy(() =>
+ import("Components/Grid").then(module => ({
+ default: module.Grid
+ }))
+);
+const NavBar = React.lazy(() =>
+ import("Components/NavBar").then(module => ({
+ default: module.NavBar
+ }))
+);
+
interface UIDefaults {
Refresh: number;
HideFiltersWhenIdle: boolean;
@@ -103,16 +116,20 @@ const App = observer(
: ReactSelectStyles(ReactSelectColors.Light)
}}
>
-
-
+
+
+
+
+
+
{
fetch.resetMocks();
diff --git a/ui/src/Components/Grid/AlertGrid/index.js b/ui/src/Components/Grid/AlertGrid/index.js
index 26792360e..372689b06 100644
--- a/ui/src/Components/Grid/AlertGrid/index.js
+++ b/ui/src/Components/Grid/AlertGrid/index.js
@@ -6,7 +6,7 @@ import { observer } from "mobx-react";
import FontFaceObserver from "fontfaceobserver";
-import { debounce } from "lodash";
+import debounce from "lodash/debounce";
import ReactResizeDetector from "react-resize-detector";
diff --git a/ui/src/Components/MainModal/Configuration/AlertGroupCollapseConfiguration.test.js b/ui/src/Components/MainModal/Configuration/AlertGroupCollapseConfiguration.test.js
index f90bab295..d9a2c1e1e 100644
--- a/ui/src/Components/MainModal/Configuration/AlertGroupCollapseConfiguration.test.js
+++ b/ui/src/Components/MainModal/Configuration/AlertGroupCollapseConfiguration.test.js
@@ -6,7 +6,10 @@ import toDiffableHtml from "diffable-html";
import { Settings } from "Stores/Settings";
import { ThemeContext } from "Components/Theme";
-import { ReactSelectColors, ReactSelectStyles } from "Components/MultiSelect";
+import {
+ ReactSelectColors,
+ ReactSelectStyles
+} from "Components/Theme/ReactSelect";
import { AlertGroupCollapseConfiguration } from "./AlertGroupCollapseConfiguration";
let settingsStore;
diff --git a/ui/src/Components/MainModal/Configuration/AlertGroupSortConfiguration.test.js b/ui/src/Components/MainModal/Configuration/AlertGroupSortConfiguration.test.js
index 0455227e8..822e20701 100644
--- a/ui/src/Components/MainModal/Configuration/AlertGroupSortConfiguration.test.js
+++ b/ui/src/Components/MainModal/Configuration/AlertGroupSortConfiguration.test.js
@@ -6,7 +6,10 @@ import toDiffableHtml from "diffable-html";
import { Settings } from "Stores/Settings";
import { ThemeContext } from "Components/Theme";
-import { ReactSelectColors, ReactSelectStyles } from "Components/MultiSelect";
+import {
+ ReactSelectColors,
+ ReactSelectStyles
+} from "Components/Theme/ReactSelect";
import { AlertGroupSortConfiguration } from "./AlertGroupSortConfiguration";
let settingsStore;
diff --git a/ui/src/Components/MainModal/Configuration/AlertGroupWidthConfiguration.js b/ui/src/Components/MainModal/Configuration/AlertGroupWidthConfiguration.js
index a199e0858..0ff4560d2 100644
--- a/ui/src/Components/MainModal/Configuration/AlertGroupWidthConfiguration.js
+++ b/ui/src/Components/MainModal/Configuration/AlertGroupWidthConfiguration.js
@@ -4,7 +4,7 @@ import PropTypes from "prop-types";
import { observable, action, toJS } from "mobx";
import { observer } from "mobx-react";
-import { debounce } from "lodash";
+import debounce from "lodash/debounce";
import InputRange from "react-input-range";
diff --git a/ui/src/Components/MainModal/Configuration/index.test.js b/ui/src/Components/MainModal/Configuration/index.test.js
index 13fb7e854..f1d259ea7 100644
--- a/ui/src/Components/MainModal/Configuration/index.test.js
+++ b/ui/src/Components/MainModal/Configuration/index.test.js
@@ -6,7 +6,10 @@ import toDiffableHtml from "diffable-html";
import { Settings } from "Stores/Settings";
import { ThemeContext } from "Components/Theme";
-import { ReactSelectColors, ReactSelectStyles } from "Components/MultiSelect";
+import {
+ ReactSelectColors,
+ ReactSelectStyles
+} from "Components/Theme/ReactSelect";
import { Configuration } from ".";
describe("", () => {
diff --git a/ui/src/Components/MainModal/MainModalContent.test.js b/ui/src/Components/MainModal/MainModalContent.test.js
index c93dbc938..9376347e5 100644
--- a/ui/src/Components/MainModal/MainModalContent.test.js
+++ b/ui/src/Components/MainModal/MainModalContent.test.js
@@ -7,7 +7,10 @@ import toDiffableHtml from "diffable-html";
import { AlertStore } from "Stores/AlertStore";
import { Settings } from "Stores/Settings";
import { ThemeContext } from "Components/Theme";
-import { ReactSelectColors, ReactSelectStyles } from "Components/MultiSelect";
+import {
+ ReactSelectColors,
+ ReactSelectStyles
+} from "Components/Theme/ReactSelect";
import { MainModalContent } from "./MainModalContent";
let alertStore;
diff --git a/ui/src/Components/MainModal/index.test.js b/ui/src/Components/MainModal/index.test.js
index 038a8fd4b..6d1d3cbef 100644
--- a/ui/src/Components/MainModal/index.test.js
+++ b/ui/src/Components/MainModal/index.test.js
@@ -5,7 +5,10 @@ import { mount } from "enzyme";
import { AlertStore } from "Stores/AlertStore";
import { Settings } from "Stores/Settings";
import { ThemeContext } from "Components/Theme";
-import { ReactSelectColors, ReactSelectStyles } from "Components/MultiSelect";
+import {
+ ReactSelectColors,
+ ReactSelectStyles
+} from "Components/Theme/ReactSelect";
import { MainModal } from ".";
let alertStore;
diff --git a/ui/src/Components/MultiSelect/index.js b/ui/src/Components/MultiSelect/index.js
index e41591eec..9e9bf2e94 100644
--- a/ui/src/Components/MultiSelect/index.js
+++ b/ui/src/Components/MultiSelect/index.js
@@ -4,138 +4,6 @@ import Creatable from "react-select/creatable";
import { ThemeContext } from "Components/Theme";
-const ReactSelectColors = {
- Light: {
- color: "#fff",
- singleValueColor: "#000",
- backgroundColor: "#fff",
- borderColor: "#ced4da",
- focusedBoxShadow: "rgba(69, 90, 100, 0.25)",
- focusedBorderColor: "#819ba8",
- menuBackground: "#fff",
- optionHoverBackground: "#455a64",
- valueContainerBackground: "#fff",
- disabledValueContainerBackground: "#fff"
- },
- Dark: {
- color: "#fff",
- singleValueColor: "#fff",
- backgroundColor: "#fff",
- borderColor: "#444",
- focusedBoxShadow: "rgba(69, 90, 100, 0.25)",
- focusedBorderColor: "#819ba8",
- menuBackground: "#222",
- optionHoverBackground: "#455a64",
- valueContainerBackground: "#444",
- disabledValueContainerBackground: "#fff"
- }
-};
-
-const ReactSelectStyles = theme => ({
- control: (base, state) =>
- state.isFocused
- ? {
- ...base,
- backgroundColor: theme.backgroundColor,
- outline: "0",
- outlineOffset: "-2px",
- boxShadow: `0 0 0 0.2rem ${theme.focusedBoxShadow}`,
- borderRadius: "0.25rem",
- borderColor: theme.focusedBorderColor,
- "&:hover": {
- borderColor: theme.focusedBorderColor
- }
- }
- : {
- ...base,
- backgroundColor: "inherit",
- borderRadius: "0.25rem",
- borderColor: theme.borderColor,
- "&:hover": { borderColor: theme.borderColor }
- },
- valueContainer: (base, state) =>
- state.isMulti
- ? {
- ...base,
- borderRadius: 0,
- backgroundColor: state.isDisabled
- ? theme.disabledValueContainerBackground
- : theme.valueContainerBackground,
- paddingLeft: "4px",
- paddingRight: "4px",
- display: "flex",
- flexDirection: "row",
- flexWrap: "wrap",
- maxWidth: "100%",
- overflow: "hidden"
- }
- : {
- ...base,
- borderRadius: 0,
- backgroundColor: state.isDisabled
- ? theme.disabledValueContainerBackground
- : theme.valueContainerBackground
- },
- singleValue: (base, state) => ({
- ...base,
- color: theme.singleValueColor
- }),
- multiValue: (base, state) => ({
- ...base,
- borderRadius: "4px",
- backgroundColor: theme.optionHoverBackground,
- "&:hover": {
- backgroundColor: theme.optionHoverBackground
- }
- }),
- multiValueLabel: (base, state) => ({
- ...base,
- color: theme.color,
- whiteSpace: "normal",
- wordWrap: "break-word",
- wordBreak: "break-word",
- "&:hover": {
- color: theme.color
- }
- }),
- multiValueRemove: (base, state) => ({
- ...base,
- cursor: "pointer",
- color: theme.color,
- backgroundColor: "inherit",
- opacity: "0.4",
- borderRadius: "inherit",
- "&:hover": {
- color: theme.color,
- backgroundColor: "inherit",
- opacity: "0.75"
- }
- }),
- indicatorsContainer: (base, state) => ({
- ...base,
- backgroundColor: state.isDisabled
- ? theme.disabledValueContainerBackground
- : theme.valueContainerBackground,
- borderTopRightRadius: "0.25rem",
- borderBottomRightRadius: "0.25rem"
- }),
- menu: (base, state) => ({
- ...base,
- zIndex: 1500,
- backgroundColor: theme.menuBackground
- }),
- option: (base, state) => ({
- ...base,
- color: "inherit",
- backgroundColor: "inherit",
- "&:hover": {
- color: theme.color,
- backgroundColor: theme.optionHoverBackground,
- cursor: "pointer"
- }
- })
-});
-
class MultiSelect extends Creatable {
renderProps = () => ({});
@@ -151,4 +19,4 @@ class MultiSelect extends Creatable {
}
MultiSelect.contextType = ThemeContext;
-export { MultiSelect, ReactSelectStyles, ReactSelectColors };
+export { MultiSelect };
diff --git a/ui/src/Components/MultiSelect/index.test.js b/ui/src/Components/MultiSelect/index.test.js
index 5b65d98ec..1a1ec69a8 100644
--- a/ui/src/Components/MultiSelect/index.test.js
+++ b/ui/src/Components/MultiSelect/index.test.js
@@ -5,7 +5,10 @@ import { mount } from "enzyme";
import toDiffableHtml from "diffable-html";
import { ThemeContext } from "Components/Theme";
-import { ReactSelectColors, ReactSelectStyles } from "Components/MultiSelect";
+import {
+ ReactSelectColors,
+ ReactSelectStyles
+} from "Components/Theme/ReactSelect";
import { MultiSelect } from ".";
const Option = value => ({ label: value, value: value });
diff --git a/ui/src/Components/NavBar/FilterInput/index.js b/ui/src/Components/NavBar/FilterInput/index.js
index d71e29ef1..9b5e354ff 100644
--- a/ui/src/Components/NavBar/FilterInput/index.js
+++ b/ui/src/Components/NavBar/FilterInput/index.js
@@ -4,7 +4,7 @@ import PropTypes from "prop-types";
import { observable, action } from "mobx";
import { observer } from "mobx-react";
-import { debounce } from "lodash";
+import debounce from "lodash/debounce";
import Autosuggest from "react-autosuggest";
import Highlight from "react-highlighter";
diff --git a/ui/src/Components/SilenceModal/AlertManagerInput/index.test.js b/ui/src/Components/SilenceModal/AlertManagerInput/index.test.js
index 15e204e0a..21927decb 100644
--- a/ui/src/Components/SilenceModal/AlertManagerInput/index.test.js
+++ b/ui/src/Components/SilenceModal/AlertManagerInput/index.test.js
@@ -7,7 +7,10 @@ import toDiffableHtml from "diffable-html";
import { AlertStore } from "Stores/AlertStore";
import { SilenceFormStore } from "Stores/SilenceFormStore";
import { ThemeContext } from "Components/Theme";
-import { ReactSelectColors, ReactSelectStyles } from "Components/MultiSelect";
+import {
+ ReactSelectColors,
+ ReactSelectStyles
+} from "Components/Theme/ReactSelect";
import { AlertManagerInput } from ".";
let alertStore;
diff --git a/ui/src/Components/SilenceModal/Browser/index.js b/ui/src/Components/SilenceModal/Browser/index.js
index fa08171f8..2a379f70c 100644
--- a/ui/src/Components/SilenceModal/Browser/index.js
+++ b/ui/src/Components/SilenceModal/Browser/index.js
@@ -4,7 +4,7 @@ import PropTypes from "prop-types";
import { observable, action } from "mobx";
import { observer } from "mobx-react";
-import { debounce } from "lodash";
+import debounce from "lodash/debounce";
import Pagination from "react-js-pagination";
diff --git a/ui/src/Components/SilenceModal/SilenceForm.test.js b/ui/src/Components/SilenceModal/SilenceForm.test.js
index 618f8492c..8bce81c9a 100644
--- a/ui/src/Components/SilenceModal/SilenceForm.test.js
+++ b/ui/src/Components/SilenceModal/SilenceForm.test.js
@@ -10,7 +10,10 @@ import {
NewEmptyMatcher
} from "Stores/SilenceFormStore";
import { ThemeContext } from "Components/Theme";
-import { ReactSelectColors, ReactSelectStyles } from "Components/MultiSelect";
+import {
+ ReactSelectColors,
+ ReactSelectStyles
+} from "Components/Theme/ReactSelect";
import { SilenceForm } from "./SilenceForm";
let alertStore;
diff --git a/ui/src/Components/SilenceModal/SilenceMatch/LabelNameInput.test.js b/ui/src/Components/SilenceModal/SilenceMatch/LabelNameInput.test.js
index 336b3b6dd..abf313ac3 100644
--- a/ui/src/Components/SilenceModal/SilenceMatch/LabelNameInput.test.js
+++ b/ui/src/Components/SilenceModal/SilenceMatch/LabelNameInput.test.js
@@ -6,7 +6,10 @@ import toDiffableHtml from "diffable-html";
import { NewEmptyMatcher, MatcherValueToObject } from "Stores/SilenceFormStore";
import { ThemeContext } from "Components/Theme";
-import { ReactSelectColors, ReactSelectStyles } from "Components/MultiSelect";
+import {
+ ReactSelectColors,
+ ReactSelectStyles
+} from "Components/Theme/ReactSelect";
import { LabelNameInput } from "./LabelNameInput";
let matcher;
diff --git a/ui/src/Components/SilenceModal/SilenceMatch/LabelValueInput.test.js b/ui/src/Components/SilenceModal/SilenceMatch/LabelValueInput.test.js
index 1eb2fb21a..92a663990 100644
--- a/ui/src/Components/SilenceModal/SilenceMatch/LabelValueInput.test.js
+++ b/ui/src/Components/SilenceModal/SilenceMatch/LabelValueInput.test.js
@@ -10,7 +10,10 @@ import {
MatcherValueToObject
} from "Stores/SilenceFormStore";
import { ThemeContext } from "Components/Theme";
-import { ReactSelectColors, ReactSelectStyles } from "Components/MultiSelect";
+import {
+ ReactSelectColors,
+ ReactSelectStyles
+} from "Components/Theme/ReactSelect";
import { LabelValueInput } from "./LabelValueInput";
let silenceFormStore;
diff --git a/ui/src/Components/SilenceModal/SilenceMatch/MatchCounter.js b/ui/src/Components/SilenceModal/SilenceMatch/MatchCounter.js
index b867ebf6e..ed589dd08 100644
--- a/ui/src/Components/SilenceModal/SilenceMatch/MatchCounter.js
+++ b/ui/src/Components/SilenceModal/SilenceMatch/MatchCounter.js
@@ -4,7 +4,7 @@ import PropTypes from "prop-types";
import { observable, action } from "mobx";
import { observer } from "mobx-react";
-import { throttle } from "lodash";
+import throttle from "lodash/throttle";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclamationCircle";
diff --git a/ui/src/Components/SilenceModal/index.test.js b/ui/src/Components/SilenceModal/index.test.js
index 15e565283..f78514efb 100644
--- a/ui/src/Components/SilenceModal/index.test.js
+++ b/ui/src/Components/SilenceModal/index.test.js
@@ -3,7 +3,10 @@ import React from "react";
import { mount } from "enzyme";
import { ThemeContext } from "Components/Theme";
-import { ReactSelectColors, ReactSelectStyles } from "Components/MultiSelect";
+import {
+ ReactSelectColors,
+ ReactSelectStyles
+} from "Components/Theme/ReactSelect";
import { AlertStore } from "Stores/AlertStore";
import { Settings } from "Stores/Settings";
import { SilenceFormStore, SilenceFormStage } from "Stores/SilenceFormStore";
diff --git a/ui/src/Components/Theme/ReactSelect.js b/ui/src/Components/Theme/ReactSelect.js
new file mode 100644
index 000000000..2ffc48c77
--- /dev/null
+++ b/ui/src/Components/Theme/ReactSelect.js
@@ -0,0 +1,133 @@
+const ReactSelectColors = {
+ Light: {
+ color: "#fff",
+ singleValueColor: "#000",
+ backgroundColor: "#fff",
+ borderColor: "#ced4da",
+ focusedBoxShadow: "rgba(69, 90, 100, 0.25)",
+ focusedBorderColor: "#819ba8",
+ menuBackground: "#fff",
+ optionHoverBackground: "#455a64",
+ valueContainerBackground: "#fff",
+ disabledValueContainerBackground: "#fff"
+ },
+ Dark: {
+ color: "#fff",
+ singleValueColor: "#fff",
+ backgroundColor: "#fff",
+ borderColor: "#444",
+ focusedBoxShadow: "rgba(69, 90, 100, 0.25)",
+ focusedBorderColor: "#819ba8",
+ menuBackground: "#222",
+ optionHoverBackground: "#455a64",
+ valueContainerBackground: "#444",
+ disabledValueContainerBackground: "#fff"
+ }
+};
+
+const ReactSelectStyles = theme => ({
+ control: (base, state) =>
+ state.isFocused
+ ? {
+ ...base,
+ backgroundColor: theme.backgroundColor,
+ outline: "0",
+ outlineOffset: "-2px",
+ boxShadow: `0 0 0 0.2rem ${theme.focusedBoxShadow}`,
+ borderRadius: "0.25rem",
+ borderColor: theme.focusedBorderColor,
+ "&:hover": {
+ borderColor: theme.focusedBorderColor
+ }
+ }
+ : {
+ ...base,
+ backgroundColor: "inherit",
+ borderRadius: "0.25rem",
+ borderColor: theme.borderColor,
+ "&:hover": { borderColor: theme.borderColor }
+ },
+ valueContainer: (base, state) =>
+ state.isMulti
+ ? {
+ ...base,
+ borderRadius: 0,
+ backgroundColor: state.isDisabled
+ ? theme.disabledValueContainerBackground
+ : theme.valueContainerBackground,
+ paddingLeft: "4px",
+ paddingRight: "4px",
+ display: "flex",
+ flexDirection: "row",
+ flexWrap: "wrap",
+ maxWidth: "100%",
+ overflow: "hidden"
+ }
+ : {
+ ...base,
+ borderRadius: 0,
+ backgroundColor: state.isDisabled
+ ? theme.disabledValueContainerBackground
+ : theme.valueContainerBackground
+ },
+ singleValue: (base, state) => ({
+ ...base,
+ color: theme.singleValueColor
+ }),
+ multiValue: (base, state) => ({
+ ...base,
+ borderRadius: "4px",
+ backgroundColor: theme.optionHoverBackground,
+ "&:hover": {
+ backgroundColor: theme.optionHoverBackground
+ }
+ }),
+ multiValueLabel: (base, state) => ({
+ ...base,
+ color: theme.color,
+ whiteSpace: "normal",
+ wordWrap: "break-word",
+ wordBreak: "break-word",
+ "&:hover": {
+ color: theme.color
+ }
+ }),
+ multiValueRemove: (base, state) => ({
+ ...base,
+ cursor: "pointer",
+ color: theme.color,
+ backgroundColor: "inherit",
+ opacity: "0.4",
+ borderRadius: "inherit",
+ "&:hover": {
+ color: theme.color,
+ backgroundColor: "inherit",
+ opacity: "0.75"
+ }
+ }),
+ indicatorsContainer: (base, state) => ({
+ ...base,
+ backgroundColor: state.isDisabled
+ ? theme.disabledValueContainerBackground
+ : theme.valueContainerBackground,
+ borderTopRightRadius: "0.25rem",
+ borderBottomRightRadius: "0.25rem"
+ }),
+ menu: (base, state) => ({
+ ...base,
+ zIndex: 1500,
+ backgroundColor: theme.menuBackground
+ }),
+ option: (base, state) => ({
+ ...base,
+ color: "inherit",
+ backgroundColor: "inherit",
+ "&:hover": {
+ color: theme.color,
+ backgroundColor: theme.optionHoverBackground,
+ cursor: "pointer"
+ }
+ })
+});
+
+export { ReactSelectStyles, ReactSelectColors };
diff --git a/ui/src/Stores/AlertStore.js b/ui/src/Stores/AlertStore.js
index 4d81acb89..8b57f8520 100644
--- a/ui/src/Stores/AlertStore.js
+++ b/ui/src/Stores/AlertStore.js
@@ -1,6 +1,6 @@
import { observable, action, toJS } from "mobx";
-import { throttle } from "lodash";
+import throttle from "lodash/throttle";
import equal from "fast-deep-equal";
diff --git a/ui/src/Stores/SilenceFormStore.js b/ui/src/Stores/SilenceFormStore.js
index a4e41d0b0..31b807721 100644
--- a/ui/src/Stores/SilenceFormStore.js
+++ b/ui/src/Stores/SilenceFormStore.js
@@ -1,6 +1,6 @@
import { observable, action, computed } from "mobx";
-import uniqueId from "lodash.uniqueid";
+import uniqueId from "lodash/uniqueId";
import moment from "moment";
diff --git a/ui/src/__mocks__/lodash.js b/ui/src/__mocks__/lodash.js
deleted file mode 100644
index 6d9fc6447..000000000
--- a/ui/src/__mocks__/lodash.js
+++ /dev/null
@@ -1,11 +0,0 @@
-// https://github.com/facebook/jest/issues/3465
-
-function debounce(wrapped) {
- return wrapped;
-}
-
-function throttle(wrapped) {
- return wrapped;
-}
-
-export { debounce, throttle };
diff --git a/ui/src/__mocks__/lodash/debounce.js b/ui/src/__mocks__/lodash/debounce.js
new file mode 100644
index 000000000..ddab5aeea
--- /dev/null
+++ b/ui/src/__mocks__/lodash/debounce.js
@@ -0,0 +1,3 @@
+export default function(wrapped) {
+ return wrapped;
+}
diff --git a/ui/src/__mocks__/lodash/throttle.js b/ui/src/__mocks__/lodash/throttle.js
new file mode 100644
index 000000000..ddab5aeea
--- /dev/null
+++ b/ui/src/__mocks__/lodash/throttle.js
@@ -0,0 +1,3 @@
+export default function(wrapped) {
+ return wrapped;
+}