From f75387bd146e6b0c91ede0f01203485f6964885b Mon Sep 17 00:00:00 2001 From: Marcus Andersson Date: Wed, 25 Mar 2020 17:01:43 +0100 Subject: [PATCH] Fix: reverted back to `import * as module` instead of using namespaces (#23069) * Removed namespace declaration to prevent issues with external plugins. * fixed imports and tests. --- .../src/datetime/datemath.test.ts | 2 +- .../grafana-data/src/datetime/datemath.ts | 277 ++++++++------- packages/grafana-data/src/datetime/index.ts | 5 +- .../grafana-data/src/datetime/rangeutil.ts | 315 +++++++++--------- packages/grafana-data/src/types/appEvents.ts | 11 +- packages/grafana-data/src/types/index.ts | 8 +- .../grafana-data/src/types/panelEvents.ts | 45 ++- .../ValueMappingsEditor/MappingRow.tsx | 2 +- packages/grafana-ui/src/themes/index.ts | 4 +- packages/grafana-ui/src/themes/mixins.ts | 111 +++--- packages/grafana-ui/src/utils/dom.ts | 81 +++-- packages/grafana-ui/src/utils/index.ts | 4 +- 12 files changed, 427 insertions(+), 438 deletions(-) diff --git a/packages/grafana-data/src/datetime/datemath.test.ts b/packages/grafana-data/src/datetime/datemath.test.ts index 70bf399ea3c..3443eea2d17 100644 --- a/packages/grafana-data/src/datetime/datemath.test.ts +++ b/packages/grafana-data/src/datetime/datemath.test.ts @@ -1,7 +1,7 @@ import sinon, { SinonFakeTimers } from 'sinon'; import each from 'lodash/each'; -import { dateMath } from './datemath'; +import * as dateMath from './datemath'; import { dateTime, DurationUnit, DateTime } from './moment_wrapper'; describe('DateMath', () => { diff --git a/packages/grafana-data/src/datetime/datemath.ts b/packages/grafana-data/src/datetime/datemath.ts index af7d8cceb79..7881729016f 100644 --- a/packages/grafana-data/src/datetime/datemath.ts +++ b/packages/grafana-data/src/datetime/datemath.ts @@ -5,161 +5,158 @@ import { TimeZone } from '../types/index'; const units: DurationUnit[] = ['y', 'M', 'w', 'd', 'h', 'm', 's']; -// eslint-disable-next-line @typescript-eslint/no-namespace -export namespace dateMath { - export function isMathString(text: string | DateTime | Date): boolean { - if (!text) { - return false; - } - - if (typeof text === 'string' && (text.substring(0, 3) === 'now' || text.includes('||'))) { - return true; - } else { - return false; - } - } - - /** - * Parses different types input to a moment instance. There is a specific formatting language that can be used - * if text arg is string. See unit tests for examples. - * @param text - * @param roundUp See parseDateMath function. - * @param timezone Only string 'utc' is acceptable here, for anything else, local timezone is used. - */ - export function parse( - text?: string | DateTime | Date | null, - roundUp?: boolean, - timezone?: TimeZone - ): DateTime | undefined { - if (!text) { - return undefined; - } - - if (typeof text !== 'string') { - if (isDateTime(text)) { - return text; - } - if (isDate(text)) { - return dateTime(text); - } - // We got some non string which is not a moment nor Date. TS should be able to check for that but not always. - return undefined; - } else { - let time; - let mathString = ''; - let index; - let parseString; - - if (text.substring(0, 3) === 'now') { - time = dateTimeForTimeZone(timezone); - mathString = text.substring('now'.length); - } else { - index = text.indexOf('||'); - if (index === -1) { - parseString = text; - mathString = ''; // nothing else - } else { - parseString = text.substring(0, index); - mathString = text.substring(index + 2); - } - // We're going to just require ISO8601 timestamps, k? - time = dateTime(parseString, ISO_8601); - } - - if (!mathString.length) { - return time; - } - - return parseDateMath(mathString, time, roundUp); - } - } - - /** - * Checks if text is a valid date which in this context means that it is either a Moment instance or it can be parsed - * by parse function. See parse function to see what is considered acceptable. - * @param text - */ - export function isValid(text: string | DateTime): boolean { - const date = parse(text); - if (!date) { - return false; - } - - if (isDateTime(date)) { - return date.isValid(); - } - +export function isMathString(text: string | DateTime | Date): boolean { + if (!text) { return false; } - /** - * Parses math part of the time string and shifts supplied time according to that math. See unit tests for examples. - * @param mathString - * @param time - * @param roundUp If true it will round the time to endOf time unit, otherwise to startOf time unit. - */ - // TODO: Had to revert Andrejs `time: moment.Moment` to `time: any` - export function parseDateMath(mathString: string, time: any, roundUp?: boolean): DateTime | undefined { - const strippedMathString = mathString.replace(/\s/g, ''); - const dateTime = time; - let i = 0; - const len = strippedMathString.length; + if (typeof text === 'string' && (text.substring(0, 3) === 'now' || text.includes('||'))) { + return true; + } else { + return false; + } +} - while (i < len) { - const c = strippedMathString.charAt(i++); - let type; - let num; - let unit; +/** + * Parses different types input to a moment instance. There is a specific formatting language that can be used + * if text arg is string. See unit tests for examples. + * @param text + * @param roundUp See parseDateMath function. + * @param timezone Only string 'utc' is acceptable here, for anything else, local timezone is used. + */ +export function parse( + text?: string | DateTime | Date | null, + roundUp?: boolean, + timezone?: TimeZone +): DateTime | undefined { + if (!text) { + return undefined; + } - if (c === '/') { - type = 0; - } else if (c === '+') { - type = 1; - } else if (c === '-') { - type = 2; + if (typeof text !== 'string') { + if (isDateTime(text)) { + return text; + } + if (isDate(text)) { + return dateTime(text); + } + // We got some non string which is not a moment nor Date. TS should be able to check for that but not always. + return undefined; + } else { + let time; + let mathString = ''; + let index; + let parseString; + + if (text.substring(0, 3) === 'now') { + time = dateTimeForTimeZone(timezone); + mathString = text.substring('now'.length); + } else { + index = text.indexOf('||'); + if (index === -1) { + parseString = text; + mathString = ''; // nothing else } else { - return undefined; + parseString = text.substring(0, index); + mathString = text.substring(index + 2); } + // We're going to just require ISO8601 timestamps, k? + time = dateTime(parseString, ISO_8601); + } - if (isNaN(parseInt(strippedMathString.charAt(i), 10))) { - num = 1; - } else if (strippedMathString.length === 2) { - num = strippedMathString.charAt(i); - } else { - const numFrom = i; - while (!isNaN(parseInt(strippedMathString.charAt(i), 10))) { - i++; - if (i > 10) { - return undefined; - } - } - num = parseInt(strippedMathString.substring(numFrom, i), 10); - } + if (!mathString.length) { + return time; + } - if (type === 0) { - // rounding is only allowed on whole, single, units (eg M or 1M, not 0.5M or 2M) - if (num !== 1) { + return parseDateMath(mathString, time, roundUp); + } +} + +/** + * Checks if text is a valid date which in this context means that it is either a Moment instance or it can be parsed + * by parse function. See parse function to see what is considered acceptable. + * @param text + */ +export function isValid(text: string | DateTime): boolean { + const date = parse(text); + if (!date) { + return false; + } + + if (isDateTime(date)) { + return date.isValid(); + } + + return false; +} + +/** + * Parses math part of the time string and shifts supplied time according to that math. See unit tests for examples. + * @param mathString + * @param time + * @param roundUp If true it will round the time to endOf time unit, otherwise to startOf time unit. + */ +// TODO: Had to revert Andrejs `time: moment.Moment` to `time: any` +export function parseDateMath(mathString: string, time: any, roundUp?: boolean): DateTime | undefined { + const strippedMathString = mathString.replace(/\s/g, ''); + const dateTime = time; + let i = 0; + const len = strippedMathString.length; + + while (i < len) { + const c = strippedMathString.charAt(i++); + let type; + let num; + let unit; + + if (c === '/') { + type = 0; + } else if (c === '+') { + type = 1; + } else if (c === '-') { + type = 2; + } else { + return undefined; + } + + if (isNaN(parseInt(strippedMathString.charAt(i), 10))) { + num = 1; + } else if (strippedMathString.length === 2) { + num = strippedMathString.charAt(i); + } else { + const numFrom = i; + while (!isNaN(parseInt(strippedMathString.charAt(i), 10))) { + i++; + if (i > 10) { return undefined; } } - unit = strippedMathString.charAt(i++); + num = parseInt(strippedMathString.substring(numFrom, i), 10); + } - if (!includes(units, unit)) { + if (type === 0) { + // rounding is only allowed on whole, single, units (eg M or 1M, not 0.5M or 2M) + if (num !== 1) { return undefined; - } else { - if (type === 0) { - if (roundUp) { - dateTime.endOf(unit); - } else { - dateTime.startOf(unit); - } - } else if (type === 1) { - dateTime.add(num, unit); - } else if (type === 2) { - dateTime.subtract(num, unit); - } } } - return dateTime; + unit = strippedMathString.charAt(i++); + + if (!includes(units, unit)) { + return undefined; + } else { + if (type === 0) { + if (roundUp) { + dateTime.endOf(unit); + } else { + dateTime.startOf(unit); + } + } else if (type === 1) { + dateTime.add(num, unit); + } else if (type === 2) { + dateTime.subtract(num, unit); + } + } } + return dateTime; } diff --git a/packages/grafana-data/src/datetime/index.ts b/packages/grafana-data/src/datetime/index.ts index 444433da32a..51b32326f58 100644 --- a/packages/grafana-data/src/datetime/index.ts +++ b/packages/grafana-data/src/datetime/index.ts @@ -1,6 +1,7 @@ // Names are too general to export globally -export { dateMath } from './datemath'; -export { rangeUtil } from './rangeutil'; +import * as dateMath from './datemath'; +import * as rangeUtil from './rangeutil'; export * from './moment_wrapper'; export * from './timezones'; export * from './formats'; +export { dateMath, rangeUtil }; diff --git a/packages/grafana-data/src/datetime/rangeutil.ts b/packages/grafana-data/src/datetime/rangeutil.ts index 799893371ed..30a63350e22 100644 --- a/packages/grafana-data/src/datetime/rangeutil.ts +++ b/packages/grafana-data/src/datetime/rangeutil.ts @@ -3,183 +3,180 @@ import groupBy from 'lodash/groupBy'; import { RawTimeRange } from '../types/time'; -import { dateMath } from './datemath'; +import * as dateMath from './datemath'; import { isDateTime, DateTime } from './moment_wrapper'; -// eslint-disable-next-line @typescript-eslint/no-namespace -export namespace rangeUtil { - const spans: { [key: string]: { display: string; section?: number } } = { - s: { display: 'second' }, - m: { display: 'minute' }, - h: { display: 'hour' }, - d: { display: 'day' }, - w: { display: 'week' }, - M: { display: 'month' }, - y: { display: 'year' }, - }; +const spans: { [key: string]: { display: string; section?: number } } = { + s: { display: 'second' }, + m: { display: 'minute' }, + h: { display: 'hour' }, + d: { display: 'day' }, + w: { display: 'week' }, + M: { display: 'month' }, + y: { display: 'year' }, +}; - const rangeOptions = [ - { from: 'now/d', to: 'now/d', display: 'Today', section: 2 }, - { from: 'now/d', to: 'now', display: 'Today so far', section: 2 }, - { from: 'now/w', to: 'now/w', display: 'This week', section: 2 }, - { from: 'now/w', to: 'now', display: 'This week so far', section: 2 }, - { from: 'now/M', to: 'now/M', display: 'This month', section: 2 }, - { from: 'now/M', to: 'now', display: 'This month so far', section: 2 }, - { from: 'now/y', to: 'now/y', display: 'This year', section: 2 }, - { from: 'now/y', to: 'now', display: 'This year so far', section: 2 }, +const rangeOptions = [ + { from: 'now/d', to: 'now/d', display: 'Today', section: 2 }, + { from: 'now/d', to: 'now', display: 'Today so far', section: 2 }, + { from: 'now/w', to: 'now/w', display: 'This week', section: 2 }, + { from: 'now/w', to: 'now', display: 'This week so far', section: 2 }, + { from: 'now/M', to: 'now/M', display: 'This month', section: 2 }, + { from: 'now/M', to: 'now', display: 'This month so far', section: 2 }, + { from: 'now/y', to: 'now/y', display: 'This year', section: 2 }, + { from: 'now/y', to: 'now', display: 'This year so far', section: 2 }, - { from: 'now-1d/d', to: 'now-1d/d', display: 'Yesterday', section: 1 }, - { - from: 'now-2d/d', - to: 'now-2d/d', - display: 'Day before yesterday', - section: 1, - }, - { - from: 'now-7d/d', - to: 'now-7d/d', - display: 'This day last week', - section: 1, - }, - { from: 'now-1w/w', to: 'now-1w/w', display: 'Previous week', section: 1 }, - { from: 'now-1M/M', to: 'now-1M/M', display: 'Previous month', section: 1 }, - { from: 'now-1y/y', to: 'now-1y/y', display: 'Previous year', section: 1 }, + { from: 'now-1d/d', to: 'now-1d/d', display: 'Yesterday', section: 1 }, + { + from: 'now-2d/d', + to: 'now-2d/d', + display: 'Day before yesterday', + section: 1, + }, + { + from: 'now-7d/d', + to: 'now-7d/d', + display: 'This day last week', + section: 1, + }, + { from: 'now-1w/w', to: 'now-1w/w', display: 'Previous week', section: 1 }, + { from: 'now-1M/M', to: 'now-1M/M', display: 'Previous month', section: 1 }, + { from: 'now-1y/y', to: 'now-1y/y', display: 'Previous year', section: 1 }, - { from: 'now-5m', to: 'now', display: 'Last 5 minutes', section: 3 }, - { from: 'now-15m', to: 'now', display: 'Last 15 minutes', section: 3 }, - { from: 'now-30m', to: 'now', display: 'Last 30 minutes', section: 3 }, - { from: 'now-1h', to: 'now', display: 'Last 1 hour', section: 3 }, - { from: 'now-3h', to: 'now', display: 'Last 3 hours', section: 3 }, - { from: 'now-6h', to: 'now', display: 'Last 6 hours', section: 3 }, - { from: 'now-12h', to: 'now', display: 'Last 12 hours', section: 3 }, - { from: 'now-24h', to: 'now', display: 'Last 24 hours', section: 3 }, - { from: 'now-2d', to: 'now', display: 'Last 2 days', section: 0 }, - { from: 'now-7d', to: 'now', display: 'Last 7 days', section: 0 }, - { from: 'now-30d', to: 'now', display: 'Last 30 days', section: 0 }, - { from: 'now-90d', to: 'now', display: 'Last 90 days', section: 0 }, - { from: 'now-6M', to: 'now', display: 'Last 6 months', section: 0 }, - { from: 'now-1y', to: 'now', display: 'Last 1 year', section: 0 }, - { from: 'now-2y', to: 'now', display: 'Last 2 years', section: 0 }, - { from: 'now-5y', to: 'now', display: 'Last 5 years', section: 0 }, - ]; + { from: 'now-5m', to: 'now', display: 'Last 5 minutes', section: 3 }, + { from: 'now-15m', to: 'now', display: 'Last 15 minutes', section: 3 }, + { from: 'now-30m', to: 'now', display: 'Last 30 minutes', section: 3 }, + { from: 'now-1h', to: 'now', display: 'Last 1 hour', section: 3 }, + { from: 'now-3h', to: 'now', display: 'Last 3 hours', section: 3 }, + { from: 'now-6h', to: 'now', display: 'Last 6 hours', section: 3 }, + { from: 'now-12h', to: 'now', display: 'Last 12 hours', section: 3 }, + { from: 'now-24h', to: 'now', display: 'Last 24 hours', section: 3 }, + { from: 'now-2d', to: 'now', display: 'Last 2 days', section: 0 }, + { from: 'now-7d', to: 'now', display: 'Last 7 days', section: 0 }, + { from: 'now-30d', to: 'now', display: 'Last 30 days', section: 0 }, + { from: 'now-90d', to: 'now', display: 'Last 90 days', section: 0 }, + { from: 'now-6M', to: 'now', display: 'Last 6 months', section: 0 }, + { from: 'now-1y', to: 'now', display: 'Last 1 year', section: 0 }, + { from: 'now-2y', to: 'now', display: 'Last 2 years', section: 0 }, + { from: 'now-5y', to: 'now', display: 'Last 5 years', section: 0 }, +]; - const absoluteFormat = 'YYYY-MM-DD HH:mm:ss'; +const absoluteFormat = 'YYYY-MM-DD HH:mm:ss'; - const rangeIndex: any = {}; - each(rangeOptions, (frame: any) => { - rangeIndex[frame.from + ' to ' + frame.to] = frame; +const rangeIndex: any = {}; +each(rangeOptions, (frame: any) => { + rangeIndex[frame.from + ' to ' + frame.to] = frame; +}); + +export function getRelativeTimesList(timepickerSettings: any, currentDisplay: any) { + const groups = groupBy(rangeOptions, (option: any) => { + option.active = option.display === currentDisplay; + return option.section; }); - export function getRelativeTimesList(timepickerSettings: any, currentDisplay: any) { - const groups = groupBy(rangeOptions, (option: any) => { - option.active = option.display === currentDisplay; - return option.section; - }); + // _.each(timepickerSettings.time_options, (duration: string) => { + // let info = describeTextRange(duration); + // if (info.section) { + // groups[info.section].push(info); + // } + // }); - // _.each(timepickerSettings.time_options, (duration: string) => { - // let info = describeTextRange(duration); - // if (info.section) { - // groups[info.section].push(info); - // } - // }); + return groups; +} - return groups; +function formatDate(date: DateTime) { + return date.format(absoluteFormat); +} + +// handles expressions like +// 5m +// 5m to now/d +// now/d to now +// now/d +// if no to then to now is assumed +export function describeTextRange(expr: any) { + const isLast = expr.indexOf('+') !== 0; + if (expr.indexOf('now') === -1) { + expr = (isLast ? 'now-' : 'now') + expr; } - function formatDate(date: DateTime) { - return date.format(absoluteFormat); - } - - // handles expressions like - // 5m - // 5m to now/d - // now/d to now - // now/d - // if no to then to now is assumed - export function describeTextRange(expr: any) { - const isLast = expr.indexOf('+') !== 0; - if (expr.indexOf('now') === -1) { - expr = (isLast ? 'now-' : 'now') + expr; - } - - let opt = rangeIndex[expr + ' to now']; - if (opt) { - return opt; - } - - if (isLast) { - opt = { from: expr, to: 'now' }; - } else { - opt = { from: 'now', to: expr }; - } - - const parts = /^now([-+])(\d+)(\w)/.exec(expr); - if (parts) { - const unit = parts[3]; - const amount = parseInt(parts[2], 10); - const span = spans[unit]; - if (span) { - opt.display = isLast ? 'Last ' : 'Next '; - opt.display += amount + ' ' + span.display; - opt.section = span.section; - if (amount > 1) { - opt.display += 's'; - } - } - } else { - opt.display = opt.from + ' to ' + opt.to; - opt.invalid = true; - } - + let opt = rangeIndex[expr + ' to now']; + if (opt) { return opt; } - /** - * Use this function to get a properly formatted string representation of a {@link @grafana/data:RawTimeRange | range}. - * - * @example - * ``` - * // Prints "2": - * console.log(add(1,1)); - * ``` - * @category TimeUtils - * @param range - a time range (usually specified by the TimePicker) - * @alpha - */ - export function describeTimeRange(range: RawTimeRange): string { - const option = rangeIndex[range.from.toString() + ' to ' + range.to.toString()]; - if (option) { - return option.display; - } - - if (isDateTime(range.from) && isDateTime(range.to)) { - return formatDate(range.from) + ' to ' + formatDate(range.to); - } - - if (isDateTime(range.from)) { - const toMoment = dateMath.parse(range.to, true); - return toMoment ? formatDate(range.from) + ' to ' + toMoment.fromNow() : ''; - } - - if (isDateTime(range.to)) { - const from = dateMath.parse(range.from, false); - return from ? from.fromNow() + ' to ' + formatDate(range.to) : ''; - } - - if (range.to.toString() === 'now') { - const res = describeTextRange(range.from); - return res.display; - } - - return range.from.toString() + ' to ' + range.to.toString(); + if (isLast) { + opt = { from: expr, to: 'now' }; + } else { + opt = { from: 'now', to: expr }; } - export const isValidTimeSpan = (value: string) => { - if (value.indexOf('$') === 0 || value.indexOf('+$') === 0) { - return true; + const parts = /^now([-+])(\d+)(\w)/.exec(expr); + if (parts) { + const unit = parts[3]; + const amount = parseInt(parts[2], 10); + const span = spans[unit]; + if (span) { + opt.display = isLast ? 'Last ' : 'Next '; + opt.display += amount + ' ' + span.display; + opt.section = span.section; + if (amount > 1) { + opt.display += 's'; + } } + } else { + opt.display = opt.from + ' to ' + opt.to; + opt.invalid = true; + } - const info = describeTextRange(value); - return info.invalid !== true; - }; + return opt; } + +/** + * Use this function to get a properly formatted string representation of a {@link @grafana/data:RawTimeRange | range}. + * + * @example + * ``` + * // Prints "2": + * console.log(add(1,1)); + * ``` + * @category TimeUtils + * @param range - a time range (usually specified by the TimePicker) + * @alpha + */ +export function describeTimeRange(range: RawTimeRange): string { + const option = rangeIndex[range.from.toString() + ' to ' + range.to.toString()]; + if (option) { + return option.display; + } + + if (isDateTime(range.from) && isDateTime(range.to)) { + return formatDate(range.from) + ' to ' + formatDate(range.to); + } + + if (isDateTime(range.from)) { + const toMoment = dateMath.parse(range.to, true); + return toMoment ? formatDate(range.from) + ' to ' + toMoment.fromNow() : ''; + } + + if (isDateTime(range.to)) { + const from = dateMath.parse(range.from, false); + return from ? from.fromNow() + ' to ' + formatDate(range.to) : ''; + } + + if (range.to.toString() === 'now') { + const res = describeTextRange(range.from); + return res.display; + } + + return range.from.toString() + ' to ' + range.to.toString(); +} + +export const isValidTimeSpan = (value: string) => { + if (value.indexOf('$') === 0 || value.indexOf('+$') === 0) { + return true; + } + + const info = describeTextRange(value); + return info.invalid !== true; +}; diff --git a/packages/grafana-data/src/types/appEvents.ts b/packages/grafana-data/src/types/appEvents.ts index 567440ab16b..9f87c1ea204 100644 --- a/packages/grafana-data/src/types/appEvents.ts +++ b/packages/grafana-data/src/types/appEvents.ts @@ -5,11 +5,8 @@ export interface AppEvent { payload?: T; } -// eslint-disable-next-line @typescript-eslint/no-namespace -export namespace AppEvents { - export type AlertPayload = [string, string?]; +export type AlertPayload = [string, string?]; - export const alertSuccess = eventFactory('alert-success'); - export const alertWarning = eventFactory('alert-warning'); - export const alertError = eventFactory('alert-error'); -} +export const alertSuccess = eventFactory('alert-success'); +export const alertWarning = eventFactory('alert-warning'); +export const alertError = eventFactory('alert-error'); diff --git a/packages/grafana-data/src/types/index.ts b/packages/grafana-data/src/types/index.ts index 11fa9a68f9a..33d9ca94a34 100644 --- a/packages/grafana-data/src/types/index.ts +++ b/packages/grafana-data/src/types/index.ts @@ -24,5 +24,9 @@ export * from './theme'; export * from './orgs'; export * from './flot'; -export { AppEvent, AppEvents } from './appEvents'; -export { PanelEvents } from './panelEvents'; +import * as AppEvents from './appEvents'; +import { AppEvent } from './appEvents'; +export { AppEvent, AppEvents }; + +import * as PanelEvents from './panelEvents'; +export { PanelEvents }; diff --git a/packages/grafana-data/src/types/panelEvents.ts b/packages/grafana-data/src/types/panelEvents.ts index f4b5255981b..0a85512bff4 100644 --- a/packages/grafana-data/src/types/panelEvents.ts +++ b/packages/grafana-data/src/types/panelEvents.ts @@ -2,28 +2,25 @@ import { eventFactory } from './utils'; import { DataQueryError, DataQueryResponseData } from './datasource'; import { AngularPanelMenuItem } from './panel'; -// eslint-disable-next-line @typescript-eslint/no-namespace -export namespace PanelEvents { - /** Payloads */ - export interface PanelChangeViewPayload { - fullscreen?: boolean; - edit?: boolean; - panelId?: number; - toggle?: boolean; - } - - /** Events */ - export const refresh = eventFactory('refresh'); - export const componentDidMount = eventFactory('component-did-mount'); - export const dataError = eventFactory('data-error'); - export const dataReceived = eventFactory('data-received'); - export const dataSnapshotLoad = eventFactory('data-snapshot-load'); - export const editModeInitialized = eventFactory('init-edit-mode'); - export const initPanelActions = eventFactory('init-panel-actions'); - export const panelChangeView = eventFactory('panel-change-view'); - export const panelInitialized = eventFactory('panel-initialized'); - export const panelSizeChanged = eventFactory('panel-size-changed'); - export const panelTeardown = eventFactory('panel-teardown'); - export const render = eventFactory('render'); - export const viewModeChanged = eventFactory('view-mode-changed'); +/** Payloads */ +export interface PanelChangeViewPayload { + fullscreen?: boolean; + edit?: boolean; + panelId?: number; + toggle?: boolean; } + +/** Events */ +export const refresh = eventFactory('refresh'); +export const componentDidMount = eventFactory('component-did-mount'); +export const dataError = eventFactory('data-error'); +export const dataReceived = eventFactory('data-received'); +export const dataSnapshotLoad = eventFactory('data-snapshot-load'); +export const editModeInitialized = eventFactory('init-edit-mode'); +export const initPanelActions = eventFactory('init-panel-actions'); +export const panelChangeView = eventFactory('panel-change-view'); +export const panelInitialized = eventFactory('panel-initialized'); +export const panelSizeChanged = eventFactory('panel-size-changed'); +export const panelTeardown = eventFactory('panel-teardown'); +export const render = eventFactory('render'); +export const viewModeChanged = eventFactory('view-mode-changed'); diff --git a/packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx b/packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx index 47f3acb4f80..31f2906d5b5 100644 --- a/packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx +++ b/packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx @@ -2,7 +2,7 @@ import React, { ChangeEvent } from 'react'; import { HorizontalGroup } from '../Layout/Layout'; import Forms from '../Forms'; import { MappingType, RangeMap, ValueMap, ValueMapping } from '@grafana/data'; -import { styleMixins } from '../../themes/mixins'; +import * as styleMixins from '../../themes/mixins'; import { useTheme } from '../../themes'; import { FieldConfigItemHeaderTitle } from '../FieldConfigs/FieldConfigItemHeaderTitle'; diff --git a/packages/grafana-ui/src/themes/index.ts b/packages/grafana-ui/src/themes/index.ts index f88298f181e..d1e0ea0295f 100644 --- a/packages/grafana-ui/src/themes/index.ts +++ b/packages/grafana-ui/src/themes/index.ts @@ -3,4 +3,6 @@ import { getTheme, mockTheme } from './getTheme'; import { selectThemeVariant } from './selectThemeVariant'; export { stylesFactory } from './stylesFactory'; export { ThemeContext, withTheme, mockTheme, getTheme, selectThemeVariant, useTheme, mockThemeContext }; -export { styleMixins } from './mixins'; + +import * as styleMixins from './mixins'; +export { styleMixins }; diff --git a/packages/grafana-ui/src/themes/mixins.ts b/packages/grafana-ui/src/themes/mixins.ts index 80addcd321a..21283b3a207 100644 --- a/packages/grafana-ui/src/themes/mixins.ts +++ b/packages/grafana-ui/src/themes/mixins.ts @@ -3,11 +3,9 @@ import { selectThemeVariant } from './selectThemeVariant'; import { css } from 'emotion'; import { stylesFactory } from './stylesFactory'; -// eslint-disable-next-line @typescript-eslint/no-namespace -export namespace styleMixins { - export function cardChrome(theme: GrafanaTheme): string { - if (theme.isDark) { - return ` +export function cardChrome(theme: GrafanaTheme): string { + if (theme.isDark) { + return ` background: linear-gradient(135deg, ${theme.colors.dark8}, ${theme.colors.dark6}); &:hover { background: linear-gradient(135deg, ${theme.colors.dark9}, ${theme.colors.dark6}); @@ -15,9 +13,9 @@ export namespace styleMixins { box-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, 0.1), 1px 1px 0 0 rgba(0, 0, 0, 0.3); border-radius: ${theme.border.radius.md}; `; - } + } - return ` + return ` background: linear-gradient(135deg, ${theme.colors.gray6}, ${theme.colors.gray7}); &:hover { background: linear-gradient(135deg, ${theme.colors.gray7}, ${theme.colors.gray6}); @@ -25,11 +23,11 @@ export namespace styleMixins { box-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, 0.1), 1px 1px 0 0 rgba(0, 0, 0, 0.1); border-radius: ${theme.border.radius.md}; `; - } +} - export function listItem(theme: GrafanaTheme): string { - if (theme.isDark) { - return ` +export function listItem(theme: GrafanaTheme): string { + if (theme.isDark) { + return ` background: ${theme.colors.dark7}; &:hover { background: ${theme.colors.dark9}; @@ -37,9 +35,9 @@ export namespace styleMixins { box-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, 0.1), 1px 1px 0 0 rgba(0, 0, 0, 0.3); border-radius: ${theme.border.radius.md}; `; - } + } - return ` + return ` background: ${theme.colors.gray7}; &:hover { background: ${theme.colors.gray6}; @@ -47,55 +45,54 @@ export namespace styleMixins { box-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, 0.1), 1px 1px 0 0 rgba(0, 0, 0, 0.1); border-radius: ${theme.border.radius.md}; `; - } +} - export const panelEditorNestedListStyles = stylesFactory((theme: GrafanaTheme) => { - const borderColor = selectThemeVariant( - { - light: theme.colors.gray85, - dark: theme.colors.dark9, - }, - theme.type - ); - const shadow = selectThemeVariant( - { - light: theme.colors.gray85, - dark: theme.colors.black, - }, - theme.type - ); - const headerBg = selectThemeVariant( - { - light: theme.colors.white, - dark: theme.colors.dark1, - }, - theme.type - ); +export const panelEditorNestedListStyles = stylesFactory((theme: GrafanaTheme) => { + const borderColor = selectThemeVariant( + { + light: theme.colors.gray85, + dark: theme.colors.dark9, + }, + theme.type + ); + const shadow = selectThemeVariant( + { + light: theme.colors.gray85, + dark: theme.colors.black, + }, + theme.type + ); + const headerBg = selectThemeVariant( + { + light: theme.colors.white, + dark: theme.colors.dark1, + }, + theme.type + ); - return { - wrapper: css` - border: 1px dashed ${borderColor}; - margin-bottom: ${theme.spacing.md}; - transition: box-shadow 0.5s cubic-bezier(0.19, 1, 0.22, 1); - box-shadow: none; - &:hover { - box-shadow: 0 0 10px ${shadow}; - } - `, - headerWrapper: css` - background: ${headerBg}; - padding: ${theme.spacing.xs} 0; - `, + return { + wrapper: css` + border: 1px dashed ${borderColor}; + margin-bottom: ${theme.spacing.md}; + transition: box-shadow 0.5s cubic-bezier(0.19, 1, 0.22, 1); + box-shadow: none; + &:hover { + box-shadow: 0 0 10px ${shadow}; + } + `, + headerWrapper: css` + background: ${headerBg}; + padding: ${theme.spacing.xs} 0; + `, - content: css` + content: css` padding: ${theme.spacing.xs} ${theme.spacing.sm} ${theme.spacing.sm} ${theme.spacing.sm}; border-top: 1px dashed ${borderColor}; > *:last-child { margin-bottom: 0; `, - itemContent: css` - padding: ${theme.spacing.xs} ${theme.spacing.sm} ${theme.spacing.sm} ${theme.spacing.sm}; - `, - }; - }); -} + itemContent: css` + padding: ${theme.spacing.xs} ${theme.spacing.sm} ${theme.spacing.sm} ${theme.spacing.sm}; + `, + }; +}); diff --git a/packages/grafana-ui/src/utils/dom.ts b/packages/grafana-ui/src/utils/dom.ts index b8fa192dbf5..13f48764e73 100644 --- a/packages/grafana-ui/src/utils/dom.ts +++ b/packages/grafana-ui/src/utils/dom.ts @@ -1,44 +1,41 @@ -// eslint-disable-next-line @typescript-eslint/no-namespace -export namespace DOMUtil { - // Node.closest() polyfill - if ('Element' in window && !Element.prototype.closest) { - Element.prototype.closest = function(this: any, s: string) { - const matches = (this.document || this.ownerDocument).querySelectorAll(s); - let el = this; - let i; +// Node.closest() polyfill +if ('Element' in window && !Element.prototype.closest) { + Element.prototype.closest = function(this: any, s: string) { + const matches = (this.document || this.ownerDocument).querySelectorAll(s); + let el = this; + let i; + // eslint-disable-next-line + do { + i = matches.length; // eslint-disable-next-line - do { - i = matches.length; - // eslint-disable-next-line - while (--i >= 0 && matches.item(i) !== el) {} - el = el.parentElement; - } while (i < 0 && el); - return el; - }; - } - - export function getPreviousCousin(node: any, selector: string) { - let sibling = node.parentElement.previousSibling; - let el; - while (sibling) { - el = sibling.querySelector(selector); - if (el) { - return el; - } - sibling = sibling.previousSibling; - } - return undefined; - } - - export function getNextCharacter(global?: any) { - const selection = (global || window).getSelection(); - if (!selection || !selection.anchorNode) { - return null; - } - - const range = selection.getRangeAt(0); - const text = selection.anchorNode.textContent; - const offset = range.startOffset; - return text!.substr(offset, 1); - } + while (--i >= 0 && matches.item(i) !== el) {} + el = el.parentElement; + } while (i < 0 && el); + return el; + }; +} + +export function getPreviousCousin(node: any, selector: string) { + let sibling = node.parentElement.previousSibling; + let el; + while (sibling) { + el = sibling.querySelector(selector); + if (el) { + return el; + } + sibling = sibling.previousSibling; + } + return undefined; +} + +export function getNextCharacter(global?: any) { + const selection = (global || window).getSelection(); + if (!selection || !selection.anchorNode) { + return null; + } + + const range = selection.getRangeAt(0); + const text = selection.anchorNode.textContent; + const offset = range.startOffset; + return text!.substr(offset, 1); } diff --git a/packages/grafana-ui/src/utils/index.ts b/packages/grafana-ui/src/utils/index.ts index b3979e27e59..09cdd61d0b2 100644 --- a/packages/grafana-ui/src/utils/index.ts +++ b/packages/grafana-ui/src/utils/index.ts @@ -6,5 +6,5 @@ export * from './tags'; export * from './measureText'; export { default as ansicolor } from './ansicolor'; -// Export with a namespace -export { DOMUtil } from './dom'; // includes Element.closest polyfil +import * as DOMUtil from './dom'; // includes Element.closest polyfil +export { DOMUtil };