mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge remote-tracking branch 'grafana/master' into alpha-react-virtualized-table
* grafana/master: Minor refactoring of PR #15770 Alternative fix to detecting when to stop a playlist, fixes #15701 and #15702 fix discord notifier so it doesn't crash when there are no image generated Add a keybinding that toggles all legends in a dashboard removed color in color variables names changed some more color variables to use variables
This commit is contained in:
commit
6a8a60bcdf
@ -54,34 +54,34 @@ $orange: ${theme.colors.orange};
|
||||
$purple: ${theme.colors.purple};
|
||||
$variable: ${theme.colors.variable};
|
||||
|
||||
$brand-primary: $orange;
|
||||
$brand-success: $green-base;
|
||||
$brand-warning: $brand-primary;
|
||||
$brand-danger: $red-base;
|
||||
$brand-primary: ${theme.colors.brandPrimary};
|
||||
$brand-success: ${theme.colors.brandSuccess};
|
||||
$brand-warning: ${theme.colors.brandWarning};
|
||||
$brand-danger: ${theme.colors.brandDanger};
|
||||
|
||||
$query-red: $red-base;
|
||||
$query-green: #74e680;
|
||||
$query-purple: #fe85fc;
|
||||
$query-keyword: #66d9ef;
|
||||
$query-orange: $orange;
|
||||
$query-red: ${theme.colors.queryRed};
|
||||
$query-green: ${theme.colors.queryGreen};
|
||||
$query-purple: ${theme.colors.queryPurple};
|
||||
$query-orange: ${theme.colors.orange};
|
||||
$query-keyword: ${theme.colors.queryKeyword};
|
||||
|
||||
// Status colors
|
||||
// -------------------------
|
||||
$online: $green-base;
|
||||
$warn: #f79520;
|
||||
$critical: $red-base;
|
||||
$online: ${theme.colors.online};
|
||||
$warn: ${theme.colors.warn};
|
||||
$critical: ${theme.colors.critical};
|
||||
|
||||
// Scaffolding
|
||||
// -------------------------
|
||||
$body-bg: ${theme.colors.bodyBg};
|
||||
$page-bg: ${theme.colors.pageBg};
|
||||
|
||||
$body-color: $gray-4;
|
||||
$text-color: $gray-4;
|
||||
$text-color-strong: $white;
|
||||
$text-color-weak: $gray-2;
|
||||
$text-color-faint: $dark-10;
|
||||
$text-color-emphasis: $gray-5;
|
||||
$body-color: ${theme.colors.body};
|
||||
$text-color: ${theme.colors.text};
|
||||
$text-color-strong: ${theme.colors.textStrong};
|
||||
$text-color-weak: ${theme.colors.textWeak};
|
||||
$text-color-faint: ${theme.colors.textFaint};
|
||||
$text-color-emphasis: ${theme.colors.textEmphasis};
|
||||
|
||||
$text-shadow-faint: 1px 1px 4px rgb(45, 45, 45);
|
||||
$textShadow: none;
|
||||
@ -99,14 +99,14 @@ $edit-gradient: linear-gradient(180deg, $dark-2 50%, $input-black);
|
||||
|
||||
// Links
|
||||
// -------------------------
|
||||
$link-color: darken($white, 11%);
|
||||
$link-color-disabled: darken($link-color, 30%);
|
||||
$link-hover-color: $white;
|
||||
$external-link-color: $blue-light;
|
||||
$link-color: ${theme.colors.link};
|
||||
$link-color-disabled: ${theme.colors.linkDisabled};
|
||||
$link-hover-color: ${theme.colors.linkHover};
|
||||
$external-link-color: ${theme.colors.linkExternal};
|
||||
|
||||
// Typography
|
||||
// -------------------------
|
||||
$headings-color: darken($white, 11%);
|
||||
$headings-color: ${theme.colors.headingColor};
|
||||
$abbr-border-color: $gray-2 !default;
|
||||
$text-muted: $text-color-weak;
|
||||
|
||||
|
@ -46,34 +46,34 @@ $orange: ${theme.colors.orange};
|
||||
$purple: ${theme.colors.purple};
|
||||
$variable: ${theme.colors.variable};
|
||||
|
||||
$brand-primary: $orange;
|
||||
$brand-success: $green-base;
|
||||
$brand-warning: $orange;
|
||||
$brand-danger: $red-base;
|
||||
$brand-primary: ${theme.colors.brandPrimary};
|
||||
$brand-success: ${theme.colors.brandSuccess};
|
||||
$brand-warning: ${theme.colors.brandWarning};
|
||||
$brand-danger: ${theme.colors.brandDanger};
|
||||
|
||||
$query-red: $red-base;
|
||||
$query-green: $green-base;
|
||||
$query-purple: $purple;
|
||||
$query-orange: $orange;
|
||||
$query-keyword: $blue-base;
|
||||
$query-red: ${theme.colors.queryRed};
|
||||
$query-green: ${theme.colors.queryGreen};
|
||||
$query-purple: ${theme.colors.queryPurple};
|
||||
$query-orange: ${theme.colors.orange};
|
||||
$query-keyword: ${theme.colors.queryKeyword};
|
||||
|
||||
// Status colors
|
||||
// -------------------------
|
||||
$online: $green-shade;
|
||||
$warn: #f79520;
|
||||
$critical: $red-shade;
|
||||
$online: ${theme.colors.online};
|
||||
$warn: ${theme.colors.warn};
|
||||
$critical: ${theme.colors.critical};
|
||||
|
||||
// Scaffolding
|
||||
// -------------------------
|
||||
$body-bg: ${theme.colors.bodyBg};
|
||||
$page-bg: ${theme.colors.pageBg};
|
||||
|
||||
$body-color: $gray-1;
|
||||
$text-color: $gray-1;
|
||||
$text-color-strong: $dark-1;
|
||||
$text-color-weak: $gray-2;
|
||||
$text-color-faint: $gray-4;
|
||||
$text-color-emphasis: $dark-2;
|
||||
$body-color: ${theme.colors.body};
|
||||
$text-color: ${theme.colors.text};
|
||||
$text-color-strong: ${theme.colors.textStrong};
|
||||
$text-color-weak: ${theme.colors.textWeak};
|
||||
$text-color-faint: ${theme.colors.textFaint};
|
||||
$text-color-emphasis: ${theme.colors.textEmphasis};
|
||||
|
||||
$text-shadow-faint: none;
|
||||
|
||||
@ -85,14 +85,14 @@ $edit-gradient: linear-gradient(-60deg, $gray-7, #f5f6f9 70%, $gray-7 98%);
|
||||
|
||||
// Links
|
||||
// -------------------------
|
||||
$link-color: $gray-1;
|
||||
$link-color-disabled: lighten($link-color, 30%);
|
||||
$link-hover-color: darken($link-color, 20%);
|
||||
$external-link-color: $blue-shade;
|
||||
$link-color: ${theme.colors.link};
|
||||
$link-color-disabled: ${theme.colors.linkDisabled};
|
||||
$link-hover-color: ${theme.colors.linkHover};
|
||||
$external-link-color: ${theme.colors.linkExternal};
|
||||
|
||||
// Typography
|
||||
// -------------------------
|
||||
$headings-color: $text-color;
|
||||
$headings-color: ${theme.colors.headingColor};
|
||||
$abbr-border-color: $gray-2 !default;
|
||||
$text-muted: $text-color-weak;
|
||||
|
||||
|
@ -46,6 +46,10 @@ const darkTheme: GrafanaTheme = {
|
||||
colors: {
|
||||
...basicColors,
|
||||
inputBlack: '#09090b',
|
||||
brandPrimary: basicColors.orange,
|
||||
brandSuccess: basicColors.greenBase,
|
||||
brandWarning: basicColors.orange,
|
||||
brandDanger: basicColors.redBase,
|
||||
queryRed: basicColors.redBase,
|
||||
queryGreen: '#74e680',
|
||||
queryPurple: '#fe85fc',
|
||||
@ -56,16 +60,16 @@ const darkTheme: GrafanaTheme = {
|
||||
critical: basicColors.redBase,
|
||||
bodyBg: basicColors.dark2,
|
||||
pageBg: basicColors.dark2,
|
||||
bodyColor: basicColors.gray4,
|
||||
textColor: basicColors.gray4,
|
||||
textColorStrong: basicColors.white,
|
||||
textColorWeak: basicColors.gray2,
|
||||
textColorEmphasis: basicColors.gray5,
|
||||
textColorFaint: basicColors.dark5,
|
||||
linkColor: new tinycolor(basicColors.white).darken(11).toString(),
|
||||
linkColorDisabled: new tinycolor(basicColors.white).darken(11).toString(),
|
||||
linkColorHover: basicColors.white,
|
||||
linkColorExternal: basicColors.blue,
|
||||
body: basicColors.gray4,
|
||||
text: basicColors.gray4,
|
||||
textStrong: basicColors.white,
|
||||
textWeak: basicColors.gray2,
|
||||
textEmphasis: basicColors.gray5,
|
||||
textFaint: basicColors.dark5,
|
||||
link: new tinycolor(basicColors.white).darken(11).toString(),
|
||||
linkDisabled: new tinycolor(basicColors.white).darken(11).toString(),
|
||||
linkHover: basicColors.white,
|
||||
linkExternal: basicColors.blue,
|
||||
headingColor: new tinycolor(basicColors.white).darken(11).toString(),
|
||||
},
|
||||
background: {
|
||||
|
@ -47,26 +47,30 @@ const lightTheme: GrafanaTheme = {
|
||||
...basicColors,
|
||||
variable: basicColors.blue,
|
||||
inputBlack: '#09090b',
|
||||
queryRed: basicColors.red,
|
||||
brandPrimary: basicColors.orange,
|
||||
brandSuccess: basicColors.greenBase,
|
||||
brandWarning: basicColors.orange,
|
||||
brandDanger: basicColors.redBase,
|
||||
queryRed: basicColors.redBase,
|
||||
queryGreen: basicColors.greenBase,
|
||||
queryPurple: basicColors.purple,
|
||||
queryKeyword: basicColors.blue,
|
||||
queryKeyword: basicColors.blueBase,
|
||||
queryOrange: basicColors.orange,
|
||||
online: basicColors.greenShade,
|
||||
warn: '#f79520',
|
||||
critical: basicColors.redShade,
|
||||
bodyBg: basicColors.gray7,
|
||||
pageBg: basicColors.gray7,
|
||||
bodyColor: basicColors.gray1,
|
||||
textColor: basicColors.gray1,
|
||||
textColorStrong: basicColors.dark2,
|
||||
textColorWeak: basicColors.gray2,
|
||||
textColorEmphasis: basicColors.gray5,
|
||||
textColorFaint: basicColors.dark4,
|
||||
linkColor: basicColors.gray1,
|
||||
linkColorDisabled: new tinycolor(basicColors.gray1).lighten(30).toString(),
|
||||
linkColorHover: new tinycolor(basicColors.gray1).darken(20).toString(),
|
||||
linkColorExternal: basicColors.blueLight,
|
||||
body: basicColors.gray1,
|
||||
text: basicColors.gray1,
|
||||
textStrong: basicColors.dark2,
|
||||
textWeak: basicColors.gray2,
|
||||
textEmphasis: basicColors.gray5,
|
||||
textFaint: basicColors.dark4,
|
||||
link: basicColors.gray1,
|
||||
linkDisabled: new tinycolor(basicColors.gray1).lighten(30).toString(),
|
||||
linkHover: new tinycolor(basicColors.gray1).darken(20).toString(),
|
||||
linkExternal: basicColors.blueLight,
|
||||
headingColor: basicColors.gray1,
|
||||
},
|
||||
background: {
|
||||
|
@ -113,25 +113,33 @@ export interface GrafanaTheme extends GrafanaThemeCommons {
|
||||
queryPurple: string;
|
||||
queryKeyword: string;
|
||||
queryOrange: string;
|
||||
brandPrimary: string;
|
||||
brandSuccess: string;
|
||||
brandWarning: string;
|
||||
brandDanger: string;
|
||||
|
||||
// Status colors
|
||||
online: string;
|
||||
warn: string;
|
||||
critical: string;
|
||||
|
||||
// Link colors
|
||||
link: string;
|
||||
linkDisabled: string;
|
||||
linkHover: string;
|
||||
linkExternal: string;
|
||||
|
||||
// Text colors
|
||||
body: string;
|
||||
text: string;
|
||||
textStrong: string;
|
||||
textWeak: string;
|
||||
textFaint: string;
|
||||
textEmphasis: string;
|
||||
|
||||
// TODO: move to background section
|
||||
bodyBg: string;
|
||||
pageBg: string;
|
||||
bodyColor: string;
|
||||
textColor: string;
|
||||
textColorStrong: string;
|
||||
textColorWeak: string;
|
||||
textColorFaint: string;
|
||||
textColorEmphasis: string;
|
||||
linkColor: string;
|
||||
linkColorDisabled: string;
|
||||
linkColorHover: string;
|
||||
linkColorExternal: string;
|
||||
headingColor: string;
|
||||
};
|
||||
}
|
||||
|
@ -111,57 +111,20 @@ func (this *DiscordNotifier) Notify(evalContext *alerting.EvalContext) error {
|
||||
|
||||
json, _ := bodyJSON.MarshalJSON()
|
||||
|
||||
content_type := "application/json"
|
||||
|
||||
var body []byte
|
||||
|
||||
if embeddedImage {
|
||||
|
||||
var b bytes.Buffer
|
||||
|
||||
w := multipart.NewWriter(&b)
|
||||
|
||||
f, err := os.Open(evalContext.ImageOnDiskPath)
|
||||
|
||||
if err != nil {
|
||||
this.log.Error("Can't open graph file", err)
|
||||
return err
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
fw, err := w.CreateFormField("payload_json")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = fw.Write([]byte(string(json))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fw, err = w.CreateFormFile("file", "graph.png")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = io.Copy(fw, f); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w.Close()
|
||||
|
||||
body = b.Bytes()
|
||||
content_type = w.FormDataContentType()
|
||||
|
||||
} else {
|
||||
body = json
|
||||
}
|
||||
|
||||
cmd := &m.SendWebhookSync{
|
||||
Url: this.WebhookURL,
|
||||
Body: string(body),
|
||||
HttpMethod: "POST",
|
||||
ContentType: content_type,
|
||||
ContentType: "application/json",
|
||||
}
|
||||
|
||||
if !embeddedImage {
|
||||
cmd.Body = string(json)
|
||||
} else {
|
||||
err := this.embedImage(cmd, evalContext.ImageOnDiskPath, json)
|
||||
if err != nil {
|
||||
this.log.Error("failed to embed image", "error", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
|
||||
@ -171,3 +134,45 @@ func (this *DiscordNotifier) Notify(evalContext *alerting.EvalContext) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *DiscordNotifier) embedImage(cmd *m.SendWebhookSync, imagePath string, existingJSONBody []byte) error {
|
||||
f, err := os.Open(imagePath)
|
||||
defer f.Close()
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
cmd.Body = string(existingJSONBody)
|
||||
return nil
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var b bytes.Buffer
|
||||
w := multipart.NewWriter(&b)
|
||||
|
||||
fw, err := w.CreateFormField("payload_json")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = fw.Write([]byte(string(existingJSONBody))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fw, err = w.CreateFormFile("file", "graph.png")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = io.Copy(fw, f); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w.Close()
|
||||
|
||||
cmd.Body = string(b.Bytes())
|
||||
cmd.ContentType = w.FormDataContentType()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ export class HelpCtrl {
|
||||
{ keys: ['d', 'C'], description: 'Collapse all rows' },
|
||||
{ keys: ['d', 'a'], description: 'Toggle auto fit panels (experimental feature)' },
|
||||
{ keys: ['mod+o'], description: 'Toggle shared graph crosshair' },
|
||||
{ keys: ['d', 'l'], description: 'Toggle all panel legends' },
|
||||
],
|
||||
'Focused Panel': [
|
||||
{ keys: ['e'], description: 'Toggle panel edit view' },
|
||||
|
@ -256,6 +256,11 @@ export class KeybindingSrv {
|
||||
}
|
||||
});
|
||||
|
||||
// toggle all panel legends
|
||||
this.bind('d l', () => {
|
||||
dashboard.toggleLegendsForAll();
|
||||
});
|
||||
|
||||
// collapse all rows
|
||||
this.bind('d shift+c', () => {
|
||||
dashboard.collapseRows();
|
||||
|
@ -635,4 +635,32 @@ describe('DashboardModel', () => {
|
||||
expect(saveModel.templating.list[0].filters[0].value).toBe('server 1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Given a dashboard with one panel legend on and two off', () => {
|
||||
let model;
|
||||
|
||||
beforeEach(() => {
|
||||
const data = {
|
||||
panels: [
|
||||
{ id: 1, type: 'graph', gridPos: { x: 0, y: 0, w: 24, h: 2 }, legend: { show: true } },
|
||||
{ id: 3, type: 'graph', gridPos: { x: 0, y: 4, w: 12, h: 2 }, legend: { show: false } },
|
||||
{ id: 4, type: 'graph', gridPos: { x: 12, y: 4, w: 12, h: 2 }, legend: { show: false } },
|
||||
],
|
||||
};
|
||||
model = new DashboardModel(data);
|
||||
});
|
||||
|
||||
it('toggleLegendsForAll should toggle all legends on on first execution', () => {
|
||||
model.toggleLegendsForAll();
|
||||
const legendsOn = model.panels.filter(panel => panel.legend.show === true);
|
||||
expect(legendsOn.length).toBe(3);
|
||||
});
|
||||
|
||||
it('toggleLegendsForAll should toggle all legends off on second execution', () => {
|
||||
model.toggleLegendsForAll();
|
||||
model.toggleLegendsForAll();
|
||||
const legendsOn = model.panels.filter(panel => panel.legend.show === true);
|
||||
expect(legendsOn.length).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -917,4 +917,20 @@ export class DashboardModel {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toggleLegendsForAll() {
|
||||
const panelsWithLegends = this.panels.filter(panel => {
|
||||
return panel.legend !== undefined && panel.legend !== null;
|
||||
});
|
||||
|
||||
// determine if more panels are displaying legends or not
|
||||
const onCount = panelsWithLegends.filter(panel => panel.legend.show).length;
|
||||
const offCount = panelsWithLegends.length - onCount;
|
||||
const panelLegendsOn = onCount >= offCount;
|
||||
|
||||
for (const panel of panelsWithLegends) {
|
||||
panel.legend.show = !panelLegendsOn;
|
||||
panel.render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,6 +106,7 @@ export class PanelModel {
|
||||
events: Emitter;
|
||||
cacheTimeout?: any;
|
||||
cachedPluginOptions?: any;
|
||||
legend?: { show: boolean };
|
||||
|
||||
constructor(model) {
|
||||
this.events = new Emitter();
|
||||
|
@ -7,6 +7,7 @@ import coreModule from '../../core/core_module';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import locationUtil from 'app/core/utils/location_util';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import { store } from 'app/store/store';
|
||||
|
||||
export class PlaylistSrv {
|
||||
private cancelPromise: any;
|
||||
@ -15,6 +16,8 @@ export class PlaylistSrv {
|
||||
private interval: number;
|
||||
private startUrl: string;
|
||||
private numberOfLoops = 0;
|
||||
private storeUnsub: () => void;
|
||||
private validPlaylistUrl: string;
|
||||
isPlaying: boolean;
|
||||
|
||||
/** @ngInject */
|
||||
@ -39,15 +42,16 @@ export class PlaylistSrv {
|
||||
const dash = this.dashboards[this.index];
|
||||
const queryParams = this.$location.search();
|
||||
const filteredParams = _.pickBy(queryParams, value => value !== null);
|
||||
const nextDashboardUrl = locationUtil.stripBaseFromUrl(dash.url);
|
||||
|
||||
// this is done inside timeout to make sure digest happens after
|
||||
// as this can be called from react
|
||||
this.$timeout(() => {
|
||||
const stripedUrl = locationUtil.stripBaseFromUrl(dash.url);
|
||||
this.$location.url(stripedUrl + '?' + toUrlParams(filteredParams));
|
||||
this.$location.url(nextDashboardUrl + '?' + toUrlParams(filteredParams));
|
||||
});
|
||||
|
||||
this.index++;
|
||||
this.validPlaylistUrl = nextDashboardUrl;
|
||||
this.cancelPromise = this.$timeout(() => this.next(), this.interval);
|
||||
}
|
||||
|
||||
@ -56,6 +60,15 @@ export class PlaylistSrv {
|
||||
this.next();
|
||||
}
|
||||
|
||||
// Detect url changes not caused by playlist srv and stop playlist
|
||||
storeUpdated() {
|
||||
const state = store.getState();
|
||||
|
||||
if (state.location.path !== this.validPlaylistUrl) {
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
|
||||
start(playlistId) {
|
||||
this.stop();
|
||||
|
||||
@ -63,6 +76,10 @@ export class PlaylistSrv {
|
||||
this.index = 0;
|
||||
this.isPlaying = true;
|
||||
|
||||
// setup location tracking
|
||||
this.storeUnsub = store.subscribe(() => this.storeUpdated());
|
||||
this.validPlaylistUrl = this.$location.path();
|
||||
|
||||
appEvents.emit('playlist-started');
|
||||
|
||||
return this.backendSrv.get(`/api/playlists/${playlistId}`).then(playlist => {
|
||||
@ -85,6 +102,10 @@ export class PlaylistSrv {
|
||||
this.index = 0;
|
||||
this.isPlaying = false;
|
||||
|
||||
if (this.storeUnsub) {
|
||||
this.storeUnsub();
|
||||
}
|
||||
|
||||
if (this.cancelPromise) {
|
||||
this.$timeout.cancel(this.cancelPromise);
|
||||
}
|
||||
|
@ -1,4 +1,14 @@
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import { PlaylistSrv } from '../playlist_srv';
|
||||
import { setStore } from 'app/store/store';
|
||||
|
||||
const mockStore = configureMockStore();
|
||||
|
||||
setStore(
|
||||
mockStore({
|
||||
location: {},
|
||||
})
|
||||
);
|
||||
|
||||
const dashboards = [{ url: 'dash1' }, { url: 'dash2' }];
|
||||
|
||||
@ -19,6 +29,7 @@ const createPlaylistSrv = (): [PlaylistSrv, { url: jest.MockInstance<any, any> }
|
||||
const mockLocation = {
|
||||
url: jest.fn(),
|
||||
search: () => ({}),
|
||||
path: () => '/playlists/1',
|
||||
};
|
||||
|
||||
const mockTimeout = jest.fn();
|
||||
@ -96,4 +107,32 @@ describe('PlaylistSrv', () => {
|
||||
expect(hrefMock).toHaveBeenCalledTimes(3);
|
||||
expect(hrefMock).toHaveBeenLastCalledWith(initialUrl);
|
||||
});
|
||||
|
||||
it('storeUpdated should stop playlist when navigating away', async () => {
|
||||
await srv.start(1);
|
||||
|
||||
srv.storeUpdated();
|
||||
|
||||
expect(srv.isPlaying).toBe(false);
|
||||
});
|
||||
|
||||
it('storeUpdated should not stop playlist when navigating to next dashboard', async () => {
|
||||
await srv.start(1);
|
||||
|
||||
srv.next();
|
||||
|
||||
setStore(
|
||||
mockStore({
|
||||
location: {
|
||||
path: 'dash2',
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
expect((srv as any).validPlaylistUrl).toBe('dash2');
|
||||
|
||||
srv.storeUpdated();
|
||||
|
||||
expect(srv.isPlaying).toBe(true);
|
||||
});
|
||||
});
|
||||
|
@ -57,34 +57,34 @@ $orange: #eb7b18;
|
||||
$purple: #9933cc;
|
||||
$variable: #32d1df;
|
||||
|
||||
$brand-primary: $orange;
|
||||
$brand-success: $green-base;
|
||||
$brand-warning: $brand-primary;
|
||||
$brand-danger: $red-base;
|
||||
$brand-primary: #eb7b18;
|
||||
$brand-success: #299c46;
|
||||
$brand-warning: #eb7b18;
|
||||
$brand-danger: #e02f44;
|
||||
|
||||
$query-red: $red-base;
|
||||
$query-red: #e02f44;
|
||||
$query-green: #74e680;
|
||||
$query-purple: #fe85fc;
|
||||
$query-orange: #eb7b18;
|
||||
$query-keyword: #66d9ef;
|
||||
$query-orange: $orange;
|
||||
|
||||
// Status colors
|
||||
// -------------------------
|
||||
$online: $green-base;
|
||||
$online: #299c46;
|
||||
$warn: #f79520;
|
||||
$critical: $red-base;
|
||||
$critical: #e02f44;
|
||||
|
||||
// Scaffolding
|
||||
// -------------------------
|
||||
$body-bg: #161719;
|
||||
$page-bg: #161719;
|
||||
|
||||
$body-color: $gray-4;
|
||||
$text-color: $gray-4;
|
||||
$text-color-strong: $white;
|
||||
$text-color-weak: $gray-2;
|
||||
$text-color-faint: $dark-10;
|
||||
$text-color-emphasis: $gray-5;
|
||||
$body-color: #d8d9da;
|
||||
$text-color: #d8d9da;
|
||||
$text-color-strong: #ffffff;
|
||||
$text-color-weak: #8e8e8e;
|
||||
$text-color-faint: #222426;
|
||||
$text-color-emphasis: #ececec;
|
||||
|
||||
$text-shadow-faint: 1px 1px 4px rgb(45, 45, 45);
|
||||
$textShadow: none;
|
||||
@ -102,14 +102,14 @@ $edit-gradient: linear-gradient(180deg, $dark-2 50%, $input-black);
|
||||
|
||||
// Links
|
||||
// -------------------------
|
||||
$link-color: darken($white, 11%);
|
||||
$link-color-disabled: darken($link-color, 30%);
|
||||
$link-hover-color: $white;
|
||||
$external-link-color: $blue-light;
|
||||
$link-color: #e3e3e3;
|
||||
$link-color-disabled: #e3e3e3;
|
||||
$link-hover-color: #ffffff;
|
||||
$external-link-color: #33b5e5;
|
||||
|
||||
// Typography
|
||||
// -------------------------
|
||||
$headings-color: darken($white, 11%);
|
||||
$headings-color: #e3e3e3;
|
||||
$abbr-border-color: $gray-2 !default;
|
||||
$text-muted: $text-color-weak;
|
||||
|
||||
|
@ -49,34 +49,34 @@ $orange: #ff7941;
|
||||
$purple: #9954bb;
|
||||
$variable: #0083b3;
|
||||
|
||||
$brand-primary: $orange;
|
||||
$brand-success: $green-base;
|
||||
$brand-warning: $orange;
|
||||
$brand-danger: $red-base;
|
||||
$brand-primary: #ff7941;
|
||||
$brand-success: #3eb15b;
|
||||
$brand-warning: #ff7941;
|
||||
$brand-danger: #e02f44;
|
||||
|
||||
$query-red: $red-base;
|
||||
$query-green: $green-base;
|
||||
$query-purple: $purple;
|
||||
$query-orange: $orange;
|
||||
$query-keyword: $blue-base;
|
||||
$query-red: #e02f44;
|
||||
$query-green: #3eb15b;
|
||||
$query-purple: #9954bb;
|
||||
$query-orange: #ff7941;
|
||||
$query-keyword: #3274d9;
|
||||
|
||||
// Status colors
|
||||
// -------------------------
|
||||
$online: $green-shade;
|
||||
$online: #369b4f;
|
||||
$warn: #f79520;
|
||||
$critical: $red-shade;
|
||||
$critical: #c4162a;
|
||||
|
||||
// Scaffolding
|
||||
// -------------------------
|
||||
$body-bg: #f7f8fa;
|
||||
$page-bg: #f7f8fa;
|
||||
|
||||
$body-color: $gray-1;
|
||||
$text-color: $gray-1;
|
||||
$text-color-strong: $dark-1;
|
||||
$text-color-weak: $gray-2;
|
||||
$text-color-faint: $gray-4;
|
||||
$text-color-emphasis: $dark-2;
|
||||
$body-color: #52545c;
|
||||
$text-color: #52545c;
|
||||
$text-color-strong: #41444b;
|
||||
$text-color-weak: #767980;
|
||||
$text-color-faint: #35373f;
|
||||
$text-color-emphasis: #dde4ed;
|
||||
|
||||
$text-shadow-faint: none;
|
||||
|
||||
@ -88,14 +88,14 @@ $edit-gradient: linear-gradient(-60deg, $gray-7, #f5f6f9 70%, $gray-7 98%);
|
||||
|
||||
// Links
|
||||
// -------------------------
|
||||
$link-color: $gray-1;
|
||||
$link-color-disabled: lighten($link-color, 30%);
|
||||
$link-hover-color: darken($link-color, 20%);
|
||||
$external-link-color: $blue-shade;
|
||||
$link-color: #52545c;
|
||||
$link-color-disabled: #9ea0a9;
|
||||
$link-hover-color: #222326;
|
||||
$external-link-color: #5794f2;
|
||||
|
||||
// Typography
|
||||
// -------------------------
|
||||
$headings-color: $text-color;
|
||||
$headings-color: #52545c;
|
||||
$abbr-border-color: $gray-2 !default;
|
||||
$text-muted: $text-color-weak;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user