Updated add panel related flows
@@ -1,12 +1,20 @@
|
|||||||
|
// Libraries
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
// Utils
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
|
import store from 'app/core/store';
|
||||||
|
|
||||||
|
// Store
|
||||||
|
import { store as reduxStore } from 'app/store/store';
|
||||||
|
import { updateLocation } from 'app/core/actions';
|
||||||
|
|
||||||
|
// Types
|
||||||
import { PanelModel } from '../../state';
|
import { PanelModel } from '../../state';
|
||||||
import { DashboardModel } from '../../state';
|
import { DashboardModel } from '../../state';
|
||||||
import store from 'app/core/store';
|
|
||||||
import { LS_PANEL_COPY_KEY } from 'app/core/constants';
|
import { LS_PANEL_COPY_KEY } from 'app/core/constants';
|
||||||
import { updateLocation } from 'app/core/actions';
|
import { LocationUpdate } from 'app/types';
|
||||||
import { store as reduxStore } from 'app/store/store';
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
panel: PanelModel;
|
panel: PanelModel;
|
||||||
@@ -17,17 +25,6 @@ export interface State {
|
|||||||
copiedPanelPlugins: any[];
|
copiedPanelPlugins: any[];
|
||||||
}
|
}
|
||||||
|
|
||||||
type Location = {
|
|
||||||
query: {
|
|
||||||
panelId: number;
|
|
||||||
edit: boolean;
|
|
||||||
fullscreen: boolean;
|
|
||||||
tab?: string;
|
|
||||||
isVizPickerOpen?: boolean;
|
|
||||||
};
|
|
||||||
partial: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export class AddPanelWidget extends React.Component<Props, State> {
|
export class AddPanelWidget extends React.Component<Props, State> {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@@ -66,10 +63,6 @@ export class AddPanelWidget extends React.Component<Props, State> {
|
|||||||
this.props.dashboard.removePanel(this.props.dashboard.panels[0]);
|
this.props.dashboard.removePanel(this.props.dashboard.panels[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
moveToEdit(location) {
|
|
||||||
reduxStore.dispatch(updateLocation(location));
|
|
||||||
}
|
|
||||||
|
|
||||||
onCreateNewPanel = (tab = 'queries') => {
|
onCreateNewPanel = (tab = 'queries') => {
|
||||||
const dashboard = this.props.dashboard;
|
const dashboard = this.props.dashboard;
|
||||||
const { gridPos } = this.props.panel;
|
const { gridPos } = this.props.panel;
|
||||||
@@ -83,7 +76,7 @@ export class AddPanelWidget extends React.Component<Props, State> {
|
|||||||
dashboard.addPanel(newPanel);
|
dashboard.addPanel(newPanel);
|
||||||
dashboard.removePanel(this.props.panel);
|
dashboard.removePanel(this.props.panel);
|
||||||
|
|
||||||
let location: Location = {
|
const location: LocationUpdate = {
|
||||||
query: {
|
query: {
|
||||||
panelId: newPanel.id,
|
panelId: newPanel.id,
|
||||||
edit: true,
|
edit: true,
|
||||||
@@ -93,18 +86,11 @@ export class AddPanelWidget extends React.Component<Props, State> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (tab === 'visualization') {
|
if (tab === 'visualization') {
|
||||||
location = {
|
location.query.tab = 'visualization';
|
||||||
...location,
|
location.query.openVizPicker = true;
|
||||||
query: {
|
|
||||||
...location.query,
|
|
||||||
tab: 'visualization',
|
|
||||||
isVizPickerOpen: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
this.moveToEdit(location);
|
|
||||||
} else {
|
|
||||||
this.moveToEdit(location);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reduxStore.dispatch(updateLocation(location));
|
||||||
};
|
};
|
||||||
|
|
||||||
onPasteCopiedPanel = panelPluginInfo => {
|
onPasteCopiedPanel = panelPluginInfo => {
|
||||||
@@ -162,28 +148,27 @@ export class AddPanelWidget extends React.Component<Props, State> {
|
|||||||
<div className="add-panel-widget">
|
<div className="add-panel-widget">
|
||||||
<div className="add-panel-widget__header grid-drag-handle">
|
<div className="add-panel-widget__header grid-drag-handle">
|
||||||
<i className="gicon gicon-add-panel" />
|
<i className="gicon gicon-add-panel" />
|
||||||
|
<span className="add-panel-widget__title">New Panel</span>
|
||||||
<button className="add-panel-widget__close" onClick={this.handleCloseAddPanel}>
|
<button className="add-panel-widget__close" onClick={this.handleCloseAddPanel}>
|
||||||
<i className="fa fa-close" />
|
<i className="fa fa-close" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="add-panel-widget__btn-container">
|
<div className="add-panel-widget__btn-container">
|
||||||
<div className="add-panel-widget__create">
|
<div className="add-panel-widget__create">
|
||||||
{this.renderOptionLink('queries', 'Add query', this.onCreateNewPanel)}
|
{this.renderOptionLink('queries', 'Add Query', this.onCreateNewPanel)}
|
||||||
{this.renderOptionLink('visualization', 'Choose Panel type', () =>
|
{this.renderOptionLink('visualization', 'Choose Visualization', () =>
|
||||||
this.onCreateNewPanel('visualization')
|
this.onCreateNewPanel('visualization')
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="add-panel-widget__actions">
|
<div className="add-panel-widget__actions">
|
||||||
<div className="add-panel-widget__action" onClick={this.onCreateNewRow}>
|
<button className="btn btn-inverse add-panel-widget__action" onClick={this.onCreateNewRow}>Convert to row</button>
|
||||||
Convert to row
|
|
||||||
</div>
|
|
||||||
{copiedPanelPlugins.length === 1 && (
|
{copiedPanelPlugins.length === 1 && (
|
||||||
<div
|
<button
|
||||||
className="add-panel-widget__action"
|
className="btn btn-inverse add-panel-widget__action"
|
||||||
onClick={() => this.onPasteCopiedPanel(copiedPanelPlugins[0])}
|
onClick={() => this.onPasteCopiedPanel(copiedPanelPlugins[0])}
|
||||||
>
|
>
|
||||||
Paste copied panel
|
Paste copied panel
|
||||||
</div>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,6 +14,9 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
cursor: move;
|
cursor: move;
|
||||||
|
background: $page-header-bg;
|
||||||
|
box-shadow: $page-header-shadow;
|
||||||
|
border-bottom: 1px solid $page-header-border-color;
|
||||||
|
|
||||||
.gicon {
|
.gicon {
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
@@ -26,9 +29,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.add-panel-widget__title {
|
||||||
|
font-size: $font-size-md;
|
||||||
|
font-weight: $font-weight-semi-bold;
|
||||||
|
margin-right: $spacer*2;
|
||||||
|
}
|
||||||
|
|
||||||
.add-panel-widget__link {
|
.add-panel-widget__link {
|
||||||
margin: 0 8px;
|
margin: 0 8px;
|
||||||
width: 150px;
|
width: 154px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-panel-widget__icon {
|
.add-panel-widget__icon {
|
||||||
@@ -54,6 +63,8 @@
|
|||||||
.add-panel-widget__create {
|
.add-panel-widget__create {
|
||||||
display: inherit;
|
display: inherit;
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
|
// this is to have the big button appear centered
|
||||||
|
margin-top: 55px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-panel-widget__actions {
|
.add-panel-widget__actions {
|
||||||
@@ -61,7 +72,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.add-panel-widget__action {
|
.add-panel-widget__action {
|
||||||
cursor: pointer;
|
|
||||||
margin: 0 4px;
|
margin: 0 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ exports[`Render should render component 1`] = `
|
|||||||
<i
|
<i
|
||||||
className="gicon gicon-add-panel"
|
className="gicon gicon-add-panel"
|
||||||
/>
|
/>
|
||||||
|
<span
|
||||||
|
className="add-panel-widget__title"
|
||||||
|
>
|
||||||
|
New Panel
|
||||||
|
</span>
|
||||||
<button
|
<button
|
||||||
className="add-panel-widget__close"
|
className="add-panel-widget__close"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
@@ -42,7 +47,7 @@ exports[`Render should render component 1`] = `
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span>
|
<span>
|
||||||
Add query
|
Add Query
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -60,7 +65,7 @@ exports[`Render should render component 1`] = `
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span>
|
<span>
|
||||||
Choose Panel type
|
Choose Visualization
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -68,12 +73,12 @@ exports[`Render should render component 1`] = `
|
|||||||
<div
|
<div
|
||||||
className="add-panel-widget__actions"
|
className="add-panel-widget__actions"
|
||||||
>
|
>
|
||||||
<div
|
<button
|
||||||
className="add-panel-widget__action"
|
className="btn btn-inverse add-panel-widget__action"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
>
|
>
|
||||||
Convert to row
|
Convert to row
|
||||||
</div>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import { QueriesTab } from './QueriesTab';
|
import { QueriesTab } from './QueriesTab';
|
||||||
import { VisualizationTab } from './VisualizationTab';
|
import VisualizationTab from './VisualizationTab';
|
||||||
import { GeneralTab } from './GeneralTab';
|
import { GeneralTab } from './GeneralTab';
|
||||||
import { AlertTab } from '../../alerting/AlertTab';
|
import { AlertTab } from '../../alerting/AlertTab';
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ export class PanelEditor extends PureComponent<PanelEditorProps> {
|
|||||||
onChangeTab = (tab: PanelEditorTab) => {
|
onChangeTab = (tab: PanelEditorTab) => {
|
||||||
store.dispatch(
|
store.dispatch(
|
||||||
updateLocation({
|
updateLocation({
|
||||||
query: { tab: tab.id },
|
query: { tab: tab.id, openVizPicker: null },
|
||||||
partial: true,
|
partial: true,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ import React, { PureComponent } from 'react';
|
|||||||
|
|
||||||
// Utils & Services
|
// Utils & Services
|
||||||
import { AngularComponent, getAngularLoader } from 'app/core/services/AngularLoader';
|
import { AngularComponent, getAngularLoader } from 'app/core/services/AngularLoader';
|
||||||
import { store } from 'app/store/store';
|
import { connectWithStore } from 'app/core/utils/connectWithReduxStore';
|
||||||
|
import { StoreState } from 'app/types';
|
||||||
|
import { updateLocation } from 'app/core/actions';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import { EditorTabBody, EditorToolbarView } from './EditorTabBody';
|
import { EditorTabBody, EditorToolbarView } from './EditorTabBody';
|
||||||
@@ -22,6 +24,8 @@ interface Props {
|
|||||||
plugin: PanelPlugin;
|
plugin: PanelPlugin;
|
||||||
angularPanel?: AngularComponent;
|
angularPanel?: AngularComponent;
|
||||||
onTypeChanged: (newType: PanelPlugin) => void;
|
onTypeChanged: (newType: PanelPlugin) => void;
|
||||||
|
updateLocation: typeof updateLocation;
|
||||||
|
urlOpenVizPicker: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
@@ -39,7 +43,7 @@ export class VisualizationTab extends PureComponent<Props, State> {
|
|||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
isVizPickerOpen: store.getState().location.query.isVizPickerOpen === true,
|
isVizPickerOpen: this.props.urlOpenVizPicker,
|
||||||
searchQuery: '',
|
searchQuery: '',
|
||||||
scrollTop: 0,
|
scrollTop: 0,
|
||||||
};
|
};
|
||||||
@@ -150,6 +154,10 @@ export class VisualizationTab extends PureComponent<Props, State> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onCloseVizPicker = () => {
|
onCloseVizPicker = () => {
|
||||||
|
if (this.props.urlOpenVizPicker) {
|
||||||
|
this.props.updateLocation({ query: { openVizPicker: null }, partial: true });
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({ isVizPickerOpen: false });
|
this.setState({ isVizPickerOpen: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -237,3 +245,13 @@ export class VisualizationTab extends PureComponent<Props, State> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state: StoreState) => ({
|
||||||
|
urlOpenVizPicker: !!state.location.query.openVizPicker
|
||||||
|
});
|
||||||
|
|
||||||
|
const mapDispatchToProps = {
|
||||||
|
updateLocation
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connectWithStore(VisualizationTab, mapStateToProps, mapDispatchToProps);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
width="121px" height="100px" viewBox="0 0 121 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
|
width="121px" height="100px" viewBox="0 0 121 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.st0{fill:#0A0A0C;}
|
.st0{fill:#161719;}
|
||||||
.st1{fill:#E3E2E2;}
|
.st1{fill:#E3E2E2;}
|
||||||
</style>
|
</style>
|
||||||
<g>
|
<g>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
@@ -5,7 +5,7 @@
|
|||||||
width="121px" height="100px" viewBox="0 0 121 100" style="enable-background:new 0 0 121 100;" xml:space="preserve">
|
width="121px" height="100px" viewBox="0 0 121 100" style="enable-background:new 0 0 121 100;" xml:space="preserve">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.st0{fill:url(#SVGID_1_);}
|
.st0{fill:url(#SVGID_1_);}
|
||||||
.st1{fill:#0A0A0C;}
|
.st1{fill:#161719;}
|
||||||
.st2{fill:url(#SVGID_2_);}
|
.st2{fill:url(#SVGID_2_);}
|
||||||
.st3{fill:url(#SVGID_3_);}
|
.st3{fill:url(#SVGID_3_);}
|
||||||
.st4{fill:url(#SVGID_4_);}
|
.st4{fill:url(#SVGID_4_);}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
@@ -4,7 +4,7 @@
|
|||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
width="121px" height="100px" viewBox="0 0 121 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
|
width="121px" height="100px" viewBox="0 0 121 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.st0{fill:#0A0A0C;}
|
.st0{fill:#161719;}
|
||||||
.st1{fill:#E3E2E2;}
|
.st1{fill:#E3E2E2;}
|
||||||
</style>
|
</style>
|
||||||
<g>
|
<g>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -5,7 +5,7 @@
|
|||||||
width="121px" height="100px" viewBox="0 0 121 100" style="enable-background:new 0 0 121 100;" xml:space="preserve">
|
width="121px" height="100px" viewBox="0 0 121 100" style="enable-background:new 0 0 121 100;" xml:space="preserve">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.st0{fill:url(#SVGID_1_);}
|
.st0{fill:url(#SVGID_1_);}
|
||||||
.st1{fill:#0A0A0C;}
|
.st1{fill:#161719;}
|
||||||
.st2{fill:url(#SVGID_2_);}
|
.st2{fill:url(#SVGID_2_);}
|
||||||
.st3{fill:url(#SVGID_3_);}
|
.st3{fill:url(#SVGID_3_);}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -4,7 +4,7 @@
|
|||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
width="121px" height="100px" viewBox="0 0 121 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
|
width="121px" height="100px" viewBox="0 0 121 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.st0{fill:#0A0A0C;}
|
.st0{fill:#161719;}
|
||||||
.st1{fill:#E3E2E2;}
|
.st1{fill:#E3E2E2;}
|
||||||
</style>
|
</style>
|
||||||
<g>
|
<g>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
@@ -5,7 +5,7 @@
|
|||||||
width="121px" height="100px" viewBox="0 0 121 100" style="enable-background:new 0 0 121 100;" xml:space="preserve">
|
width="121px" height="100px" viewBox="0 0 121 100" style="enable-background:new 0 0 121 100;" xml:space="preserve">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.st0{fill:url(#SVGID_1_);}
|
.st0{fill:url(#SVGID_1_);}
|
||||||
.st1{fill:#0A0A0C;}
|
.st1{fill:#161719;}
|
||||||
.st2{fill:url(#SVGID_2_);}
|
.st2{fill:url(#SVGID_2_);}
|
||||||
.st3{fill:url(#SVGID_3_);}
|
.st3{fill:url(#SVGID_3_);}
|
||||||
.st4{fill:url(#SVGID_4_);}
|
.st4{fill:url(#SVGID_4_);}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
@@ -4,7 +4,7 @@
|
|||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
width="121px" height="100px" viewBox="0 0 121 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
|
width="121px" height="100px" viewBox="0 0 121 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.st0{fill:#0A0A0C;}
|
.st0{fill:#161719;}
|
||||||
.st1{fill:#E3E2E2;}
|
.st1{fill:#E3E2E2;}
|
||||||
</style>
|
</style>
|
||||||
<path class="st0" d="M94.3,50C94.3,25.6,74.4,5.7,50,5.7S5.7,25.6,5.7,50S25.6,94.3,50,94.3S94.3,74.4,94.3,50z"/>
|
<path class="st0" d="M94.3,50C94.3,25.6,74.4,5.7,50,5.7S5.7,25.6,5.7,50S25.6,94.3,50,94.3S94.3,74.4,94.3,50z"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -5,7 +5,7 @@
|
|||||||
width="121px" height="100px" viewBox="0 0 121 100" style="enable-background:new 0 0 121 100;" xml:space="preserve">
|
width="121px" height="100px" viewBox="0 0 121 100" style="enable-background:new 0 0 121 100;" xml:space="preserve">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.st0{fill:url(#SVGID_1_);}
|
.st0{fill:url(#SVGID_1_);}
|
||||||
.st1{fill:#0A0A0C;}
|
.st1{fill:#161719;}
|
||||||
.st2{fill:url(#SVGID_2_);}
|
.st2{fill:url(#SVGID_2_);}
|
||||||
.st3{fill:url(#SVGID_3_);}
|
.st3{fill:url(#SVGID_3_);}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |