Commit 4f38af12 by Erik Sundell

Merge branch 'panel-edit-in-react' of https://github.com/grafana/grafana into panel-edit-in-react

parents 3c556c48 1db38852
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
<gf-form-checkbox <gf-form-checkbox
on-change="ctrl.onSelectAllChanged()" on-change="ctrl.onSelectAllChanged()"
checked="ctrl.selectAllChecked" checked="ctrl.selectAllChecked"
switch-class="gf-form-switch--transparent" switch-class="gf-form-checkbox--transparent"
/> />
<div class="search-results-filter-row__filters"> <div class="search-results-filter-row__filters">
<div class="gf-form-select-wrapper" ng-show="!(ctrl.canMove || ctrl.canDelete)"> <div class="gf-form-select-wrapper" ng-show="!(ctrl.canMove || ctrl.canDelete)">
......
<div ng-repeat="section in ctrl.results" class="search-section"> <div ng-repeat="section in ctrl.results" class="search-section">
<div class="search-section__header pointer" ng-hide="section.hideHeader" ng-class="{'selected': section.selected}" ng-click="ctrl.toggleFolderExpand(section)"> <div class="search-section__header pointer" ng-hide="section.hideHeader" ng-class="{'selected': section.selected}" ng-click="ctrl.toggleFolderExpand(section)">
<div ng-click="ctrl.toggleSelection(section, $event)"> <div ng-click="ctrl.toggleSelection(section, $event)" class="center-vh">
<gf-form-checkbox <gf-form-checkbox
ng-show="ctrl.editable" ng-show="ctrl.editable"
on-change="ctrl.selectionChanged($event)" on-change="ctrl.selectionChanged($event)"
checked="section.checked" checked="section.checked"
switch-class="gf-form-switch--transparent gf-form-switch--search-result__section"> switch-class="gf-form-checkbox--transparent">
</gf-form-checkbox> </gf-form-checkbox>
</div> </div>
<i class="search-section__header__icon" ng-class="section.icon"></i> <i class="search-section__header__icon" ng-class="section.icon"></i>
...@@ -21,12 +21,12 @@ ...@@ -21,12 +21,12 @@
<div ng-if="section.expanded"> <div ng-if="section.expanded">
<a ng-repeat="item in section.items" class="search-item search-item--indent" ng-class="{'selected': item.selected}" ng-href="{{::item.url}}" > <a ng-repeat="item in section.items" class="search-item search-item--indent" ng-class="{'selected': item.selected}" ng-href="{{::item.url}}" >
<div ng-click="ctrl.toggleSelection(item, $event)"> <div ng-click="ctrl.toggleSelection(item, $event)" class="center-vh">
<gf-form-checkbox <gf-form-checkbox
ng-show="ctrl.editable" ng-show="ctrl.editable"
on-change="ctrl.selectionChanged()" on-change="ctrl.selectionChanged()"
checked="item.checked" checked="item.checked"
switch-class="gf-form-switch--transparent gf-form-switch--search-result__item"> switch-class="gf-form-checkbox--transparent">
</gf-form-checkbox> </gf-form-checkbox>
</div> </div>
<span class="search-item__icon"> <span class="search-item__icon">
......
...@@ -79,10 +79,6 @@ export class DataSourcePicker extends PureComponent<Props, State> { ...@@ -79,10 +79,6 @@ export class DataSourcePicker extends PureComponent<Props, State> {
/> />
<i className="gf-form-input-icon fa fa-search" /> <i className="gf-form-input-icon fa fa-search" />
</label> </label>
<div className="p-l-1">
<button className="btn toggle-btn gf-form-btn active">All</button>
<button className="btn toggle-btn gf-form-btn">Favorites</button>
</div>
</> </>
); );
} }
......
...@@ -8,11 +8,7 @@ import { DashboardModel } from '../dashboard_model'; ...@@ -8,11 +8,7 @@ import { DashboardModel } from '../dashboard_model';
import './../../panel/metrics_tab'; import './../../panel/metrics_tab';
import config from 'app/core/config'; import config from 'app/core/config';
import { QueryInspector } from './QueryInspector'; import { QueryInspector } from './QueryInspector';
import { Switch } from 'app/core/components/Switch/Switch'; import { TimeRangeOptions } from './TimeRangeOptions';
import { Input } from 'app/core/components/Form';
import { InputStatus, EventsWithValidation } from 'app/core/components/Form/Input';
import { isValidTimeSpan } from 'app/core/utils/rangeutil';
import { ValidationEvents } from 'app/types';
// Services // Services
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
...@@ -43,20 +39,6 @@ interface LoadingPlaceholderProps { ...@@ -43,20 +39,6 @@ interface LoadingPlaceholderProps {
const LoadingPlaceholder: SFC<LoadingPlaceholderProps> = ({ text }) => <h2>{text}</h2>; const LoadingPlaceholder: SFC<LoadingPlaceholderProps> = ({ text }) => <h2>{text}</h2>;
const timeRangeValidationEvents: ValidationEvents = {
[EventsWithValidation.onBlur]: [
{
rule: value => {
if (!value) {
return true;
}
return isValidTimeSpan(value);
},
errorMessage: 'Not a valid timespan',
},
],
};
export class QueriesTab extends PureComponent<Props, State> { export class QueriesTab extends PureComponent<Props, State> {
element: any; element: any;
component: AngularComponent; component: AngularComponent;
...@@ -220,10 +202,19 @@ export class QueriesTab extends PureComponent<Props, State> { ...@@ -220,10 +202,19 @@ export class QueriesTab extends PureComponent<Props, State> {
}, },
}; };
return Object.keys(queryOptions).map(key => { const dsOptions = queryOptions
const options = allOptions[key]; ? Object.keys(queryOptions).map(key => {
return <DataSourceOption key={key} {...options} onChange={onChangeFn(allOptions[key].panelKey || key)} />; const options = allOptions[key];
}); return <DataSourceOption key={key} {...options} onChange={onChangeFn(allOptions[key].panelKey || key)} />;
})
: null;
return (
<>
<TimeRangeOptions panel={this.props.panel} />
{dsOptions}
</>
);
}; };
renderQueryInspector = () => { renderQueryInspector = () => {
...@@ -236,42 +227,9 @@ export class QueriesTab extends PureComponent<Props, State> { ...@@ -236,42 +227,9 @@ export class QueriesTab extends PureComponent<Props, State> {
return isLoading ? <LoadingPlaceholder text="Loading help..." /> : helpHtml; return isLoading ? <LoadingPlaceholder text="Loading help..." /> : helpHtml;
}; };
emptyToNull = (value: string) => {
return value === '' ? null : value;
};
onOverrideTime = (evt, status: InputStatus) => {
const { value } = evt.target;
const { panel } = this.props;
const emptyToNullValue = this.emptyToNull(value);
if (status === InputStatus.Valid && panel.timeFrom !== emptyToNullValue) {
panel.timeFrom = emptyToNullValue;
panel.refresh();
}
};
onTimeShift = (evt, status: InputStatus) => {
const { value } = evt.target;
const { panel } = this.props;
const emptyToNullValue = this.emptyToNull(value);
if (status === InputStatus.Valid && panel.timeShift !== emptyToNullValue) {
panel.timeShift = emptyToNullValue;
panel.refresh();
}
};
onToggleTimeOverride = () => {
const { panel } = this.props;
panel.hideTimeOverride = !panel.hideTimeOverride;
panel.refresh();
};
render() { render() {
const { currentDatasource } = this.state; const { currentDatasource } = this.state;
const hideTimeOverride = this.props.panel.hideTimeOverride; const { hasQueryHelp } = currentDatasource.meta;
console.log('hideTimeOverride', hideTimeOverride);
const { hasQueryHelp, queryOptions } = currentDatasource.meta;
const hasQueryOptions = !!queryOptions;
const dsInformation = { const dsInformation = {
title: currentDatasource.name, title: currentDatasource.name,
imgSrc: currentDatasource.meta.info.logos.small, imgSrc: currentDatasource.meta.info.logos.small,
...@@ -302,7 +260,7 @@ export class QueriesTab extends PureComponent<Props, State> { ...@@ -302,7 +260,7 @@ export class QueriesTab extends PureComponent<Props, State> {
const options = { const options = {
title: '', title: '',
icon: 'fa fa-cog', icon: 'fa fa-cog',
disabled: !hasQueryOptions, disabled: false,
render: this.renderOptions, render: this.renderOptions,
}; };
...@@ -310,52 +268,6 @@ export class QueriesTab extends PureComponent<Props, State> { ...@@ -310,52 +268,6 @@ export class QueriesTab extends PureComponent<Props, State> {
<EditorTabBody heading="Queries" main={dsInformation} toolbarItems={[options, queryInspector, dsHelp]}> <EditorTabBody heading="Queries" main={dsInformation} toolbarItems={[options, queryInspector, dsHelp]}>
<> <>
<div ref={element => (this.element = element)} style={{ width: '100%' }} /> <div ref={element => (this.element = element)} style={{ width: '100%' }} />
<h5 className="section-heading">Time Range</h5>
<div className="gf-form-group">
<div className="gf-form">
<span className="gf-form-label">
<i className="fa fa-clock-o" />
</span>
<span className="gf-form-label width-12">Override relative time</span>
<span className="gf-form-label width-6">Last</span>
<Input
type="text"
className="gf-form-input max-width-8"
placeholder="1h"
onBlur={this.onOverrideTime}
validationEvents={timeRangeValidationEvents}
hideErrorMessage={true}
/>
</div>
<div className="gf-form">
<span className="gf-form-label">
<i className="fa fa-clock-o" />
</span>
<span className="gf-form-label width-12">Add time shift</span>
<span className="gf-form-label width-6">Amount</span>
<Input
type="text"
className="gf-form-input max-width-8"
placeholder="1h"
onBlur={this.onTimeShift}
validationEvents={timeRangeValidationEvents}
hideErrorMessage={true}
/>
</div>
<div className="gf-form-inline">
<div className="gf-form">
<span className="gf-form-label">
<i className="fa fa-clock-o" />
</span>
</div>
<Switch label="Hide time override info" checked={hideTimeOverride} onChange={this.onToggleTimeOverride} />
</div>
</div>
</> </>
</EditorTabBody> </EditorTabBody>
); );
......
import React, { PureComponent } from 'react';
import { Switch } from 'app/core/components/Switch/Switch';
import { Input } from 'app/core/components/Form';
import { isValidTimeSpan } from 'app/core/utils/rangeutil';
import { ValidationEvents } from 'app/types';
import { EventsWithValidation } from 'app/core/components/Form/Input';
import { PanelModel } from '../panel_model';
import { InputStatus } from 'app/core/components/Form/Input';
const timeRangeValidationEvents: ValidationEvents = {
[EventsWithValidation.onBlur]: [
{
rule: value => {
if (!value) {
return true;
}
return isValidTimeSpan(value);
},
errorMessage: 'Not a valid timespan',
},
],
};
const emptyToNull = (value: string) => {
return value === '' ? null : value;
};
interface Props {
panel: PanelModel;
}
export class TimeRangeOptions extends PureComponent<Props> {
onOverrideTime = (evt, status: InputStatus) => {
const { value } = evt.target;
const { panel } = this.props;
const emptyToNullValue = emptyToNull(value);
if (status === InputStatus.Valid && panel.timeFrom !== emptyToNullValue) {
panel.timeFrom = emptyToNullValue;
panel.refresh();
}
};
onTimeShift = (evt, status: InputStatus) => {
const { value } = evt.target;
const { panel } = this.props;
const emptyToNullValue = emptyToNull(value);
if (status === InputStatus.Valid && panel.timeShift !== emptyToNullValue) {
panel.timeShift = emptyToNullValue;
panel.refresh();
}
};
onToggleTimeOverride = () => {
const { panel } = this.props;
panel.hideTimeOverride = !panel.hideTimeOverride;
panel.refresh();
};
render = () => {
const hideTimeOverride = this.props.panel.hideTimeOverride;
return (
<>
<h5 className="section-heading">Time Range</h5>
<div className="gf-form-group">
<div className="gf-form">
<span className="gf-form-label">
<i className="fa fa-clock-o" />
</span>
<span className="gf-form-label width-12">Override relative time</span>
<span className="gf-form-label width-6">Last</span>
<Input
type="text"
className="gf-form-input max-width-8"
placeholder="1h"
onBlur={this.onOverrideTime}
validationEvents={timeRangeValidationEvents}
hideErrorMessage={true}
/>
</div>
<div className="gf-form">
<span className="gf-form-label">
<i className="fa fa-clock-o" />
</span>
<span className="gf-form-label width-12">Add time shift</span>
<span className="gf-form-label width-6">Amount</span>
<Input
type="text"
className="gf-form-input max-width-8"
placeholder="1h"
onBlur={this.onTimeShift}
validationEvents={timeRangeValidationEvents}
hideErrorMessage={true}
/>
</div>
<div className="gf-form-inline">
<div className="gf-form">
<span className="gf-form-label">
<i className="fa fa-clock-o" />
</span>
</div>
<Switch label="Hide time override info" checked={hideTimeOverride} onChange={this.onToggleTimeOverride} />
</div>
</div>
</>
);
};
}
...@@ -84,6 +84,13 @@ class TestDataDatasource { ...@@ -84,6 +84,13 @@ class TestDataDatasource {
} }
return this.$q.when(events); return this.$q.when(events);
} }
testDatasource() {
return Promise.resolve({
status: 'success',
message: 'Data source is working',
});
}
} }
export { TestDataDatasource }; export { TestDataDatasource };
...@@ -79,7 +79,7 @@ $brand-gradient: linear-gradient( ...@@ -79,7 +79,7 @@ $brand-gradient: linear-gradient(
); );
$page-gradient: linear-gradient(180deg, #222426 10px, rgb(22, 23, 25) 100px); $page-gradient: linear-gradient(180deg, #222426 10px, rgb(22, 23, 25) 100px);
$edit-gradient: linear-gradient(180deg, rgb(22, 23, 25) 00px, #090909 60%); $edit-gradient: linear-gradient(180deg, rgb(22, 23, 25) 50%, #090909);
// Links // Links
// ------------------------- // -------------------------
...@@ -383,3 +383,6 @@ $panel-editor-viz-item-bg: $black; ...@@ -383,3 +383,6 @@ $panel-editor-viz-item-bg: $black;
$panel-editor-tabs-line-color: #e3e3e3; $panel-editor-tabs-line-color: #e3e3e3;
$panel-editor-viz-item-bg-hover: darken($blue, 47%); $panel-editor-viz-item-bg-hover: darken($blue, 47%);
$panel-editor-viz-item-bg-hover-active: darken($orange, 45%); $panel-editor-viz-item-bg-hover-active: darken($orange, 45%);
$panel-grid-placeholder-bg: darken($blue, 47%);
$panel-grid-placeholder-shadow: 0 0 4px $blue;
...@@ -393,3 +393,6 @@ $panel-editor-viz-item-bg: $white; ...@@ -393,3 +393,6 @@ $panel-editor-viz-item-bg: $white;
$panel-editor-tabs-line-color: $dark-5; $panel-editor-tabs-line-color: $dark-5;
$panel-editor-viz-item-bg-hover: lighten($blue, 62%); $panel-editor-viz-item-bg-hover: lighten($blue, 62%);
$panel-editor-viz-item-bg-hover-active: lighten($orange, 34%); $panel-editor-viz-item-bg-hover-active: lighten($orange, 34%);
$panel-grid-placeholder-bg: lighten($blue, 62%);
$panel-grid-placeholder-shadow: 0 0 4px $blue-light;
...@@ -57,6 +57,13 @@ ...@@ -57,6 +57,13 @@
} }
} }
.react-grid-item.react-grid-placeholder {
box-shadow: $panel-grid-placeholder-shadow;
background: $panel-grid-placeholder-bg;
z-index: 0;
opacity: unset;
}
.theme-dark { .theme-dark {
.react-grid-item > .react-resizable-handle::after { .react-grid-item > .react-resizable-handle::after {
border-right: 2px solid $gray-1; border-right: 2px solid $gray-1;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
height: 35px; height: 35px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center;
.gf-form-button-row { .gf-form-button-row {
padding-top: 0; padding-top: 0;
......
...@@ -141,19 +141,6 @@ $input-border: 1px solid $input-border-color; ...@@ -141,19 +141,6 @@ $input-border: 1px solid $input-border-color;
@include border-radius($label-border-radius-sm); @include border-radius($label-border-radius-sm);
} }
.gf-form-checkbox {
flex-shrink: 0;
padding: $input-padding-y $input-padding-x;
line-height: $input-line-height;
.checkbox-label {
display: inline;
cursor: pointer;
padding: $input-padding-y 0.4rem;
line-height: $input-line-height;
}
}
.gf-form-textarea { .gf-form-textarea {
max-width: 650px; max-width: 650px;
} }
......
...@@ -159,8 +159,6 @@ ...@@ -159,8 +159,6 @@
transition: transform 1 ease; transition: transform 1 ease;
&:hover { &:hover {
//background: $card-background-hover;
transform: scale(1.05);
box-shadow: $panel-editor-viz-item-shadow-hover; box-shadow: $panel-editor-viz-item-shadow-hover;
background: $panel-editor-viz-item-bg-hover; background: $panel-editor-viz-item-bg-hover;
border: $panel-editor-viz-item-border-hover; border: $panel-editor-viz-item-border-hover;
...@@ -171,7 +169,6 @@ ...@@ -171,7 +169,6 @@
border: 1px solid $orange; border: 1px solid $orange;
&:hover { &:hover {
transform: scale(1.05);
box-shadow: 0 0 6px $orange; box-shadow: 0 0 6px $orange;
border: 1px solid $orange; border: 1px solid $orange;
background: $panel-editor-viz-item-bg-hover-active; background: $panel-editor-viz-item-bg-hover-active;
...@@ -268,11 +265,9 @@ ...@@ -268,11 +265,9 @@
height: 44px; height: 44px;
&:hover { &:hover {
background: $card-background-hover;
transform: scaleY(1.1);
box-shadow: $panel-editor-viz-item-shadow-hover;
background: $panel-editor-viz-item-bg-hover; background: $panel-editor-viz-item-bg-hover;
border: $panel-editor-viz-item-border-hover; border: $panel-editor-viz-item-border-hover;
box-shadow: $panel-editor-viz-item-shadow-hover;
} }
&--selected { &--selected {
......
...@@ -78,6 +78,9 @@ input:checked + .gf-form-switch__slider::before { ...@@ -78,6 +78,9 @@ input:checked + .gf-form-switch__slider::before {
border: 1px solid $input-border-color; border: 1px solid $input-border-color;
border-left: none; border-left: none;
border-radius: $input-border-radius; border-radius: $input-border-radius;
display: flex;
align-items: center;
justify-content: center;
input { input {
opacity: 0; opacity: 0;
...@@ -88,25 +91,14 @@ input:checked + .gf-form-switch__slider::before { ...@@ -88,25 +91,14 @@ input:checked + .gf-form-switch__slider::before {
&--transparent { &--transparent {
background: transparent; background: transparent;
border: none; border: none;
} width: 20px;
&--search-result__section {
width: 3.05rem;
height: auto; height: auto;
position: relative; position: relative;
top: -5px; padding-left: 7px;
left: 3px;
}
&--search-result__item {
width: 2.7rem;
height: auto;
position: relative;
top: 3px;
} }
&--table-cell { &--table-cell {
width: 40px; width: 20px;
background: transparent; background: transparent;
height: auto; height: auto;
border: none; border: none;
...@@ -116,17 +108,14 @@ input:checked + .gf-form-switch__slider::before { ...@@ -116,17 +108,14 @@ input:checked + .gf-form-switch__slider::before {
} }
.gf-form-switch__checkbox { .gf-form-switch__checkbox {
position: absolute;
left: 16px;
height: 16px; height: 16px;
width: 16px; width: 16px;
border-radius: 3px; border-radius: 3px;
border: $checkbox-border; border: $checkbox-border;
background: $checkbox-bg; background: $checkbox-bg;
top: 8px;
display: flex; display: flex;
justify-content: center;
align-items: center; align-items: center;
justify-content: center;
} }
input:checked + .gf-form-switch__checkbox::before { input:checked + .gf-form-switch__checkbox::before {
......
...@@ -25,6 +25,7 @@ div.flot-text { ...@@ -25,6 +25,7 @@ div.flot-text {
bottom: 0; bottom: 0;
right: 0; right: 0;
margin: 0; margin: 0;
.panel-container { .panel-container {
border: none; border: none;
z-index: $zindex-sidemenu + 1; z-index: $zindex-sidemenu + 1;
......
...@@ -82,3 +82,10 @@ button.close { ...@@ -82,3 +82,10 @@ button.close {
.absolute { .absolute {
position: absolute; position: absolute;
} }
.center-vh {
display: flex;
align-items: center;
justify-content: center;
justify-items: center;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment