mirror of
https://github.com/prymitive/karma
synced 2026-08-23 11:56:20 +00:00
fix(ui): add animation settings to the theme context
This commit is contained in:
committed by
Łukasz Mierzwa
parent
c8dfeb7a66
commit
7eaa7cbf34
+16
-8
@@ -3,7 +3,7 @@ import {
|
||||
configure,
|
||||
getStorybook,
|
||||
setAddon,
|
||||
addDecorator
|
||||
addDecorator,
|
||||
} from "@storybook/react";
|
||||
|
||||
import createPercyAddon from "@percy-io/percy-storybook";
|
||||
@@ -15,7 +15,7 @@ import { advanceTo } from "jest-date-mock";
|
||||
import { ThemeContext } from "Components/Theme";
|
||||
import {
|
||||
ReactSelectColors,
|
||||
ReactSelectStyles
|
||||
ReactSelectStyles,
|
||||
} from "Components/Theme/ReactSelect";
|
||||
|
||||
const { percyAddon, serializeStories } = createPercyAddon();
|
||||
@@ -24,17 +24,21 @@ setAddon(percyAddon);
|
||||
// mock date so the silence form always shows same preview
|
||||
advanceTo(new Date(Date.UTC(2018, 7, 14, 17, 36, 40)));
|
||||
|
||||
addDecorator(story => {
|
||||
addDecorator((story) => {
|
||||
document.body.style = "";
|
||||
return story();
|
||||
});
|
||||
addDecorator(story => {
|
||||
addDecorator((story) => {
|
||||
return (
|
||||
<div>
|
||||
<div className="theme-light">
|
||||
<ThemeContext.Provider
|
||||
value={{
|
||||
reactSelectStyles: ReactSelectStyles(ReactSelectColors.Light)
|
||||
reactSelectStyles: ReactSelectStyles(ReactSelectColors.Light),
|
||||
animations: {
|
||||
in: true,
|
||||
duration: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{story()}
|
||||
@@ -46,13 +50,17 @@ addDecorator(story => {
|
||||
width: "100%",
|
||||
backgroundColor: "#eee",
|
||||
marginTop: "4px",
|
||||
marginBottom: "4px"
|
||||
marginBottom: "4px",
|
||||
}}
|
||||
></div>
|
||||
<div className="theme-dark">
|
||||
<ThemeContext.Provider
|
||||
value={{
|
||||
reactSelectStyles: ReactSelectStyles(ReactSelectColors.Dark)
|
||||
reactSelectStyles: ReactSelectStyles(ReactSelectColors.Dark),
|
||||
animations: {
|
||||
in: true,
|
||||
duration: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{story()}
|
||||
@@ -65,7 +73,7 @@ addDecorator(story => {
|
||||
const req = require.context("../src/Components", true, /\.stories\.(js|tsx)$/);
|
||||
|
||||
function loadStories() {
|
||||
req.keys().forEach(filename => req(filename));
|
||||
req.keys().forEach((filename) => req(filename));
|
||||
}
|
||||
|
||||
configure(loadStories, module);
|
||||
|
||||
@@ -137,6 +137,10 @@ const App = observer(
|
||||
this.settingsStore.themeConfig.options.dark.value
|
||||
? ReactSelectStyles(ReactSelectColors.Dark)
|
||||
: ReactSelectStyles(ReactSelectColors.Light),
|
||||
animations: {
|
||||
enabled: true,
|
||||
duration: 1000,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<BodyTheme />
|
||||
|
||||
@@ -2,16 +2,21 @@ import React from "react";
|
||||
|
||||
import { Fade } from "react-reveal";
|
||||
|
||||
const CenteredMessage = ({ children, className }) => (
|
||||
<h1
|
||||
className={`${
|
||||
className ? className : "display-1 text-placeholder"
|
||||
} screen-center`}
|
||||
>
|
||||
<Fade in={true} duration={500}>
|
||||
{children}
|
||||
</Fade>
|
||||
</h1>
|
||||
);
|
||||
import { ThemeContext } from "Components/Theme";
|
||||
|
||||
const CenteredMessage = ({ children, className }) => {
|
||||
const theme = React.useContext(ThemeContext);
|
||||
return (
|
||||
<h1
|
||||
className={`${
|
||||
className ? className : "display-1 text-placeholder"
|
||||
} screen-center`}
|
||||
>
|
||||
<Fade in={theme.animations.in} duration={theme.animations.duration}>
|
||||
{children}
|
||||
</Fade>
|
||||
</h1>
|
||||
);
|
||||
};
|
||||
|
||||
export { CenteredMessage };
|
||||
|
||||
@@ -4,8 +4,13 @@ import { shallow } from "enzyme";
|
||||
|
||||
import toDiffableHtml from "diffable-html";
|
||||
|
||||
import { MockThemeContext } from "__mocks__/Theme";
|
||||
import { CenteredMessage } from ".";
|
||||
|
||||
beforeAll(() => {
|
||||
jest.spyOn(React, "useContext").mockImplementation(() => MockThemeContext);
|
||||
});
|
||||
|
||||
describe("<CenteredMessage />", () => {
|
||||
const Message = () => <div>Foo</div>;
|
||||
|
||||
|
||||
@@ -13,10 +13,12 @@ import {
|
||||
MockAnnotation,
|
||||
MockAlertGroup,
|
||||
MockSilence,
|
||||
} from "__mocks__/Alerts.js";
|
||||
} from "__mocks__/Alerts";
|
||||
import { MockThemeContext } from "__mocks__/Theme";
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
import { SilenceFormStore } from "Stores/SilenceFormStore";
|
||||
import { BorderClassMap } from "Common/Colors";
|
||||
import { ThemeContext } from "Components/Theme";
|
||||
import { Alert } from ".";
|
||||
|
||||
let alertStore;
|
||||
@@ -60,7 +62,11 @@ const MountedAlert = (alert, group, showAlertmanagers, showReceiver) => {
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
setIsMenuOpen={MockSetIsMenuOpen}
|
||||
/>
|
||||
/>,
|
||||
{
|
||||
wrappingComponent: ThemeContext.Provider,
|
||||
wrappingComponentProps: { value: MockThemeContext },
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -12,9 +12,11 @@ import {
|
||||
MockAnnotation,
|
||||
MockAlert,
|
||||
MockSilence,
|
||||
} from "__mocks__/Alerts.js";
|
||||
} from "__mocks__/Alerts";
|
||||
import { MockThemeContext } from "__mocks__/Theme";
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
import { SilenceFormStore } from "Stores/SilenceFormStore";
|
||||
import { ThemeContext } from "Components/Theme";
|
||||
import { GroupFooter } from ".";
|
||||
|
||||
let group;
|
||||
@@ -63,7 +65,11 @@ const MountedGroupFooter = () => {
|
||||
afterUpdate={MockAfterUpdate}
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
/>
|
||||
/>,
|
||||
{
|
||||
wrappingComponent: ThemeContext.Provider,
|
||||
wrappingComponentProps: { value: MockThemeContext },
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -18,6 +18,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";
|
||||
@@ -237,9 +238,9 @@ const AlertGroup = observer(
|
||||
style={{ ...style, ...extraStyle }}
|
||||
>
|
||||
<Fade
|
||||
in={true}
|
||||
duration={500}
|
||||
wait={500}
|
||||
in={this.context.animations.in}
|
||||
duration={this.context.animations.duration}
|
||||
wait={this.context.animations.duration}
|
||||
onReveal={this.renderConfig.setAnimationDone}
|
||||
>
|
||||
<div className={`card ${cardBackgroundClass}`}>
|
||||
@@ -313,5 +314,6 @@ const AlertGroup = observer(
|
||||
}
|
||||
}
|
||||
);
|
||||
AlertGroup.contextType = ThemeContext;
|
||||
|
||||
export { AlertGroup };
|
||||
|
||||
@@ -4,10 +4,12 @@ import { mount } from "enzyme";
|
||||
|
||||
import moment from "moment";
|
||||
|
||||
import { MockAlert, MockAlertGroup } from "__mocks__/Alerts.js";
|
||||
import { MockAlert, MockAlertGroup } from "__mocks__/Alerts";
|
||||
import { MockThemeContext } from "__mocks__/Theme";
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
import { Settings } from "Stores/Settings";
|
||||
import { SilenceFormStore } from "Stores/SilenceFormStore";
|
||||
import { ThemeContext } from "Components/Theme";
|
||||
import { AlertGroup } from ".";
|
||||
|
||||
let alertStore;
|
||||
@@ -66,7 +68,11 @@ const MountedAlertGroup = (afterUpdate, showAlertmanagers) => {
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
gridLabelValue=""
|
||||
/>
|
||||
/>,
|
||||
{
|
||||
wrappingComponent: ThemeContext.Provider,
|
||||
wrappingComponentProps: { value: MockThemeContext },
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import { APIGrid } from "Models/API";
|
||||
import { FilteringLabel } from "Components/Labels/FilteringLabel";
|
||||
import { FilteringCounterBadge } from "Components/Labels/FilteringCounterBadge";
|
||||
import { TooltipWrapper } from "Components/TooltipWrapper";
|
||||
import { ThemeContext } from "Components/Theme";
|
||||
import { DefaultDetailsCollapseValue } from "./AlertGroup/DetailsToggle";
|
||||
import { AlertGroup } from "./AlertGroup";
|
||||
|
||||
@@ -182,7 +183,10 @@ const Grid = observer(
|
||||
return (
|
||||
<React.Fragment>
|
||||
{grid.labelName !== "" && (
|
||||
<Fade in={true} duration={500}>
|
||||
<Fade
|
||||
in={this.context.animations.in}
|
||||
duration={this.context.animations.duration}
|
||||
>
|
||||
<h5 className="components-grid-swimlane d-flex flex-row justify-content-between rounded px-2 py-1 mt-2 mb-0 border border-dark">
|
||||
<span
|
||||
className="flex-shrink-1 flex-grow-1"
|
||||
@@ -297,5 +301,6 @@ const Grid = observer(
|
||||
}
|
||||
}
|
||||
);
|
||||
Grid.contextType = ThemeContext;
|
||||
|
||||
export { Grid };
|
||||
|
||||
@@ -4,11 +4,13 @@ import { shallow, mount } from "enzyme";
|
||||
|
||||
import { advanceBy, clear } from "jest-date-mock";
|
||||
|
||||
import { MockAlert, MockAlertGroup } from "__mocks__/Alerts.js";
|
||||
import { MockAlert, MockAlertGroup } from "__mocks__/Alerts";
|
||||
import { MockThemeContext } 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 { GetGridElementWidth, GridSizesConfig } from "./GridSize";
|
||||
import { Grid } from "./Grid";
|
||||
import { AlertGrid } from ".";
|
||||
@@ -42,7 +44,11 @@ const MountedAlertGrid = () => {
|
||||
alertStore={alertStore}
|
||||
settingsStore={settingsStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
/>
|
||||
/>,
|
||||
{
|
||||
wrappingComponent: ThemeContext.Provider,
|
||||
wrappingComponentProps: { value: MockThemeContext },
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@@ -93,7 +99,11 @@ const MountedGrid = () => {
|
||||
groupWidth={420}
|
||||
grid={MockGrid()}
|
||||
outerPadding={0}
|
||||
/>
|
||||
/>,
|
||||
{
|
||||
wrappingComponent: ThemeContext.Provider,
|
||||
wrappingComponentProps: { value: MockThemeContext },
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -2,10 +2,15 @@ import React from "react";
|
||||
|
||||
import { shallow } from "enzyme";
|
||||
|
||||
import { MockThemeContext } from "__mocks__/Theme";
|
||||
import toDiffableHtml from "diffable-html";
|
||||
|
||||
import { EmptyGrid } from ".";
|
||||
|
||||
beforeAll(() => {
|
||||
jest.spyOn(React, "useContext").mockImplementation(() => MockThemeContext);
|
||||
});
|
||||
|
||||
describe("<EmptyGrid />", () => {
|
||||
it("matches snapshot", () => {
|
||||
const tree = shallow(<EmptyGrid />);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { Component } from "react";
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
@@ -6,27 +6,21 @@ import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclama
|
||||
|
||||
import { CenteredMessage } from "Components/CenteredMessage";
|
||||
|
||||
class FatalError extends Component {
|
||||
static propTypes = {
|
||||
message: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { message } = this.props;
|
||||
return (
|
||||
<CenteredMessage>
|
||||
<div className="container-fluid text-center">
|
||||
<FontAwesomeIcon
|
||||
icon={faExclamationCircle}
|
||||
className="screen-center-icon-big text-danger mb-4"
|
||||
/>
|
||||
<p className="lead text-white bg-secondary p-3 rounded text-wrap text-break">
|
||||
{message}
|
||||
</p>
|
||||
</div>
|
||||
</CenteredMessage>
|
||||
);
|
||||
}
|
||||
}
|
||||
const FatalError = ({ message }) => (
|
||||
<CenteredMessage>
|
||||
<div className="container-fluid text-center">
|
||||
<FontAwesomeIcon
|
||||
icon={faExclamationCircle}
|
||||
className="screen-center-icon-big text-danger mb-4"
|
||||
/>
|
||||
<p className="lead text-white bg-secondary p-3 rounded text-wrap text-break">
|
||||
{message}
|
||||
</p>
|
||||
</div>
|
||||
</CenteredMessage>
|
||||
);
|
||||
FatalError.propTypes = {
|
||||
message: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export { FatalError };
|
||||
|
||||
@@ -4,8 +4,13 @@ import { shallow } from "enzyme";
|
||||
|
||||
import toDiffableHtml from "diffable-html";
|
||||
|
||||
import { MockThemeContext } from "__mocks__/Theme";
|
||||
import { FatalError } from ".";
|
||||
|
||||
beforeAll(() => {
|
||||
jest.spyOn(React, "useContext").mockImplementation(() => MockThemeContext);
|
||||
});
|
||||
|
||||
describe("<FatalError />", () => {
|
||||
it("matches snapshot", () => {
|
||||
const tree = shallow(<FatalError message="foo bar" />);
|
||||
|
||||
@@ -4,11 +4,13 @@ import { mount, shallow } from "enzyme";
|
||||
|
||||
import toDiffableHtml from "diffable-html";
|
||||
|
||||
import { MockThemeContext } from "__mocks__/Theme";
|
||||
import { ReloadNeeded } from ".";
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
jest.clearAllTimers();
|
||||
jest.spyOn(React, "useContext").mockImplementation(() => MockThemeContext);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -4,11 +4,13 @@ import { mount, shallow } from "enzyme";
|
||||
|
||||
import toDiffableHtml from "diffable-html";
|
||||
|
||||
import { MockThemeContext } from "__mocks__/Theme";
|
||||
import { UpgradeNeeded } from ".";
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
jest.clearAllTimers();
|
||||
jest.spyOn(React, "useContext").mockImplementation(() => MockThemeContext);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -4,8 +4,13 @@ import { shallow } from "enzyme";
|
||||
|
||||
import toDiffableHtml from "diffable-html";
|
||||
|
||||
import { MockThemeContext } from "__mocks__/Theme";
|
||||
import { UpstreamError } from ".";
|
||||
|
||||
beforeAll(() => {
|
||||
jest.spyOn(React, "useContext").mockImplementation(() => MockThemeContext);
|
||||
});
|
||||
|
||||
describe("<UpstreamError />", () => {
|
||||
it("matches snapshot", () => {
|
||||
const tree = shallow(<UpstreamError name="foo" message="bar" />);
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Fade } from "react-reveal";
|
||||
import { APISilence } from "Models/API";
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
import { SilenceFormStore, SilenceTabNames } from "Stores/SilenceFormStore";
|
||||
import { ThemeContext } from "Components/Theme";
|
||||
import { SilenceComment } from "./SilenceComment";
|
||||
import { SilenceDetails } from "./SilenceDetails";
|
||||
|
||||
@@ -78,7 +79,10 @@ const ManagedSilence = observer(
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Fade in={true} duration={500}>
|
||||
<Fade
|
||||
in={this.context.animations.in}
|
||||
duration={this.context.animations.duration}
|
||||
>
|
||||
<div className="card my-1 components-managed-silence">
|
||||
<div className="card-header rounded-0 border-bottom-0 px-3">
|
||||
<SilenceComment
|
||||
@@ -110,5 +114,6 @@ const ManagedSilence = observer(
|
||||
}
|
||||
}
|
||||
);
|
||||
ManagedSilence.contextType = ThemeContext;
|
||||
|
||||
export { ManagedSilence };
|
||||
|
||||
@@ -8,8 +8,10 @@ import moment from "moment";
|
||||
import { advanceTo, clear } from "jest-date-mock";
|
||||
|
||||
import { MockSilence } from "__mocks__/Alerts";
|
||||
import { MockThemeContext } from "__mocks__/Theme";
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
import { SilenceFormStore } from "Stores/SilenceFormStore";
|
||||
import { ThemeContext } from "Components/Theme";
|
||||
import { ManagedSilence } from ".";
|
||||
|
||||
let alertStore;
|
||||
@@ -62,7 +64,11 @@ const MountedManagedSilence = (onDidUpdate) => {
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
onDidUpdate={onDidUpdate}
|
||||
/>
|
||||
/>,
|
||||
{
|
||||
wrappingComponent: ThemeContext.Provider,
|
||||
wrappingComponentProps: { value: MockThemeContext },
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { Component } from "react";
|
||||
import React, { Component, useContext } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { observable, action } from "mobx";
|
||||
@@ -20,6 +20,7 @@ import { Settings } from "Stores/Settings";
|
||||
import { FetchGet } from "Common/Fetch";
|
||||
import { ManagedSilence } from "Components/ManagedSilence";
|
||||
import { PageSelect } from "Components/Pagination";
|
||||
import { ThemeContext } from "Components/Theme";
|
||||
|
||||
const FetchError = ({ message }) => (
|
||||
<div className="text-center">
|
||||
@@ -33,13 +34,17 @@ FetchError.propTypes = {
|
||||
message: PropTypes.node.isRequired,
|
||||
};
|
||||
|
||||
const Placeholder = ({ content }) => (
|
||||
<Fade in={true} duration={500}>
|
||||
<div className="jumbotron bg-transparent">
|
||||
<h1 className="display-5 text-placeholder text-center">{content}</h1>
|
||||
</div>
|
||||
</Fade>
|
||||
);
|
||||
const Placeholder = ({ content }) => {
|
||||
const theme = useContext(ThemeContext);
|
||||
|
||||
return (
|
||||
<Fade in={theme.animations.in} duration={theme.animations.duration}>
|
||||
<div className="jumbotron bg-transparent">
|
||||
<h1 className="display-5 text-placeholder text-center">{content}</h1>
|
||||
</div>
|
||||
</Fade>
|
||||
);
|
||||
};
|
||||
Placeholder.propTypes = {
|
||||
content: PropTypes.node.isRequired,
|
||||
};
|
||||
|
||||
@@ -8,10 +8,12 @@ import moment from "moment";
|
||||
import { advanceTo, clear } from "jest-date-mock";
|
||||
|
||||
import { MockSilence } from "__mocks__/Alerts";
|
||||
import { MockThemeContext } from "__mocks__/Theme";
|
||||
import { PressKey } from "__mocks__/KeyPress";
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
import { Settings } from "Stores/Settings";
|
||||
import { SilenceFormStore } from "Stores/SilenceFormStore";
|
||||
import { ThemeContext } from "Components/Theme";
|
||||
import { Browser } from ".";
|
||||
|
||||
let alertStore;
|
||||
@@ -80,7 +82,11 @@ const MountedBrowser = () => {
|
||||
silenceFormStore={silenceFormStore}
|
||||
settingsStore={settingsStore}
|
||||
onDeleteModalClose={MockOnDeleteModalClose}
|
||||
/>
|
||||
/>,
|
||||
{
|
||||
wrappingComponent: ThemeContext.Provider,
|
||||
wrappingComponentProps: { value: MockThemeContext },
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
const MockThemeContext = {
|
||||
animations: {
|
||||
in: undefined,
|
||||
duration: 500,
|
||||
},
|
||||
};
|
||||
|
||||
export { MockThemeContext };
|
||||
Reference in New Issue
Block a user