mirror of
https://github.com/prymitive/karma
synced 2026-05-07 03:26:52 +00:00
feat(ui): allow disabling animations
This commit is contained in:
committed by
Łukasz Mierzwa
parent
d6029506d5
commit
45f30f6ce9
@@ -115,7 +115,7 @@ const App: FunctionComponent<AppProps> = observer(
|
||||
? ReactSelectStyles(ReactSelectColors.Dark)
|
||||
: ReactSelectStyles(ReactSelectColors.Light),
|
||||
animations: {
|
||||
duration: 500,
|
||||
duration: settingsStore.themeConfig.config.animations ? 500 : 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -2,20 +2,26 @@ import React, { FC, ReactNode } from "react";
|
||||
|
||||
import { CSSTransition } from "react-transition-group";
|
||||
|
||||
import { ThemeContext } from "Components/Theme";
|
||||
|
||||
const DropdownSlide: FC<{
|
||||
children: ReactNode;
|
||||
in?: boolean;
|
||||
unmountOnExit?: boolean;
|
||||
}> = ({ children, ...props }) => (
|
||||
<CSSTransition
|
||||
classNames="components-animation-slide"
|
||||
timeout={150}
|
||||
appear={true}
|
||||
exit={true}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</CSSTransition>
|
||||
);
|
||||
}> = ({ children, ...props }) => {
|
||||
const context = React.useContext(ThemeContext);
|
||||
|
||||
return (
|
||||
<CSSTransition
|
||||
classNames="components-animation-slide"
|
||||
timeout={context.animations.duration ? 150 : 0}
|
||||
appear={true}
|
||||
exit={true}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</CSSTransition>
|
||||
);
|
||||
};
|
||||
|
||||
export { DropdownSlide };
|
||||
|
||||
@@ -4,12 +4,15 @@ import { act } from "react-dom/test-utils";
|
||||
import { mount } from "enzyme";
|
||||
|
||||
import { MockAlert, MockAlertGroup } from "__mocks__/Alerts";
|
||||
import { MockThemeContext } from "__mocks__/Theme";
|
||||
import {
|
||||
MockThemeContext,
|
||||
MockThemeContextWithoutAnimations,
|
||||
} from "__mocks__/Theme";
|
||||
import { APIAlertGroupT } from "Models/APITypes";
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
import { Settings, CollapseStateT } from "Stores/Settings";
|
||||
import { SilenceFormStore } from "Stores/SilenceFormStore";
|
||||
import { ThemeContext } from "Components/Theme";
|
||||
import { ThemeContext, ThemeCtx } from "Components/Theme";
|
||||
import AlertGroup from ".";
|
||||
|
||||
let alertStore: AlertStore;
|
||||
@@ -60,7 +63,8 @@ const MockAlerts = (alertCount: number) => {
|
||||
const MountedAlertGroup = (
|
||||
afterUpdate: () => void,
|
||||
showAlertmanagers: boolean,
|
||||
initialAlertsToRender?: number
|
||||
initialAlertsToRender?: number,
|
||||
theme?: ThemeCtx
|
||||
) => {
|
||||
return mount(
|
||||
<AlertGroup
|
||||
@@ -76,7 +80,7 @@ const MountedAlertGroup = (
|
||||
/>,
|
||||
{
|
||||
wrappingComponent: ThemeContext.Provider,
|
||||
wrappingComponentProps: { value: MockThemeContext },
|
||||
wrappingComponentProps: { value: theme || MockThemeContext },
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -102,6 +106,27 @@ describe("<AlertGroup />", () => {
|
||||
tree.unmount();
|
||||
});
|
||||
|
||||
it("uses 'animate' class when settingsStore.themeConfig.config.animations is true", () => {
|
||||
MockAlerts(5);
|
||||
const tree = MountedAlertGroup(jest.fn(), true, 5, MockThemeContext);
|
||||
expect(
|
||||
tree.find("div.components-grid-alertgrid-alertgroup").hasClass("animate")
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("doesn't use 'animate' class when settingsStore.themeConfig.config.animations is false", () => {
|
||||
MockAlerts(5);
|
||||
const tree = MountedAlertGroup(
|
||||
jest.fn(),
|
||||
true,
|
||||
5,
|
||||
MockThemeContextWithoutAnimations
|
||||
);
|
||||
expect(
|
||||
tree.find("div.components-grid-alertgrid-alertgroup").hasClass("animate")
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("renders Alertmanager cluster labels in footer if showAlertmanagersInFooter=true", () => {
|
||||
MockAlerts(2);
|
||||
const tree = MountedAlertGroup(jest.fn(), true).find("AlertGroup");
|
||||
|
||||
@@ -13,6 +13,7 @@ import { AlertStore } from "Stores/AlertStore";
|
||||
import { SilenceFormStore } from "Stores/SilenceFormStore";
|
||||
import { BackgroundClassMap } from "Common/Colors";
|
||||
import { TooltipWrapper } from "Components/TooltipWrapper";
|
||||
import { ThemeContext } from "Components/Theme";
|
||||
import GroupHeader from "./GroupHeader";
|
||||
import Alert from "./Alert";
|
||||
import GroupFooter from "./GroupFooter";
|
||||
@@ -168,9 +169,13 @@ const AlertGroup: FC<{
|
||||
}
|
||||
}
|
||||
|
||||
const context = React.useContext(ThemeContext);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="components-grid-alertgrid-alertgroup"
|
||||
className={`components-grid-alertgrid-alertgroup ${
|
||||
context.animations.duration ? "animate" : ""
|
||||
}`}
|
||||
style={{
|
||||
width: groupWidth,
|
||||
zIndex: isMenuOpen ? 100 : undefined,
|
||||
|
||||
@@ -139,7 +139,11 @@ const Grid: FC<{
|
||||
? grid.alertGroups.slice(0, groupsToRender).map((group) => (
|
||||
<CSSTransition
|
||||
key={group.id}
|
||||
classNames="components-animation-fade"
|
||||
classNames={
|
||||
context.animations.duration
|
||||
? "components-animation-fade"
|
||||
: ""
|
||||
}
|
||||
timeout={context.animations.duration}
|
||||
onEntering={repack}
|
||||
onExited={debouncedRepack}
|
||||
|
||||
@@ -6,12 +6,15 @@ import { shallow, mount } from "enzyme";
|
||||
import { advanceBy, clear } from "jest-date-mock";
|
||||
|
||||
import { MockAlert, MockAlertGroup } from "__mocks__/Alerts";
|
||||
import { MockThemeContext } from "__mocks__/Theme";
|
||||
import {
|
||||
MockThemeContext,
|
||||
MockThemeContextWithoutAnimations,
|
||||
} from "__mocks__/Theme";
|
||||
import { mockMatchMedia } from "__mocks__/matchMedia";
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
import { Settings } from "Stores/Settings";
|
||||
import { SilenceFormStore } from "Stores/SilenceFormStore";
|
||||
import { ThemeContext } from "Components/Theme";
|
||||
import { ThemeContext, ThemeCtx } from "Components/Theme";
|
||||
import { GetGridElementWidth, GridSizesConfig } from "./GridSize";
|
||||
import Grid from "./Grid";
|
||||
import AlertGrid from ".";
|
||||
@@ -109,7 +112,7 @@ const ShallowGrid = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const MountedGrid = () => {
|
||||
const MountedGrid = (theme?: ThemeCtx) => {
|
||||
return mount(
|
||||
<Grid
|
||||
alertStore={alertStore}
|
||||
@@ -122,7 +125,7 @@ const MountedGrid = () => {
|
||||
/>,
|
||||
{
|
||||
wrappingComponent: ThemeContext.Provider,
|
||||
wrappingComponentProps: { value: MockThemeContext },
|
||||
wrappingComponentProps: { value: theme || MockThemeContext },
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -183,6 +186,25 @@ const MockGroupList = (count: number, alertPerGroup: number) => {
|
||||
};
|
||||
|
||||
describe("<Grid />", () => {
|
||||
it("uses animations when settingsStore.themeConfig.config.animations is true", () => {
|
||||
MockGroupList(1, 1);
|
||||
const tree = MountedGrid(MockThemeContext);
|
||||
expect(
|
||||
tree.find("div.components-grid-alertgrid-alertgroup").html()
|
||||
).toMatch(/animate components-animation-fade-appear/);
|
||||
});
|
||||
|
||||
it("doesn't use animations when settingsStore.themeConfig.config.animations is false", () => {
|
||||
jest
|
||||
.spyOn(React, "useContext")
|
||||
.mockImplementation(() => MockThemeContextWithoutAnimations);
|
||||
MockGroupList(1, 1);
|
||||
const tree = MountedGrid(MockThemeContextWithoutAnimations);
|
||||
expect(
|
||||
tree.find("div.components-grid-alertgrid-alertgroup").html()
|
||||
).not.toMatch(/animate components-animation-fade-appear/);
|
||||
});
|
||||
|
||||
it("renders only first 50 alert groups", () => {
|
||||
MockGroupList(55, 5);
|
||||
const tree = MountedGrid();
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import React from "react";
|
||||
|
||||
import { mount } from "enzyme";
|
||||
|
||||
import toDiffableHtml from "diffable-html";
|
||||
|
||||
import { Settings } from "Stores/Settings";
|
||||
import { AnimationsConfiguration } from "./AnimationsConfiguration";
|
||||
|
||||
let settingsStore: Settings;
|
||||
beforeEach(() => {
|
||||
settingsStore = new Settings(null);
|
||||
});
|
||||
|
||||
const FakeConfiguration = () => {
|
||||
return mount(<AnimationsConfiguration settingsStore={settingsStore} />);
|
||||
};
|
||||
|
||||
describe("<AnimationsConfiguration />", () => {
|
||||
it("matches snapshot with default values", () => {
|
||||
const tree = FakeConfiguration();
|
||||
expect(toDiffableHtml(tree.html())).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("animations is 'true' by default", () => {
|
||||
expect(settingsStore.themeConfig.config.animations).toBe(true);
|
||||
});
|
||||
|
||||
it("unchecking the checkbox sets stored animations value to 'false'", (done) => {
|
||||
const tree = FakeConfiguration();
|
||||
const checkbox = tree.find("#configuration-animations");
|
||||
|
||||
settingsStore.themeConfig.setAnimations(true);
|
||||
expect(settingsStore.themeConfig.config.animations).toBe(true);
|
||||
checkbox.simulate("change", { target: { checked: false } });
|
||||
setTimeout(() => {
|
||||
expect(settingsStore.themeConfig.config.animations).toBe(false);
|
||||
done();
|
||||
}, 200);
|
||||
});
|
||||
|
||||
it("checking the checkbox sets stored animations value to 'true'", (done) => {
|
||||
const tree = FakeConfiguration();
|
||||
const checkbox = tree.find("#configuration-animations");
|
||||
|
||||
settingsStore.themeConfig.setAnimations(false);
|
||||
expect(settingsStore.themeConfig.config.animations).toBe(false);
|
||||
checkbox.simulate("change", { target: { checked: true } });
|
||||
setTimeout(() => {
|
||||
expect(settingsStore.themeConfig.config.animations).toBe(true);
|
||||
done();
|
||||
}, 200);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
import React, { FC } from "react";
|
||||
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
import { Settings } from "Stores/Settings";
|
||||
|
||||
const AnimationsConfiguration: FC<{
|
||||
settingsStore: Settings;
|
||||
}> = observer(({ settingsStore }) => {
|
||||
const onChange = (value: boolean) => {
|
||||
settingsStore.themeConfig.setAnimations(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="form-group mb-0">
|
||||
<div className="form-check form-check-inline">
|
||||
<span className="custom-control custom-switch">
|
||||
<input
|
||||
id="configuration-animations"
|
||||
className="custom-control-input"
|
||||
type="checkbox"
|
||||
value=""
|
||||
checked={settingsStore.themeConfig.config.animations || false}
|
||||
onChange={(event) => onChange(event.target.checked)}
|
||||
/>
|
||||
<label
|
||||
className="custom-control-label cursor-pointer mr-3"
|
||||
htmlFor="configuration-animations"
|
||||
>
|
||||
Enable animations
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export { AnimationsConfiguration };
|
||||
@@ -0,0 +1,23 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<AnimationsConfiguration /> matches snapshot with default values 1`] = `
|
||||
"
|
||||
<div class=\\"form-group mb-0\\">
|
||||
<div class=\\"form-check form-check-inline\\">
|
||||
<span class=\\"custom-control custom-switch\\">
|
||||
<input id=\\"configuration-animations\\"
|
||||
class=\\"custom-control-input\\"
|
||||
type=\\"checkbox\\"
|
||||
value
|
||||
checked
|
||||
>
|
||||
<label class=\\"custom-control-label cursor-pointer mr-3\\"
|
||||
for=\\"configuration-animations\\"
|
||||
>
|
||||
Enable animations
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
"
|
||||
`;
|
||||
@@ -206,6 +206,23 @@ exports[`<Configuration /> matches snapshot 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class=\\"form-group mb-0\\">
|
||||
<div class=\\"form-check form-check-inline\\">
|
||||
<span class=\\"custom-control custom-switch\\">
|
||||
<input id=\\"configuration-animations\\"
|
||||
class=\\"custom-control-input\\"
|
||||
type=\\"checkbox\\"
|
||||
value
|
||||
checked
|
||||
>
|
||||
<label class=\\"custom-control-label cursor-pointer mr-3\\"
|
||||
for=\\"configuration-animations\\"
|
||||
>
|
||||
Enable animations
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class=\\"accordion card\\">
|
||||
|
||||
@@ -11,6 +11,7 @@ import { AlertGroupCollapseConfiguration } from "./AlertGroupCollapseConfigurati
|
||||
import { AlertGroupTitleBarColor } from "./AlertGroupTitleBarColor";
|
||||
import { ThemeConfiguration } from "./ThemeConfiguration";
|
||||
import { MultiGridConfiguration } from "./MultiGridConfiguration";
|
||||
import { AnimationsConfiguration } from "./AnimationsConfiguration";
|
||||
|
||||
const Configuration: FC<{
|
||||
settingsStore: Settings;
|
||||
@@ -33,6 +34,7 @@ const Configuration: FC<{
|
||||
<React.Fragment>
|
||||
<ThemeConfiguration settingsStore={settingsStore} />
|
||||
<AlertGroupTitleBarColor settingsStore={settingsStore} />
|
||||
<AnimationsConfiguration settingsStore={settingsStore} />
|
||||
</React.Fragment>
|
||||
}
|
||||
defaultIsOpen={defaultIsOpen}
|
||||
|
||||
@@ -225,6 +225,23 @@ exports[`<MainModalContent /> matches snapshot 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class=\\"form-group mb-0\\">
|
||||
<div class=\\"form-check form-check-inline\\">
|
||||
<span class=\\"custom-control custom-switch\\">
|
||||
<input id=\\"configuration-animations\\"
|
||||
class=\\"custom-control-input\\"
|
||||
type=\\"checkbox\\"
|
||||
value
|
||||
checked
|
||||
>
|
||||
<label class=\\"custom-control-label cursor-pointer mr-3\\"
|
||||
for=\\"configuration-animations\\"
|
||||
>
|
||||
Enable animations
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class=\\"accordion card\\">
|
||||
|
||||
@@ -7,6 +7,8 @@ import { disableBodyScroll, enableBodyScroll } from "body-scroll-lock";
|
||||
|
||||
import { useHotkeys } from "react-hotkeys-hook";
|
||||
|
||||
import { ThemeContext } from "Components/Theme";
|
||||
|
||||
const ModalInner: FC<{
|
||||
size: "lg" | "xl";
|
||||
isUpper: boolean;
|
||||
@@ -60,12 +62,15 @@ const Modal: FC<{
|
||||
onExited,
|
||||
children,
|
||||
}) => {
|
||||
const context = React.useContext(ThemeContext);
|
||||
return ReactDOM.createPortal(
|
||||
<React.Fragment>
|
||||
<CSSTransition
|
||||
in={isOpen}
|
||||
classNames="components-animation-modal"
|
||||
timeout={300}
|
||||
classNames={
|
||||
context.animations.duration ? "components-animation-modal" : ""
|
||||
}
|
||||
timeout={context.animations.duration ? 300 : 0}
|
||||
onExited={onExited}
|
||||
enter
|
||||
exit
|
||||
@@ -78,7 +83,7 @@ const Modal: FC<{
|
||||
<CSSTransition
|
||||
in={isOpen && !isUpper}
|
||||
classNames="components-animation-backdrop"
|
||||
timeout={300}
|
||||
timeout={context.animations.duration ? 300 : 0}
|
||||
enter
|
||||
exit
|
||||
unmountOnExit
|
||||
|
||||
@@ -40,7 +40,7 @@ const Placeholder = () => {
|
||||
);
|
||||
};
|
||||
|
||||
interface ThemeCtx {
|
||||
export interface ThemeCtx {
|
||||
isDark: boolean;
|
||||
reactSelectStyles: Styles;
|
||||
animations: {
|
||||
|
||||
@@ -7,6 +7,7 @@ export interface UIDefaults {
|
||||
HideFiltersWhenIdle: boolean;
|
||||
ColorTitlebar: boolean;
|
||||
Theme: ThemeT;
|
||||
Animations: boolean;
|
||||
MinimalGroupWidth: number;
|
||||
AlertsPerGroup: number;
|
||||
CollapseGroups: CollapseGroupsT;
|
||||
|
||||
@@ -102,15 +102,20 @@ interface SilenceFormConfigStorage {
|
||||
author: string;
|
||||
}
|
||||
class SilenceFormConfig {
|
||||
config: SilenceFormConfigStorage = localStored(
|
||||
"silenceFormConfig",
|
||||
{ author: "" },
|
||||
{ delay: 100 }
|
||||
);
|
||||
config: SilenceFormConfigStorage;
|
||||
saveAuthor: (newAuthor: string) => void;
|
||||
|
||||
saveAuthor = action((newAuthor: string) => {
|
||||
this.config.author = newAuthor;
|
||||
});
|
||||
constructor() {
|
||||
this.config = localStored(
|
||||
"silenceFormConfig",
|
||||
{ author: "" },
|
||||
{ delay: 100 }
|
||||
);
|
||||
|
||||
this.saveAuthor = action((newAuthor: string) => {
|
||||
this.config.author = newAuthor;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export type SortOrderT = "default" | "disabled" | "startsAt" | "label";
|
||||
@@ -129,6 +134,10 @@ class GridConfig {
|
||||
});
|
||||
|
||||
config: GridConfigStorage;
|
||||
setSortOrder: (o: SortOrderT) => void;
|
||||
setSortLabel: (l: string) => void;
|
||||
setSortReverse: (v: boolean | null) => void;
|
||||
|
||||
constructor(groupWidth: number) {
|
||||
this.config = localStored(
|
||||
"alertGridConfig",
|
||||
@@ -140,17 +149,17 @@ class GridConfig {
|
||||
},
|
||||
{ delay: 100 }
|
||||
);
|
||||
}
|
||||
|
||||
setSortOrder = action((o: SortOrderT) => {
|
||||
this.config.sortOrder = o;
|
||||
});
|
||||
setSortLabel = action((l: string) => {
|
||||
this.config.sortLabel = l;
|
||||
});
|
||||
setSortReverse = action((v: boolean | null) => {
|
||||
this.config.reverseSort = v;
|
||||
});
|
||||
this.setSortOrder = action((o: SortOrderT) => {
|
||||
this.config.sortOrder = o;
|
||||
});
|
||||
this.setSortLabel = action((l: string) => {
|
||||
this.config.sortLabel = l;
|
||||
});
|
||||
this.setSortReverse = action((v: boolean | null) => {
|
||||
this.config.reverseSort = v;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
interface FilterBarConfigStorage {
|
||||
@@ -158,6 +167,8 @@ interface FilterBarConfigStorage {
|
||||
}
|
||||
class FilterBarConfig {
|
||||
config: FilterBarConfigStorage;
|
||||
setAutohide: (v: boolean) => void;
|
||||
|
||||
constructor(autohide: boolean) {
|
||||
this.config = localStored(
|
||||
"filterBarConfig",
|
||||
@@ -168,16 +179,16 @@ class FilterBarConfig {
|
||||
delay: 100,
|
||||
}
|
||||
);
|
||||
this.setAutohide = action((v: boolean) => {
|
||||
this.config.autohide = v;
|
||||
});
|
||||
}
|
||||
|
||||
setAutohide = action((v: boolean) => {
|
||||
this.config.autohide = v;
|
||||
});
|
||||
}
|
||||
|
||||
export type ThemeT = "auto" | "light" | "dark";
|
||||
interface ThemeConfigStorage {
|
||||
theme: ThemeT;
|
||||
animations: boolean;
|
||||
}
|
||||
class ThemeConfig {
|
||||
options = Object.freeze({
|
||||
@@ -188,22 +199,29 @@ class ThemeConfig {
|
||||
light: { label: "Light theme", value: "light" },
|
||||
dark: { label: "Dark theme", value: "dark" },
|
||||
});
|
||||
|
||||
config: ThemeConfigStorage;
|
||||
constructor(defaultTheme: ThemeT) {
|
||||
setTheme: (v: ThemeT) => void;
|
||||
setAnimations: (v: boolean) => void;
|
||||
|
||||
constructor(defaultTheme: ThemeT, animations: boolean) {
|
||||
this.config = localStored(
|
||||
"themeConfig",
|
||||
{
|
||||
theme: defaultTheme,
|
||||
animations: animations,
|
||||
},
|
||||
{
|
||||
delay: 100,
|
||||
}
|
||||
);
|
||||
this.setTheme = action((v: ThemeT) => {
|
||||
this.config.theme = v;
|
||||
});
|
||||
this.setAnimations = action((v: boolean) => {
|
||||
this.config.animations = v;
|
||||
});
|
||||
}
|
||||
|
||||
setTheme = action((v: ThemeT) => {
|
||||
this.config.theme = v;
|
||||
});
|
||||
}
|
||||
|
||||
interface MultiGridConfigStorage {
|
||||
@@ -212,6 +230,9 @@ interface MultiGridConfigStorage {
|
||||
}
|
||||
class MultiGridConfig {
|
||||
config: MultiGridConfigStorage;
|
||||
setGridLabel: (l: string) => void;
|
||||
setGridSortReverse: (v: boolean) => void;
|
||||
|
||||
constructor(gridLabel: string, gridSortReverse: boolean) {
|
||||
this.config = localStored(
|
||||
"multiGridConfig",
|
||||
@@ -223,14 +244,14 @@ class MultiGridConfig {
|
||||
delay: 100,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
setGridLabel = action((l: string) => {
|
||||
this.config.gridLabel = l;
|
||||
});
|
||||
setGridSortReverse = action((v: boolean) => {
|
||||
this.config.gridSortReverse = v;
|
||||
});
|
||||
this.setGridLabel = action((l: string) => {
|
||||
this.config.gridLabel = l;
|
||||
});
|
||||
this.setGridSortReverse = action((v: boolean) => {
|
||||
this.config.gridSortReverse = v;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class Settings {
|
||||
@@ -251,6 +272,7 @@ class Settings {
|
||||
HideFiltersWhenIdle: true,
|
||||
ColorTitlebar: false,
|
||||
Theme: "auto",
|
||||
Animations: true,
|
||||
MinimalGroupWidth: 420,
|
||||
AlertsPerGroup: 5,
|
||||
CollapseGroups: "collapsedOnMobile",
|
||||
@@ -275,7 +297,10 @@ class Settings {
|
||||
this.filterBarConfig = new FilterBarConfig(
|
||||
defaultSettings.HideFiltersWhenIdle
|
||||
);
|
||||
this.themeConfig = new ThemeConfig(defaultSettings.Theme);
|
||||
this.themeConfig = new ThemeConfig(
|
||||
defaultSettings.Theme,
|
||||
defaultSettings.Animations
|
||||
);
|
||||
this.multiGridConfig = new MultiGridConfig(
|
||||
defaultSettings.MultiGridLabel,
|
||||
defaultSettings.MultiGridSortReverse
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
.components-grid-alertgrid-alertgroup {
|
||||
padding: 0.3rem;
|
||||
|
||||
&.components-animation-fade-appear-done,
|
||||
&.components-animation-fade-enter-done {
|
||||
&.components-animation-fade-appear-done.animate,
|
||||
&.components-animation-fade-enter-done.animate {
|
||||
z-index: 1;
|
||||
transition-property: transform;
|
||||
transition-duration: 0.4s;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { UIDefaults } from "Models/UI";
|
||||
|
||||
const DefaultsBase64 =
|
||||
"eyJSZWZyZXNoIjo0NTAwMDAwMDAwMCwiSGlkZUZpbHRlcnNXaGVuSWRsZSI6ZmFsc2UsIkNvbG9yVGl0bGViYXIiOmZhbHNlLCJUaGVtZSI6ImxpZ2h0IiwiTWluaW1hbEdyb3VwV2lkdGgiOjU1NSwiQWxlcnRzUGVyR3JvdXAiOjE1LCJDb2xsYXBzZUdyb3VwcyI6ImV4cGFuZGVkIiwiTXVsdGlHcmlkTGFiZWwiOiIiLCJNdWx0aUdyaWRTb3J0UmV2ZXJzZSI6ZmFsc2V9Cg==";
|
||||
"eyJSZWZyZXNoIjo0NTAwMDAwMDAwMCwiSGlkZUZpbHRlcnNXaGVuSWRsZSI6ZmFsc2UsIkNvbG9yVGl0bGViYXIiOmZhbHNlLCJUaGVtZSI6ImxpZ2h0IiwiQW5pbWF0aW9ucyI6dHJ1ZSwiTWluaW1hbEdyb3VwV2lkdGgiOjU1NSwiQWxlcnRzUGVyR3JvdXAiOjE1LCJDb2xsYXBzZUdyb3VwcyI6ImV4cGFuZGVkIiwiTXVsdGlHcmlkTGFiZWwiOiIiLCJNdWx0aUdyaWRTb3J0UmV2ZXJzZSI6ZmFsc2V9Cg==";
|
||||
const DefaultsObject: UIDefaults = {
|
||||
Refresh: 45000000000,
|
||||
HideFiltersWhenIdle: false,
|
||||
ColorTitlebar: false,
|
||||
Theme: "light",
|
||||
Animations: true,
|
||||
MinimalGroupWidth: 555,
|
||||
AlertsPerGroup: 15,
|
||||
CollapseGroups: "expanded",
|
||||
|
||||
@@ -11,4 +11,12 @@ const MockThemeContext = {
|
||||
reactSelectStyles: ReactSelectStyles(ReactSelectColors.Light),
|
||||
};
|
||||
|
||||
export { MockThemeContext };
|
||||
const MockThemeContextWithoutAnimations = {
|
||||
animations: {
|
||||
duration: 0,
|
||||
},
|
||||
isDark: false,
|
||||
reactSelectStyles: ReactSelectStyles(ReactSelectColors.Light),
|
||||
};
|
||||
|
||||
export { MockThemeContext, MockThemeContextWithoutAnimations };
|
||||
|
||||
Reference in New Issue
Block a user