Commit aa227c5c by Torkel Ödegaard

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.

(cherry picked from commit f75387bd)
parent ba26ac34
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', () => {
......
......@@ -5,9 +5,7 @@ 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 {
export function isMathString(text: string | DateTime | Date): boolean {
if (!text) {
return false;
}
......@@ -17,16 +15,20 @@ export namespace dateMath {
} 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, roundUp?: boolean, timezone?: TimeZone): DateTime | undefined {
export function parse(
text?: string | DateTime | Date | null,
roundUp?: boolean,
timezone?: TimeZone
): DateTime | undefined {
if (!text) {
return undefined;
}
......@@ -68,14 +70,14 @@ export namespace dateMath {
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 {
export function isValid(text: string | DateTime): boolean {
const date = parse(text);
if (!date) {
return false;
......@@ -86,16 +88,16 @@ export namespace dateMath {
}
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 {
// 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;
......@@ -157,5 +159,4 @@ export namespace dateMath {
}
}
return dateTime;
}
}
// 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 };
......@@ -3,12 +3,10 @@ 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 } } = {
const spans: { [key: string]: { display: string; section?: number } } = {
s: { display: 'second' },
m: { display: 'minute' },
h: { display: 'hour' },
......@@ -16,9 +14,9 @@ export namespace rangeUtil {
w: { display: 'week' },
M: { display: 'month' },
y: { display: 'year' },
};
};
const rangeOptions = [
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 },
......@@ -61,16 +59,16 @@ export namespace rangeUtil {
{ 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) => {
const rangeIndex: any = {};
each(rangeOptions, (frame: any) => {
rangeIndex[frame.from + ' to ' + frame.to] = frame;
});
});
export function getRelativeTimesList(timepickerSettings: any, currentDisplay: any) {
export function getRelativeTimesList(timepickerSettings: any, currentDisplay: any) {
const groups = groupBy(rangeOptions, (option: any) => {
option.active = option.display === currentDisplay;
return option.section;
......@@ -84,19 +82,19 @@ export namespace rangeUtil {
// });
return groups;
}
}
function formatDate(date: DateTime) {
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 <expr> then to now is assumed
export function describeTextRange(expr: any) {
// handles expressions like
// 5m
// 5m to now/d
// now/d to now
// now/d
// if no to <expr> 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;
......@@ -132,9 +130,9 @@ export namespace rangeUtil {
}
return opt;
}
}
/**
/**
* Use this function to get a properly formatted string representation of a {@link @grafana/data:RawTimeRange | range}.
*
* @example
......@@ -146,7 +144,7 @@ export namespace rangeUtil {
* @param range - a time range (usually specified by the TimePicker)
* @alpha
*/
export function describeTimeRange(range: RawTimeRange): string {
export function describeTimeRange(range: RawTimeRange): string {
const option = rangeIndex[range.from.toString() + ' to ' + range.to.toString()];
if (option) {
return option.display;
......@@ -172,14 +170,13 @@ export namespace rangeUtil {
}
return range.from.toString() + ' to ' + range.to.toString();
}
}
export const isValidTimeSpan = (value: string) => {
export const isValidTimeSpan = (value: string) => {
if (value.indexOf('$') === 0 || value.indexOf('+$') === 0) {
return true;
}
const info = describeTextRange(value);
return info.invalid !== true;
};
}
};
......@@ -5,11 +5,8 @@ export interface AppEvent<T> {
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<AlertPayload>('alert-success');
export const alertWarning = eventFactory<AlertPayload>('alert-warning');
export const alertError = eventFactory<AlertPayload>('alert-error');
}
export const alertSuccess = eventFactory<AlertPayload>('alert-success');
export const alertWarning = eventFactory<AlertPayload>('alert-warning');
export const alertError = eventFactory<AlertPayload>('alert-error');
......@@ -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 };
......@@ -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 {
/** 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<DataQueryError>('data-error');
export const dataReceived = eventFactory<DataQueryResponseData[]>('data-received');
export const dataSnapshotLoad = eventFactory<DataQueryResponseData[]>('data-snapshot-load');
export const editModeInitialized = eventFactory('init-edit-mode');
export const initPanelActions = eventFactory<AngularPanelMenuItem[]>('init-panel-actions');
export const panelChangeView = eventFactory<PanelChangeViewPayload>('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<any>('render');
export const viewModeChanged = eventFactory('view-mode-changed');
}
/** Events */
export const refresh = eventFactory('refresh');
export const componentDidMount = eventFactory('component-did-mount');
export const dataError = eventFactory<DataQueryError>('data-error');
export const dataReceived = eventFactory<DataQueryResponseData[]>('data-received');
export const dataSnapshotLoad = eventFactory<DataQueryResponseData[]>('data-snapshot-load');
export const editModeInitialized = eventFactory('init-edit-mode');
export const initPanelActions = eventFactory<AngularPanelMenuItem[]>('init-panel-actions');
export const panelChangeView = eventFactory<PanelChangeViewPayload>('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<any>('render');
export const viewModeChanged = eventFactory('view-mode-changed');
......@@ -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 };
import { GrafanaTheme } from '@grafana/data';
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace styleMixins {
export function cardChrome(theme: GrafanaTheme): string {
export function cardChrome(theme: GrafanaTheme): string {
if (theme.isDark) {
return `
background: linear-gradient(135deg, ${theme.colors.dark8}, ${theme.colors.dark6});
......@@ -22,9 +20,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.1);
border-radius: ${theme.border.radius.md};
`;
}
}
export function listItem(theme: GrafanaTheme): string {
export function listItem(theme: GrafanaTheme): string {
if (theme.isDark) {
return `
background: ${theme.colors.dark7};
......@@ -44,5 +42,4 @@ 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};
`;
}
}
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace DOMUtil {
// Node.closest() polyfill
if ('Element' in window && !Element.prototype.closest) {
// 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;
......@@ -15,9 +13,9 @@ export namespace DOMUtil {
} while (i < 0 && el);
return el;
};
}
}
export function getPreviousCousin(node: any, selector: string) {
export function getPreviousCousin(node: any, selector: string) {
let sibling = node.parentElement.previousSibling;
let el;
while (sibling) {
......@@ -28,9 +26,9 @@ export namespace DOMUtil {
sibling = sibling.previousSibling;
}
return undefined;
}
}
export function getNextCharacter(global?: any) {
export function getNextCharacter(global?: any) {
const selection = (global || window).getSelection();
if (!selection || !selection.anchorNode) {
return null;
......@@ -40,5 +38,4 @@ export namespace DOMUtil {
const text = selection.anchorNode.textContent;
const offset = range.startOffset;
return text!.substr(offset, 1);
}
}
......@@ -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 };
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