mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'master' into storybook/valuemappingseditor
This commit is contained in:
commit
a4d35e2fbc
54
README.md
54
README.md
@ -25,49 +25,71 @@ the latest master builds [here](https://grafana.com/grafana/download)
|
|||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
- Go (Latest Stable)
|
- Go (Latest Stable)
|
||||||
|
- bra [`go get github.com/Unknwon/bra`]
|
||||||
- Node.js LTS
|
- Node.js LTS
|
||||||
|
- yarn [`npm install -g yarn`]
|
||||||
|
|
||||||
|
### Get the project
|
||||||
|
|
||||||
|
**The project located in the go-path will be your working directory.**
|
||||||
|
|
||||||
### Building the backend
|
|
||||||
```bash
|
```bash
|
||||||
go get github.com/grafana/grafana
|
go get github.com/grafana/grafana
|
||||||
cd $GOPATH/src/github.com/grafana/grafana
|
cd $GOPATH/src/github.com/grafana/grafana
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building
|
||||||
|
|
||||||
|
#### The backend
|
||||||
|
|
||||||
|
```bash
|
||||||
go run build.go setup
|
go run build.go setup
|
||||||
go run build.go build
|
go run build.go build
|
||||||
```
|
```
|
||||||
|
|
||||||
### Building frontend assets
|
#### Frontend assets
|
||||||
|
|
||||||
For this you need Node.js (LTS version).
|
*For this you need Node.js (LTS version).*
|
||||||
|
|
||||||
To build the assets, rebuild on file change, and serve them by Grafana's webserver (http://localhost:3000):
|
|
||||||
```bash
|
```bash
|
||||||
npm install -g yarn
|
|
||||||
yarn install --pure-lockfile
|
yarn install --pure-lockfile
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run and rebuild on source change
|
||||||
|
|
||||||
|
#### Backend
|
||||||
|
|
||||||
|
To run the backend and rebuild on source change:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$GOPATH/bin/bra run
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Frontend
|
||||||
|
|
||||||
|
Rebuild on file change, and serve them by Grafana's webserver (http://localhost:3000):
|
||||||
|
|
||||||
|
```bash
|
||||||
yarn watch
|
yarn watch
|
||||||
```
|
```
|
||||||
|
|
||||||
Build the assets, rebuild on file change with Hot Module Replacement (HMR), and serve them by webpack-dev-server (http://localhost:3333):
|
Build the assets, rebuild on file change with Hot Module Replacement (HMR), and serve them by webpack-dev-server (http://localhost:3333):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn start
|
yarn start
|
||||||
# OR set a theme
|
# OR set a theme
|
||||||
env GRAFANA_THEME=light yarn start
|
env GRAFANA_THEME=light yarn start
|
||||||
```
|
```
|
||||||
Note: HMR for Angular is not supported. If you edit files in the Angular part of the app, the whole page will reload.
|
|
||||||
|
|
||||||
Run tests
|
*Note: HMR for Angular is not supported. If you edit files in the Angular part of the app, the whole page will reload.*
|
||||||
|
|
||||||
|
Run tests and rebuild on source change:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn jest
|
yarn jest
|
||||||
```
|
```
|
||||||
|
|
||||||
### Recompile backend on source change
|
**Open grafana in your browser (default: e.g. `http://localhost:3000`) and login with admin user (default: `user/pass = admin/admin`).**
|
||||||
|
|
||||||
To rebuild on source change.
|
|
||||||
```bash
|
|
||||||
go get github.com/Unknwon/bra
|
|
||||||
bra run
|
|
||||||
```
|
|
||||||
|
|
||||||
Open grafana in your browser (default: `http://localhost:3000`) and login with admin user (default: `user/pass = admin/admin`).
|
|
||||||
|
|
||||||
### Building a Docker image
|
### Building a Docker image
|
||||||
|
|
||||||
|
@ -113,6 +113,9 @@ cache_mode = private
|
|||||||
# Login cookie name
|
# Login cookie name
|
||||||
cookie_name = grafana_session
|
cookie_name = grafana_session
|
||||||
|
|
||||||
|
# Login cookie same site setting. defaults to `lax`. can be set to "lax", "strict" and "none"
|
||||||
|
cookie_samesite = lax
|
||||||
|
|
||||||
# How many days an session can be unused before we inactivate it
|
# How many days an session can be unused before we inactivate it
|
||||||
login_remember_days = 7
|
login_remember_days = 7
|
||||||
|
|
||||||
|
@ -109,6 +109,9 @@ log_queries =
|
|||||||
# Login cookie name
|
# Login cookie name
|
||||||
;cookie_name = grafana_session
|
;cookie_name = grafana_session
|
||||||
|
|
||||||
|
# Login cookie same site setting. defaults to `lax`. can be set to "lax", "strict" and "none"
|
||||||
|
;cookie_samesite = lax
|
||||||
|
|
||||||
# How many days an session can be unused before we inactivate it
|
# How many days an session can be unused before we inactivate it
|
||||||
;login_remember_days = 7
|
;login_remember_days = 7
|
||||||
|
|
||||||
|
@ -167,6 +167,7 @@ $arrowSize: 15px;
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sp-replacer:hover,
|
.sp-replacer:hover,
|
||||||
|
@ -1,26 +1,38 @@
|
|||||||
// Libraries
|
// Libraries
|
||||||
import React, { SFC } from 'react';
|
import React, { FunctionComponent } from 'react';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title?: string;
|
title?: string;
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
children: JSX.Element | JSX.Element[];
|
children: JSX.Element | JSX.Element[] | boolean;
|
||||||
|
onAdd?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PanelOptionsGroup: SFC<Props> = props => {
|
export const PanelOptionsGroup: FunctionComponent<Props> = props => {
|
||||||
return (
|
return (
|
||||||
<div className="panel-options-group">
|
<div className="panel-options-group">
|
||||||
{props.title && (
|
{props.onAdd ? (
|
||||||
<div className="panel-options-group__header">
|
<div className="panel-options-group__header">
|
||||||
{props.title}
|
<button className="panel-options-group__add-btn" onClick={props.onAdd}>
|
||||||
{props.onClose && (
|
<div className="panel-options-group__add-circle">
|
||||||
<button className="btn btn-link" onClick={props.onClose}>
|
<i className="fa fa-plus" />
|
||||||
<i className="fa fa-remove" />
|
</div>
|
||||||
</button>
|
<span className="panel-options-group__title">{props.title}</span>
|
||||||
)}
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
props.title && (
|
||||||
|
<div className="panel-options-group__header">
|
||||||
|
<span className="panel-options-group__title">{props.title}</span>
|
||||||
|
{props.onClose && (
|
||||||
|
<button className="btn btn-link" onClick={props.onClose}>
|
||||||
|
<i className="fa fa-remove" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
<div className="panel-options-group__body">{props.children}</div>
|
{props.children && <div className="panel-options-group__body">{props.children}</div>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -7,18 +7,57 @@
|
|||||||
|
|
||||||
.panel-options-group__header {
|
.panel-options-group__header {
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
font-size: 1.1rem;
|
|
||||||
background: $panel-options-group-header-bg;
|
background: $panel-options-group-header-bg;
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: $border-radius $border-radius 0 0;
|
border-radius: $border-radius $border-radius 0 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 0px;
|
top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.panel-options-group__add-btn {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.panel-options-group__add-circle {
|
||||||
|
background-color: $btn-success-bg;
|
||||||
|
color: $text-color-strong;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-options-group__add-circle {
|
||||||
|
@include gradientBar($btn-success-bg, $btn-success-bg-hl, $text-color);
|
||||||
|
|
||||||
|
border-radius: 50px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-right: 6px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-options-group__title {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
.panel-options-group__body {
|
.panel-options-group__body {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
.thresholds {
|
.thresholds {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thresholds-row {
|
.thresholds-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
height: 70px;
|
height: 62px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thresholds-row:first-child > .thresholds-row-color-indicator {
|
.thresholds-row:first-child > .thresholds-row-color-indicator {
|
||||||
@ -21,21 +21,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.thresholds-row-add-button {
|
.thresholds-row-add-button {
|
||||||
|
@include buttonBackground($btn-success-bg, $btn-success-bg-hl, $text-color);
|
||||||
|
|
||||||
align-self: center;
|
align-self: center;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
color: $green;
|
|
||||||
height: 24px;
|
height: 24px;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
background-color: $green;
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
|
||||||
|
|
||||||
.thresholds-row-add-button > i {
|
&:hover {
|
||||||
color: $white;
|
color: $text-color-strong;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.thresholds-row-color-indicator {
|
.thresholds-row-color-indicator {
|
||||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import { ValueMappingsEditor, Props } from './ValueMappingsEditor';
|
import { ValueMappingsEditor, Props } from './ValueMappingsEditor';
|
||||||
import { MappingType } from '../../types/panel';
|
import { MappingType } from '../../types';
|
||||||
|
|
||||||
const setup = (propOverrides?: object) => {
|
const setup = (propOverrides?: object) => {
|
||||||
const props: Props = {
|
const props: Props = {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
import MappingRow from './MappingRow';
|
import MappingRow from './MappingRow';
|
||||||
import { MappingType, ValueMapping } from '../../types/panel';
|
import { MappingType, ValueMapping } from '../../types';
|
||||||
import { PanelOptionsGroup } from '../PanelOptionsGroup/PanelOptionsGroup';
|
import { PanelOptionsGroup } from '..';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
valueMappings: ValueMapping[];
|
valueMappings: ValueMapping[];
|
||||||
@ -81,8 +81,7 @@ export class ValueMappingsEditor extends PureComponent<Props, State> {
|
|||||||
const { valueMappings } = this.state;
|
const { valueMappings } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PanelOptionsGroup title="Value Mappings">
|
<PanelOptionsGroup title="Add value mapping" onAdd={this.addMapping}>
|
||||||
<div>
|
|
||||||
{valueMappings.length > 0 &&
|
{valueMappings.length > 0 &&
|
||||||
valueMappings.map((valueMapping, index) => (
|
valueMappings.map((valueMapping, index) => (
|
||||||
<MappingRow
|
<MappingRow
|
||||||
@ -92,13 +91,6 @@ export class ValueMappingsEditor extends PureComponent<Props, State> {
|
|||||||
removeValueMapping={() => this.onRemoveMapping(valueMapping.id)}
|
removeValueMapping={() => this.onRemoveMapping(valueMapping.id)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
|
||||||
<div className="add-mapping-row" onClick={this.addMapping}>
|
|
||||||
<div className="add-mapping-row-icon">
|
|
||||||
<i className="fa fa-plus" />
|
|
||||||
</div>
|
|
||||||
<div className="add-mapping-row-label">Add mapping</div>
|
|
||||||
</div>
|
|
||||||
</PanelOptionsGroup>
|
</PanelOptionsGroup>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,55 +2,37 @@
|
|||||||
|
|
||||||
exports[`Render should render component 1`] = `
|
exports[`Render should render component 1`] = `
|
||||||
<Component
|
<Component
|
||||||
title="Value Mappings"
|
onAdd={[Function]}
|
||||||
|
title="Add value mapping"
|
||||||
>
|
>
|
||||||
<div>
|
<MappingRow
|
||||||
<MappingRow
|
key="Ok-0"
|
||||||
key="Ok-0"
|
removeValueMapping={[Function]}
|
||||||
removeValueMapping={[Function]}
|
updateValueMapping={[Function]}
|
||||||
updateValueMapping={[Function]}
|
valueMapping={
|
||||||
valueMapping={
|
Object {
|
||||||
Object {
|
"id": 1,
|
||||||
"id": 1,
|
"operator": "",
|
||||||
"operator": "",
|
"text": "Ok",
|
||||||
"text": "Ok",
|
"type": 1,
|
||||||
"type": 1,
|
"value": "20",
|
||||||
"value": "20",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/>
|
}
|
||||||
<MappingRow
|
/>
|
||||||
key="Meh-1"
|
<MappingRow
|
||||||
removeValueMapping={[Function]}
|
key="Meh-1"
|
||||||
updateValueMapping={[Function]}
|
removeValueMapping={[Function]}
|
||||||
valueMapping={
|
updateValueMapping={[Function]}
|
||||||
Object {
|
valueMapping={
|
||||||
"from": "21",
|
Object {
|
||||||
"id": 2,
|
"from": "21",
|
||||||
"operator": "",
|
"id": 2,
|
||||||
"text": "Meh",
|
"operator": "",
|
||||||
"to": "30",
|
"text": "Meh",
|
||||||
"type": 2,
|
"to": "30",
|
||||||
}
|
"type": 2,
|
||||||
}
|
}
|
||||||
/>
|
}
|
||||||
</div>
|
/>
|
||||||
<div
|
|
||||||
className="add-mapping-row"
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="add-mapping-row-icon"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
className="fa fa-plus"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="add-mapping-row-label"
|
|
||||||
>
|
|
||||||
Add mapping
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Component>
|
</Component>
|
||||||
`;
|
`;
|
||||||
|
@ -96,6 +96,7 @@ func (s *UserAuthTokenServiceImpl) writeSessionCookie(ctx *models.ReqContext, va
|
|||||||
Path: setting.AppSubUrl + "/",
|
Path: setting.AppSubUrl + "/",
|
||||||
Secure: s.Cfg.SecurityHTTPSCookies,
|
Secure: s.Cfg.SecurityHTTPSCookies,
|
||||||
MaxAge: maxAge,
|
MaxAge: maxAge,
|
||||||
|
SameSite: s.Cfg.LoginCookieSameSite,
|
||||||
}
|
}
|
||||||
|
|
||||||
http.SetCookie(ctx.Resp, &cookie)
|
http.SetCookie(ctx.Resp, &cookie)
|
||||||
|
@ -6,6 +6,7 @@ package setting
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@ -227,6 +228,7 @@ type Cfg struct {
|
|||||||
LoginCookieMaxDays int
|
LoginCookieMaxDays int
|
||||||
LoginCookieRotation int
|
LoginCookieRotation int
|
||||||
LoginDeleteExpiredTokensAfterDays int
|
LoginDeleteExpiredTokensAfterDays int
|
||||||
|
LoginCookieSameSite http.SameSite
|
||||||
|
|
||||||
SecurityHTTPSCookies bool
|
SecurityHTTPSCookies bool
|
||||||
}
|
}
|
||||||
@ -557,6 +559,20 @@ func (cfg *Cfg) Load(args *CommandLineArgs) error {
|
|||||||
cfg.LoginCookieName = login.Key("cookie_name").MustString("grafana_session")
|
cfg.LoginCookieName = login.Key("cookie_name").MustString("grafana_session")
|
||||||
cfg.LoginCookieMaxDays = login.Key("login_remember_days").MustInt(7)
|
cfg.LoginCookieMaxDays = login.Key("login_remember_days").MustInt(7)
|
||||||
cfg.LoginDeleteExpiredTokensAfterDays = login.Key("delete_expired_token_after_days").MustInt(30)
|
cfg.LoginDeleteExpiredTokensAfterDays = login.Key("delete_expired_token_after_days").MustInt(30)
|
||||||
|
|
||||||
|
samesiteString := login.Key("cookie_samesite").MustString("lax")
|
||||||
|
validSameSiteValues := map[string]http.SameSite{
|
||||||
|
"lax": http.SameSiteLaxMode,
|
||||||
|
"strict": http.SameSiteStrictMode,
|
||||||
|
"none": http.SameSiteDefaultMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
if samesite, ok := validSameSiteValues[samesiteString]; ok {
|
||||||
|
cfg.LoginCookieSameSite = samesite
|
||||||
|
} else {
|
||||||
|
cfg.LoginCookieSameSite = http.SameSiteLaxMode
|
||||||
|
}
|
||||||
|
|
||||||
cfg.LoginCookieRotation = login.Key("rotate_token_minutes").MustInt(10)
|
cfg.LoginCookieRotation = login.Key("rotate_token_minutes").MustInt(10)
|
||||||
if cfg.LoginCookieRotation < 2 {
|
if cfg.LoginCookieRotation < 2 {
|
||||||
cfg.LoginCookieRotation = 2
|
cfg.LoginCookieRotation = 2
|
||||||
|
@ -249,7 +249,7 @@ export class KeybindingSrv {
|
|||||||
if (panelInfo.panel.legend) {
|
if (panelInfo.panel.legend) {
|
||||||
const panelRef = dashboard.getPanelById(dashboard.meta.focusPanelId);
|
const panelRef = dashboard.getPanelById(dashboard.meta.focusPanelId);
|
||||||
panelRef.legend.show = !panelRef.legend.show;
|
panelRef.legend.show = !panelRef.legend.show;
|
||||||
panelRef.refresh();
|
panelRef.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -16,12 +16,12 @@ export class DataSourcesListItem extends PureComponent<Props> {
|
|||||||
</div>
|
</div>
|
||||||
<div className="card-item-body">
|
<div className="card-item-body">
|
||||||
<figure className="card-item-figure">
|
<figure className="card-item-figure">
|
||||||
<img src={dataSource.typeLogoUrl} />
|
<img src={dataSource.typeLogoUrl} alt={dataSource.name} />
|
||||||
</figure>
|
</figure>
|
||||||
<div className="card-item-details">
|
<div className="card-item-details">
|
||||||
<div className="card-item-name">
|
<div className="card-item-name">
|
||||||
{dataSource.name}
|
{dataSource.name}
|
||||||
{dataSource.isDefault && <span className="btn btn-secondary btn-mini">default</span>}
|
{dataSource.isDefault && <span className="btn btn-secondary btn-mini card-item-label">default</span>}
|
||||||
</div>
|
</div>
|
||||||
<div className="card-item-sub-name">{dataSource.url}</div>
|
<div className="card-item-sub-name">{dataSource.url}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -24,6 +24,7 @@ exports[`Render should render component 1`] = `
|
|||||||
className="card-item-figure"
|
className="card-item-figure"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
|
alt="gdev-cloudwatch"
|
||||||
src="public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png"
|
src="public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png"
|
||||||
/>
|
/>
|
||||||
</figure>
|
</figure>
|
||||||
|
@ -281,7 +281,7 @@ class GraphCtrl extends MetricsPanelCtrl {
|
|||||||
|
|
||||||
toggleLegend() {
|
toggleLegend() {
|
||||||
this.panel.legend.show = !this.panel.legend.show;
|
this.panel.legend.show = !this.panel.legend.show;
|
||||||
this.refresh();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
legendValuesOptionChanged() {
|
legendValuesOptionChanged() {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<h5 class="section-heading">Options</h5>
|
<h5 class="section-heading">Options</h5>
|
||||||
<gf-form-switch class="gf-form"
|
<gf-form-switch class="gf-form"
|
||||||
label="Show" label-class="width-7"
|
label="Show" label-class="width-7"
|
||||||
checked="ctrl.panel.legend.show" on-change="ctrl.refresh()">
|
checked="ctrl.panel.legend.show" on-change="ctrl.render()">
|
||||||
</gf-form-switch>
|
</gf-form-switch>
|
||||||
<gf-form-switch class="gf-form"
|
<gf-form-switch class="gf-form"
|
||||||
label="As Table" label-class="width-7"
|
label="As Table" label-class="width-7"
|
||||||
|
@ -109,6 +109,10 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-item-label {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.card-item-sub-name {
|
.card-item-sub-name {
|
||||||
color: $text-color-weak;
|
color: $text-color-weak;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
Loading…
Reference in New Issue
Block a user