mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Chore: Typescript no-implicit any fixes progress (#17018)
* Chore: Typescript no-implicit any fixes progress * Fixed tests * Updated snapshot
This commit is contained in:
parent
813e3ffc15
commit
f12d47ef52
@ -55,11 +55,11 @@ export interface CommonProps<T> {
|
||||
onCloseMenu?: () => void;
|
||||
}
|
||||
|
||||
export interface SelectProps<T> {
|
||||
export interface SelectProps<T> extends CommonProps<T> {
|
||||
options: Array<SelectOptionItem<T>>;
|
||||
}
|
||||
|
||||
interface AsyncProps<T> {
|
||||
interface AsyncProps<T> extends CommonProps<T> {
|
||||
defaultOptions: boolean;
|
||||
loadOptions: (query: string) => Promise<Array<SelectOptionItem<T>>>;
|
||||
loadingMessage?: () => string;
|
||||
@ -95,9 +95,8 @@ export const MenuList = (props: any) => {
|
||||
);
|
||||
};
|
||||
|
||||
export class Select<T> extends PureComponent<CommonProps<T> & SelectProps<T>> {
|
||||
static defaultProps = {
|
||||
width: null,
|
||||
export class Select<T> extends PureComponent<SelectProps<T>> {
|
||||
static defaultProps: Partial<SelectProps<any>> = {
|
||||
className: '',
|
||||
isDisabled: false,
|
||||
isSearchable: true,
|
||||
@ -108,7 +107,7 @@ export class Select<T> extends PureComponent<CommonProps<T> & SelectProps<T>> {
|
||||
isLoading: false,
|
||||
backspaceRemovesValue: true,
|
||||
maxMenuHeight: 300,
|
||||
menuIsOpen: false,
|
||||
isOpen: false,
|
||||
components: {
|
||||
Option: SelectOption,
|
||||
SingleValue,
|
||||
@ -201,9 +200,8 @@ export class Select<T> extends PureComponent<CommonProps<T> & SelectProps<T>> {
|
||||
}
|
||||
}
|
||||
|
||||
export class AsyncSelect<T> extends PureComponent<CommonProps<T> & AsyncProps<T>> {
|
||||
static defaultProps = {
|
||||
width: null,
|
||||
export class AsyncSelect<T> extends PureComponent<AsyncProps<T>> {
|
||||
static defaultProps: Partial<AsyncProps<any>> = {
|
||||
className: '',
|
||||
components: {},
|
||||
loadingMessage: () => 'Loading...',
|
||||
|
@ -7,11 +7,13 @@ export interface NavModelItem {
|
||||
id?: string;
|
||||
active?: boolean;
|
||||
hideFromTabs?: boolean;
|
||||
hideFromMenu?: boolean;
|
||||
divider?: boolean;
|
||||
children?: NavModelItem[];
|
||||
breadcrumbs?: NavModelBreadcrumb[];
|
||||
target?: string;
|
||||
parentItem?: NavModelItem;
|
||||
showOrgSwitcher?: boolean;
|
||||
}
|
||||
|
||||
export interface NavModel {
|
||||
|
@ -4,7 +4,6 @@ import { AnnotationQueryEditor as StackdriverAnnotationQueryEditor } from 'app/p
|
||||
import { PasswordStrength } from './components/PasswordStrength';
|
||||
import PageHeader from './components/PageHeader/PageHeader';
|
||||
import EmptyListCTA from './components/EmptyListCTA/EmptyListCTA';
|
||||
import { SearchResult } from './components/search/SearchResult';
|
||||
import { TagFilter } from './components/TagFilter/TagFilter';
|
||||
import { SideMenu } from './components/sidemenu/SideMenu';
|
||||
import { MetricSelect } from './components/Select/MetricSelect';
|
||||
@ -20,7 +19,6 @@ export function registerAngularDirectives() {
|
||||
react2AngularDirective('appNotificationsList', AppNotificationList, []);
|
||||
react2AngularDirective('pageHeader', PageHeader, ['model', 'noTabs']);
|
||||
react2AngularDirective('emptyListCta', EmptyListCTA, ['model']);
|
||||
react2AngularDirective('searchResult', SearchResult, []);
|
||||
react2AngularDirective('searchField', SearchField, [
|
||||
'query',
|
||||
'autoFocus',
|
||||
|
@ -4,11 +4,11 @@ import { AlertBox } from '../AlertBox/AlertBox';
|
||||
|
||||
interface Props {
|
||||
appNotification: AppNotification;
|
||||
onClearNotification: (id) => void;
|
||||
onClearNotification: (id: number) => void;
|
||||
}
|
||||
|
||||
export default class AppNotificationItem extends Component<Props> {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
shouldComponentUpdate(nextProps: Props) {
|
||||
return this.props.appNotification.id !== nextProps.appNotification.id;
|
||||
}
|
||||
|
||||
|
@ -20,12 +20,12 @@ export class AppNotificationList extends PureComponent<Props> {
|
||||
componentDidMount() {
|
||||
const { notifyApp } = this.props;
|
||||
|
||||
appEvents.on('alert-warning', options => notifyApp(createWarningNotification(options[0], options[1])));
|
||||
appEvents.on('alert-success', options => notifyApp(createSuccessNotification(options[0], options[1])));
|
||||
appEvents.on('alert-error', options => notifyApp(createErrorNotification(options[0], options[1])));
|
||||
appEvents.on('alert-warning', (options: string[]) => notifyApp(createWarningNotification(options[0], options[1])));
|
||||
appEvents.on('alert-success', (options: string[]) => notifyApp(createSuccessNotification(options[0], options[1])));
|
||||
appEvents.on('alert-error', (options: string[]) => notifyApp(createErrorNotification(options[0], options[1])));
|
||||
}
|
||||
|
||||
onClearAppNotification = id => {
|
||||
onClearAppNotification = (id: number) => {
|
||||
this.props.clearAppNotification(id);
|
||||
};
|
||||
|
||||
|
@ -14,10 +14,10 @@ export interface Props {
|
||||
export default class OrgActionBar extends PureComponent<Props> {
|
||||
render() {
|
||||
const { searchQuery, layoutMode, onSetLayoutMode, linkButton, setSearchQuery, target } = this.props;
|
||||
const linkProps = { href: linkButton.href, target: undefined };
|
||||
const linkProps = { href: linkButton.href };
|
||||
|
||||
if (target) {
|
||||
linkProps.target = target;
|
||||
(linkProps as any).target = target;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -1,9 +1,9 @@
|
||||
import React from 'react';
|
||||
import PageHeader from './PageHeader';
|
||||
import { shallow } from 'enzyme';
|
||||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
|
||||
describe('PageHeader', () => {
|
||||
let wrapper;
|
||||
let wrapper: ShallowWrapper<PageHeader>;
|
||||
|
||||
describe('when the nav tree has a node with a title', () => {
|
||||
beforeAll(() => {
|
||||
|
@ -22,7 +22,7 @@ class AddPermissions extends Component<Props, NewDashboardAclItem> {
|
||||
showPermissionLevels: true,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = this.getCleanState();
|
||||
}
|
||||
@ -36,7 +36,7 @@ class AddPermissions extends Component<Props, NewDashboardAclItem> {
|
||||
};
|
||||
}
|
||||
|
||||
onTypeChanged = evt => {
|
||||
onTypeChanged = (evt: any) => {
|
||||
const type = evt.target.value as AclTarget;
|
||||
|
||||
switch (type) {
|
||||
@ -65,7 +65,7 @@ class AddPermissions extends Component<Props, NewDashboardAclItem> {
|
||||
this.setState({ permission: permission.value });
|
||||
};
|
||||
|
||||
onSubmit = async evt => {
|
||||
onSubmit = async (evt: React.SyntheticEvent) => {
|
||||
evt.preventDefault();
|
||||
await this.props.onAddPermission(this.state);
|
||||
this.setState(this.getCleanState());
|
||||
|
@ -1,13 +1,13 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Select } from '@grafana/ui';
|
||||
import { Select, SelectOptionItem } from '@grafana/ui';
|
||||
import { dashboardPermissionLevels, DashboardAcl, PermissionLevel } from 'app/types/acl';
|
||||
import { FolderInfo } from 'app/types';
|
||||
|
||||
const setClassNameHelper = inherited => {
|
||||
const setClassNameHelper = (inherited: boolean) => {
|
||||
return inherited ? 'gf-form-disabled' : '';
|
||||
};
|
||||
|
||||
function ItemAvatar({ item }) {
|
||||
function ItemAvatar({ item }: { item: DashboardAcl }) {
|
||||
if (item.userAvatarUrl) {
|
||||
return <img className="filter-table__avatar" src={item.userAvatarUrl} />;
|
||||
}
|
||||
@ -21,7 +21,7 @@ function ItemAvatar({ item }) {
|
||||
return <i style={{ width: '25px', height: '25px' }} className="gicon gicon-viewer" />;
|
||||
}
|
||||
|
||||
function ItemDescription({ item }) {
|
||||
function ItemDescription({ item }: { item: DashboardAcl }) {
|
||||
if (item.userId) {
|
||||
return <span className="filter-table__weak-italic">(User)</span>;
|
||||
}
|
||||
@ -39,8 +39,8 @@ interface Props {
|
||||
}
|
||||
|
||||
export default class PermissionsListItem extends PureComponent<Props> {
|
||||
onPermissionChanged = option => {
|
||||
this.props.onPermissionChanged(this.props.item, option.value as PermissionLevel);
|
||||
onPermissionChanged = (option: SelectOptionItem<PermissionLevel>) => {
|
||||
this.props.onPermissionChanged(this.props.item, option.value);
|
||||
};
|
||||
|
||||
onRemoveItem = () => {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
// @ts-ignore
|
||||
import Remarkable from 'remarkable';
|
||||
import { getBackendSrv } from '../../services/backend_srv';
|
||||
|
||||
@ -37,7 +38,7 @@ export class PluginHelp extends PureComponent<Props, State> {
|
||||
|
||||
getBackendSrv()
|
||||
.get(`/api/plugins/${plugin.id}/markdown/${type}`)
|
||||
.then(response => {
|
||||
.then((response: string) => {
|
||||
const markdown = new Remarkable();
|
||||
const helpHtml = markdown.render(response);
|
||||
|
||||
|
@ -19,13 +19,13 @@ interface State {
|
||||
}
|
||||
|
||||
export class MetricSelect extends React.Component<Props, State> {
|
||||
static defaultProps = {
|
||||
static defaultProps: Partial<Props> = {
|
||||
variables: [],
|
||||
options: [],
|
||||
isSearchable: true,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = { options: [] };
|
||||
}
|
||||
@ -45,7 +45,7 @@ export class MetricSelect extends React.Component<Props, State> {
|
||||
return nextProps.value !== this.props.value || !_.isEqual(nextOptions, this.state.options);
|
||||
}
|
||||
|
||||
buildOptions({ variables = [], options }) {
|
||||
buildOptions({ variables = [], options }: Props) {
|
||||
return variables.length > 0 ? [this.getVariablesGroup(), ...options] : options;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
// @ts-ignore
|
||||
import renderer from 'react-test-renderer';
|
||||
import { TeamPicker } from './TeamPicker';
|
||||
|
||||
|
@ -23,7 +23,7 @@ export interface State {
|
||||
export class TeamPicker extends Component<Props, State> {
|
||||
debouncedSearch: any;
|
||||
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = { isLoading: false };
|
||||
this.search = this.search.bind(this);
|
||||
@ -42,8 +42,8 @@ export class TeamPicker extends Component<Props, State> {
|
||||
query = '';
|
||||
}
|
||||
|
||||
return backendSrv.get(`/api/teams/search?perpage=10&page=1&query=${query}`).then(result => {
|
||||
const teams = result.teams.map(team => {
|
||||
return backendSrv.get(`/api/teams/search?perpage=10&page=1&query=${query}`).then((result: any) => {
|
||||
const teams = result.teams.map((team: any) => {
|
||||
return {
|
||||
id: team.id,
|
||||
value: team.id,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
// @ts-ignore
|
||||
import renderer from 'react-test-renderer';
|
||||
import { UserPicker } from './UserPicker';
|
||||
|
||||
|
@ -24,7 +24,7 @@ export interface State {
|
||||
export class UserPicker extends Component<Props, State> {
|
||||
debouncedSearch: any;
|
||||
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = { isLoading: false };
|
||||
this.search = this.search.bind(this);
|
||||
@ -45,8 +45,8 @@ export class UserPicker extends Component<Props, State> {
|
||||
|
||||
return backendSrv
|
||||
.get(`/api/org/users?query=${query}&limit=10`)
|
||||
.then(result => {
|
||||
return result.map(user => ({
|
||||
.then((result: any) => {
|
||||
return result.map((user: any) => ({
|
||||
id: user.userId,
|
||||
value: user.userId,
|
||||
label: user.login === user.email ? user.login : `${user.login} - ${user.email}`,
|
||||
|
@ -27,7 +27,7 @@ const timezones = [
|
||||
export class SharedPreferences extends PureComponent<Props, State> {
|
||||
backendSrv: BackendSrv = getBackendSrv();
|
||||
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
@ -72,7 +72,7 @@ export class SharedPreferences extends PureComponent<Props, State> {
|
||||
});
|
||||
}
|
||||
|
||||
onSubmitForm = async event => {
|
||||
onSubmitForm = async (event: React.SyntheticEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
const { homeDashboardId, theme, timezone } = this.state;
|
||||
|
@ -55,7 +55,7 @@ const DEFAULT_SNIPPETS = true;
|
||||
|
||||
const editorTemplate = `<div></div>`;
|
||||
|
||||
function link(scope, elem, attrs) {
|
||||
function link(scope: any, elem: any, attrs: any) {
|
||||
// Options
|
||||
const langMode = attrs.mode || DEFAULT_MODE;
|
||||
const maxLines = attrs.maxLines || DEFAULT_MAX_LINES;
|
||||
@ -116,7 +116,7 @@ function link(scope, elem, attrs) {
|
||||
});
|
||||
|
||||
// Sync with outer scope - update editor content if model has been changed from outside of directive.
|
||||
scope.$watch('content', (newValue, oldValue) => {
|
||||
scope.$watch('content', (newValue: any, oldValue: any) => {
|
||||
const editorValue = codeEditor.getValue();
|
||||
if (newValue !== editorValue && newValue !== oldValue) {
|
||||
scope.$$postDigest(() => {
|
||||
@ -142,7 +142,7 @@ function link(scope, elem, attrs) {
|
||||
},
|
||||
});
|
||||
|
||||
function setLangMode(lang) {
|
||||
function setLangMode(lang: string) {
|
||||
ace.acequire('ace/ext/language_tools');
|
||||
codeEditor.setOptions({
|
||||
enableBasicAutocompletion: true,
|
||||
@ -170,7 +170,7 @@ function link(scope, elem, attrs) {
|
||||
codeEditor.setTheme(theme);
|
||||
}
|
||||
|
||||
function setEditorContent(value) {
|
||||
function setEditorContent(value: string) {
|
||||
codeEditor.setValue(value);
|
||||
codeEditor.clearSelection();
|
||||
}
|
||||
|
@ -13,9 +13,9 @@ export function spectrumPicker() {
|
||||
scope: true,
|
||||
replace: true,
|
||||
template: '<color-picker color="ngModel.$viewValue" onChange="onColorChange"></color-picker>',
|
||||
link: (scope, element, attrs, ngModel) => {
|
||||
link: (scope: any, element: any, attrs: any, ngModel: any) => {
|
||||
scope.ngModel = ngModel;
|
||||
scope.onColorChange = color => {
|
||||
scope.onColorChange = (color: string) => {
|
||||
ngModel.$setViewValue(color);
|
||||
};
|
||||
},
|
||||
|
@ -1,12 +0,0 @@
|
||||
<div class="page-nav">
|
||||
<div class="page-breadcrumbs">
|
||||
<a class="breadcrumb-item active" href="/">
|
||||
<i class="fa fa-home"></i>
|
||||
</a>
|
||||
<a class="breadcrumb-item" ng-href="{{::item.url}}" ng-repeat="item in ctrl.model.breadcrumbs">
|
||||
{{::item.text}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<dashboard-search></dashboard-search>
|
@ -1,54 +0,0 @@
|
||||
import coreModule from '../../core_module';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import { NavModel } from '@grafana/ui';
|
||||
|
||||
export class NavbarCtrl {
|
||||
model: NavModel;
|
||||
|
||||
/** @ngInject */
|
||||
constructor() {}
|
||||
|
||||
showSearch() {
|
||||
appEvents.emit('show-dash-search');
|
||||
}
|
||||
|
||||
navItemClicked(navItem, evt) {
|
||||
if (navItem.clickHandler) {
|
||||
navItem.clickHandler();
|
||||
evt.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function navbarDirective() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
templateUrl: 'public/app/core/components/navbar/navbar.html',
|
||||
controller: NavbarCtrl,
|
||||
bindToController: true,
|
||||
controllerAs: 'ctrl',
|
||||
scope: {
|
||||
model: '=',
|
||||
},
|
||||
link: (scope, elem) => {},
|
||||
};
|
||||
}
|
||||
|
||||
export function pageH1() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: `
|
||||
<h1 class="page-header__title">
|
||||
<i class="page-header__icon {{::model.header.icon}}" ng-if="::model.header.icon"></i>
|
||||
<img class="page-header__img" ng-src="{{::model.header.img}}" ng-if="::model.header.img"></i>
|
||||
{{model.header.text}}
|
||||
</h1>
|
||||
`,
|
||||
scope: {
|
||||
model: '=',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
coreModule.directive('pageH1', pageH1);
|
||||
coreModule.directive('navbar', navbarDirective);
|
@ -40,7 +40,7 @@ export class QueryPart {
|
||||
return this.def.renderer(this, innerExpr);
|
||||
}
|
||||
|
||||
hasMultipleParamsInString(strValue, index) {
|
||||
hasMultipleParamsInString(strValue: string, index: number) {
|
||||
if (strValue.indexOf(',') === -1) {
|
||||
return false;
|
||||
}
|
||||
@ -48,7 +48,7 @@ export class QueryPart {
|
||||
return this.def.params[index + 1] && this.def.params[index + 1].optional;
|
||||
}
|
||||
|
||||
updateParam(strValue, index) {
|
||||
updateParam(strValue: string, index: number) {
|
||||
// handle optional parameters
|
||||
// if string contains ',' and next param is optional, split and update both
|
||||
if (this.hasMultipleParamsInString(strValue, index)) {
|
||||
@ -81,7 +81,7 @@ export class QueryPart {
|
||||
}
|
||||
}
|
||||
|
||||
export function functionRenderer(part, innerExpr) {
|
||||
export function functionRenderer(part: any, innerExpr: string) {
|
||||
const str = part.def.type + '(';
|
||||
const parameters = _.map(part.params, (value, index) => {
|
||||
const paramType = part.def.params[index];
|
||||
@ -105,14 +105,14 @@ export function functionRenderer(part, innerExpr) {
|
||||
return str + parameters.join(', ') + ')';
|
||||
}
|
||||
|
||||
export function suffixRenderer(part, innerExpr) {
|
||||
export function suffixRenderer(part: QueryPartDef, innerExpr: string) {
|
||||
return innerExpr + ' ' + part.params[0];
|
||||
}
|
||||
|
||||
export function identityRenderer(part, innerExpr) {
|
||||
export function identityRenderer(part: QueryPartDef, innerExpr: string) {
|
||||
return part.params[0];
|
||||
}
|
||||
|
||||
export function quotedIdentityRenderer(part, innerExpr) {
|
||||
export function quotedIdentityRenderer(part: QueryPartDef, innerExpr: string) {
|
||||
return '"' + part.params[0] + '"';
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ const template = `
|
||||
`;
|
||||
|
||||
/** @ngInject */
|
||||
export function queryPartEditorDirective($compile, templateSrv) {
|
||||
export function queryPartEditorDirective(templateSrv: any) {
|
||||
const paramTemplate = '<input type="text" class="hide input-mini tight-form-func-param"></input>';
|
||||
|
||||
return {
|
||||
@ -25,7 +25,7 @@ export function queryPartEditorDirective($compile, templateSrv) {
|
||||
handleEvent: '&',
|
||||
debounce: '@',
|
||||
},
|
||||
link: function postLink($scope, elem) {
|
||||
link: function postLink($scope: any, elem: any) {
|
||||
const part = $scope.part;
|
||||
const partDef = part.def;
|
||||
const $paramsContainer = elem.find('.query-part-parameters');
|
||||
@ -33,7 +33,7 @@ export function queryPartEditorDirective($compile, templateSrv) {
|
||||
|
||||
$scope.partActions = [];
|
||||
|
||||
function clickFuncParam(this: any, paramIndex) {
|
||||
function clickFuncParam(this: any, paramIndex: number) {
|
||||
/*jshint validthis:true */
|
||||
const $link = $(this);
|
||||
const $input = $link.next();
|
||||
@ -53,7 +53,7 @@ export function queryPartEditorDirective($compile, templateSrv) {
|
||||
}
|
||||
}
|
||||
|
||||
function inputBlur(this: any, paramIndex) {
|
||||
function inputBlur(this: any, paramIndex: number) {
|
||||
/*jshint validthis:true */
|
||||
const $input = $(this);
|
||||
const $link = $input.prev();
|
||||
@ -72,7 +72,7 @@ export function queryPartEditorDirective($compile, templateSrv) {
|
||||
$link.show();
|
||||
}
|
||||
|
||||
function inputKeyPress(this: any, paramIndex, e) {
|
||||
function inputKeyPress(this: any, paramIndex: number, e: any) {
|
||||
/*jshint validthis:true */
|
||||
if (e.which === 13) {
|
||||
inputBlur.call(this, paramIndex);
|
||||
@ -84,12 +84,12 @@ export function queryPartEditorDirective($compile, templateSrv) {
|
||||
this.style.width = (3 + this.value.length) * 8 + 'px';
|
||||
}
|
||||
|
||||
function addTypeahead($input, param, paramIndex) {
|
||||
function addTypeahead($input: JQuery, param: any, paramIndex: number) {
|
||||
if (!param.options && !param.dynamicLookup) {
|
||||
return;
|
||||
}
|
||||
|
||||
const typeaheadSource = (query, callback) => {
|
||||
const typeaheadSource = (query: string, callback: any) => {
|
||||
if (param.options) {
|
||||
let options = param.options;
|
||||
if (param.type === 'int') {
|
||||
@ -101,7 +101,7 @@ export function queryPartEditorDirective($compile, templateSrv) {
|
||||
}
|
||||
|
||||
$scope.$apply(() => {
|
||||
$scope.handleEvent({ $event: { name: 'get-param-options' } }).then(result => {
|
||||
$scope.handleEvent({ $event: { name: 'get-param-options' } }).then((result: any) => {
|
||||
const dynamicOptions = _.map(result, op => {
|
||||
return _.escape(op.value);
|
||||
});
|
||||
@ -116,7 +116,7 @@ export function queryPartEditorDirective($compile, templateSrv) {
|
||||
source: typeaheadSource,
|
||||
minLength: 0,
|
||||
items: 1000,
|
||||
updater: value => {
|
||||
updater: (value: string) => {
|
||||
value = _.unescape(value);
|
||||
setTimeout(() => {
|
||||
inputBlur.call($input[0], paramIndex);
|
||||
@ -138,12 +138,12 @@ export function queryPartEditorDirective($compile, templateSrv) {
|
||||
}
|
||||
|
||||
$scope.showActionsMenu = () => {
|
||||
$scope.handleEvent({ $event: { name: 'get-part-actions' } }).then(res => {
|
||||
$scope.handleEvent({ $event: { name: 'get-part-actions' } }).then((res: any) => {
|
||||
$scope.partActions = res;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.triggerPartAction = action => {
|
||||
$scope.triggerPartAction = (action: string) => {
|
||||
$scope.handleEvent({ $event: { name: 'action', action: action } });
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import $ from 'jquery';
|
||||
// @ts-ignore
|
||||
import baron from 'baron';
|
||||
import coreModule from 'app/core/core_module';
|
||||
|
||||
@ -14,7 +15,7 @@ const scrollerClass = 'baron__scroller';
|
||||
export function geminiScrollbar() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: (scope, elem, attrs) => {
|
||||
link: (scope: any, elem: any, attrs: any) => {
|
||||
let scrollRoot = elem.parent();
|
||||
const scroller = elem;
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React, { useContext } from 'react';
|
||||
// @ts-ignore
|
||||
import tinycolor from 'tinycolor2';
|
||||
import { SearchQuery } from './search';
|
||||
import { css, cx } from 'emotion';
|
||||
|
@ -1,67 +0,0 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export class SearchResult extends React.Component<any, any> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
search: '',
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.state.search.sections.map(section => {
|
||||
return <SearchResultSection section={section} key={section.id} />;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export interface SectionProps {
|
||||
section: any;
|
||||
}
|
||||
|
||||
export class SearchResultSection extends React.Component<SectionProps, any> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
renderItem(item) {
|
||||
return (
|
||||
<a className="search-item" href={item.url} key={item.id}>
|
||||
<span className="search-item__icon">
|
||||
<i className="fa fa-th-large" />
|
||||
</span>
|
||||
<span className="search-item__body">
|
||||
<div className="search-item__body-title">{item.title}</div>
|
||||
</span>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
toggleSection = () => {
|
||||
this.props.section.toggle();
|
||||
};
|
||||
|
||||
render() {
|
||||
const collapseClassNames = classNames({
|
||||
fa: true,
|
||||
'fa-plus': !this.props.section.expanded,
|
||||
'fa-minus': this.props.section.expanded,
|
||||
'search-section__header__toggle': true,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="search-section" key={this.props.section.id}>
|
||||
<div className="search-section__header">
|
||||
<i className={classNames('search-section__header__icon', this.props.section.icon)} />
|
||||
<span className="search-section__header__text">{this.props.section.title}</span>
|
||||
<i className={collapseClassNames} onClick={this.toggleSection} />
|
||||
</div>
|
||||
{this.props.section.expanded && (
|
||||
<div className="search-section__items">{this.props.section.items.map(this.renderItem)}</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ import { contextSrv } from 'app/core/services/context_srv';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import { parse, SearchParserOptions, SearchParserResult } from 'search-query-parser';
|
||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||
|
||||
export interface SearchQuery {
|
||||
query: string;
|
||||
parsedQuery: SearchParserResult;
|
||||
@ -32,6 +33,11 @@ class SearchQueryParser {
|
||||
}
|
||||
}
|
||||
|
||||
interface SelectedIndicies {
|
||||
dashboardIndex?: number;
|
||||
folderIndex?: number;
|
||||
}
|
||||
|
||||
export class SearchCtrl {
|
||||
isOpen: boolean;
|
||||
query: SearchQuery;
|
||||
@ -49,7 +55,7 @@ export class SearchCtrl {
|
||||
queryParser: SearchQueryParser;
|
||||
|
||||
/** @ngInject */
|
||||
constructor($scope, private $location, private $timeout, private searchSrv: SearchSrv) {
|
||||
constructor($scope: any, private $location: any, private $timeout: any, private searchSrv: SearchSrv) {
|
||||
appEvents.on('show-dash-search', this.openSearch.bind(this), $scope);
|
||||
appEvents.on('hide-dash-search', this.closeSearch.bind(this), $scope);
|
||||
appEvents.on('search-query', debounce(this.search.bind(this), 500), $scope);
|
||||
@ -88,7 +94,7 @@ export class SearchCtrl {
|
||||
appEvents.emit('search-query');
|
||||
}
|
||||
|
||||
openSearch(evt, payload) {
|
||||
openSearch(evt: any, payload: any) {
|
||||
if (this.isOpen) {
|
||||
this.closeSearch();
|
||||
return;
|
||||
@ -166,7 +172,7 @@ export class SearchCtrl {
|
||||
}, 100);
|
||||
}
|
||||
|
||||
moveSelection(direction) {
|
||||
moveSelection(direction: number) {
|
||||
if (this.results.length === 0) {
|
||||
return;
|
||||
}
|
||||
@ -252,14 +258,14 @@ export class SearchCtrl {
|
||||
return query.query === '' && query.starred === false && query.tags.length === 0;
|
||||
}
|
||||
|
||||
filterByTag(tag) {
|
||||
filterByTag(tag: string) {
|
||||
if (_.indexOf(this.query.tags, tag) === -1) {
|
||||
this.query.tags.push(tag);
|
||||
this.search();
|
||||
}
|
||||
}
|
||||
|
||||
removeTag(tag, evt) {
|
||||
removeTag(tag: string, evt: any) {
|
||||
this.query.tags = _.without(this.query.tags, tag);
|
||||
this.search();
|
||||
this.giveSearchFocus = true;
|
||||
@ -298,14 +304,11 @@ export class SearchCtrl {
|
||||
this.moveSelection(0);
|
||||
}
|
||||
|
||||
private getFlattenedResultForNavigation(): Array<{
|
||||
folderIndex: number;
|
||||
dashboardIndex: number;
|
||||
}> {
|
||||
private getFlattenedResultForNavigation(): SelectedIndicies[] {
|
||||
let folderIndex = 0;
|
||||
|
||||
return _.flatMap(this.results, s => {
|
||||
let result = [];
|
||||
return _.flatMap(this.results, (s: any) => {
|
||||
let result: SelectedIndicies[] = [];
|
||||
|
||||
result.push({
|
||||
folderIndex: folderIndex,
|
||||
|
@ -10,15 +10,15 @@ export class SearchResultsCtrl {
|
||||
editable: boolean;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private $location) {}
|
||||
constructor(private $location: any) {}
|
||||
|
||||
toggleFolderExpand(section) {
|
||||
toggleFolderExpand(section: any) {
|
||||
if (section.toggle) {
|
||||
if (!section.expanded && this.onFolderExpanding) {
|
||||
this.onFolderExpanding();
|
||||
}
|
||||
|
||||
section.toggle(section).then(f => {
|
||||
section.toggle(section).then((f: any) => {
|
||||
if (this.editable && f.expanded) {
|
||||
if (f.items) {
|
||||
_.each(f.items, i => {
|
||||
@ -34,7 +34,7 @@ export class SearchResultsCtrl {
|
||||
}
|
||||
}
|
||||
|
||||
navigateToFolder(section, evt) {
|
||||
navigateToFolder(section: any, evt: any) {
|
||||
this.$location.path(section.url);
|
||||
|
||||
if (evt) {
|
||||
@ -43,7 +43,7 @@ export class SearchResultsCtrl {
|
||||
}
|
||||
}
|
||||
|
||||
toggleSelection(item, evt) {
|
||||
toggleSelection(item: any, evt: any) {
|
||||
item.checked = !item.checked;
|
||||
|
||||
if (item.items) {
|
||||
@ -62,14 +62,14 @@ export class SearchResultsCtrl {
|
||||
}
|
||||
}
|
||||
|
||||
onItemClick(item) {
|
||||
onItemClick(item: any) {
|
||||
//Check if one string can be found in the other
|
||||
if (this.$location.path().indexOf(item.url) > -1 || item.url.indexOf(this.$location.path()) > -1) {
|
||||
appEvents.emit('hide-dash-search');
|
||||
}
|
||||
}
|
||||
|
||||
selectTag(tag, evt) {
|
||||
selectTag(tag: any, evt: any) {
|
||||
if (this.onTagSelected) {
|
||||
this.onTagSelected({ $tag: tag });
|
||||
}
|
||||
|
@ -10,7 +10,9 @@ jest.mock('../../app_events', () => ({
|
||||
const setup = (propOverrides?: object) => {
|
||||
const props = Object.assign(
|
||||
{
|
||||
link: {},
|
||||
link: {
|
||||
text: 'Hello',
|
||||
},
|
||||
user: {
|
||||
id: 1,
|
||||
isGrafanaAdmin: false,
|
||||
@ -87,9 +89,9 @@ describe('Functions', () => {
|
||||
const wrapper = setup();
|
||||
const mockEvent = { preventDefault: jest.fn() };
|
||||
it('should emit show modal event if url matches shortcut', () => {
|
||||
const child = { url: '/shortcuts' };
|
||||
const child = { url: '/shortcuts', text: 'hello' };
|
||||
const instance = wrapper.instance() as BottomNavLinks;
|
||||
instance.itemClicked(mockEvent, child);
|
||||
instance.itemClicked(mockEvent as any, child);
|
||||
|
||||
expect(appEvents.emit).toHaveBeenCalledWith('show-modal', { templateHtml: '<help-modal></help-modal>' });
|
||||
});
|
||||
|
@ -1,14 +1,15 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import appEvents from '../../app_events';
|
||||
import { User } from '../../services/context_srv';
|
||||
import { NavModelItem } from '@grafana/ui';
|
||||
|
||||
export interface Props {
|
||||
link: any;
|
||||
link: NavModelItem;
|
||||
user: User;
|
||||
}
|
||||
|
||||
class BottomNavLinks extends PureComponent<Props> {
|
||||
itemClicked = (event, child) => {
|
||||
itemClicked = (event: React.SyntheticEvent, child: NavModelItem) => {
|
||||
if (child.url === '/shortcuts') {
|
||||
event.preventDefault();
|
||||
appEvents.emit('show-modal', {
|
||||
@ -57,7 +58,7 @@ class BottomNavLinks extends PureComponent<Props> {
|
||||
link.children.map((child, index) => {
|
||||
if (!child.hideFromMenu) {
|
||||
return (
|
||||
<li className={child.divider} key={`${child.text}-${index}`}>
|
||||
<li key={`${child.text}-${index}`}>
|
||||
<a href={child.url} target={child.target} onClick={event => this.itemClicked(event, child)}>
|
||||
{child.icon && <i className={child.icon} />}
|
||||
{child.text}
|
||||
|
@ -4,10 +4,11 @@ import SignIn from './SignIn';
|
||||
import BottomNavLinks from './BottomNavLinks';
|
||||
import { contextSrv } from 'app/core/services/context_srv';
|
||||
import config from '../../config';
|
||||
import { NavModelItem } from '@grafana/ui';
|
||||
|
||||
export default function BottomSection() {
|
||||
const navTree: any = _.cloneDeep(config.bootData.navTree);
|
||||
const bottomNav: any = _.filter(navTree, item => item.hideFromMenu);
|
||||
const navTree: NavModelItem[] = _.cloneDeep(config.bootData.navTree);
|
||||
const bottomNav: NavModelItem[] = _.filter(navTree, item => item.hideFromMenu);
|
||||
const isSignedIn = contextSrv.isSignedIn;
|
||||
const user = contextSrv.user;
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
import React, { FC } from 'react';
|
||||
import DropDownChild from './DropDownChild';
|
||||
import { NavModelItem } from '@grafana/ui';
|
||||
|
||||
interface Props {
|
||||
link: any;
|
||||
link: NavModelItem;
|
||||
}
|
||||
|
||||
const SideMenuDropDown: FC<Props> = props => {
|
||||
|
@ -67,7 +67,9 @@ exports[`Render should render component 1`] = `
|
||||
>
|
||||
<span
|
||||
className="sidemenu-item-text"
|
||||
/>
|
||||
>
|
||||
Hello
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -20,7 +20,6 @@ import { colors } from '@grafana/ui/';
|
||||
|
||||
import { searchDirective } from './components/search/search';
|
||||
import { infoPopover } from './components/info_popover';
|
||||
import { navbarDirective } from './components/navbar/navbar';
|
||||
import { arrayJoin } from './directives/array_join';
|
||||
import { liveSrv } from './live/live_srv';
|
||||
import { Emitter } from './utils/emitter';
|
||||
@ -56,7 +55,6 @@ export {
|
||||
registerAngularDirectives,
|
||||
arrayJoin,
|
||||
coreModule,
|
||||
navbarDirective,
|
||||
searchDirective,
|
||||
liveSrv,
|
||||
layoutSelector,
|
||||
|
@ -97,9 +97,9 @@ exports[`Render when feature toggle editorsCanAdmin is turned off should not ren
|
||||
isDisabled={false}
|
||||
isLoading={false}
|
||||
isMulti={false}
|
||||
isOpen={false}
|
||||
isSearchable={false}
|
||||
maxMenuHeight={300}
|
||||
menuIsOpen={false}
|
||||
onChange={[Function]}
|
||||
openMenuOnFocus={false}
|
||||
options={
|
||||
@ -123,7 +123,6 @@ exports[`Render when feature toggle editorsCanAdmin is turned off should not ren
|
||||
"value": 0,
|
||||
}
|
||||
}
|
||||
width={null}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
@ -183,9 +182,9 @@ exports[`Render when feature toggle editorsCanAdmin is turned on should render p
|
||||
isDisabled={false}
|
||||
isLoading={false}
|
||||
isMulti={false}
|
||||
isOpen={false}
|
||||
isSearchable={false}
|
||||
maxMenuHeight={300}
|
||||
menuIsOpen={false}
|
||||
onChange={[Function]}
|
||||
openMenuOnFocus={false}
|
||||
options={
|
||||
@ -209,7 +208,6 @@ exports[`Render when feature toggle editorsCanAdmin is turned on should render p
|
||||
"value": 0,
|
||||
}
|
||||
}
|
||||
width={null}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
|
@ -39,6 +39,8 @@ export interface DashboardAcl {
|
||||
name?: string;
|
||||
inherited?: boolean;
|
||||
sortRank?: number;
|
||||
userAvatarUrl?: string;
|
||||
teamAvatarUrl?: string;
|
||||
}
|
||||
|
||||
export interface DashboardPermissionInfo {
|
||||
|
Loading…
Reference in New Issue
Block a user