diff --git a/public/app/features/datasources/settings/HttpSettingsCtrl.ts b/public/app/angular/components/HttpSettingsCtrl.ts
similarity index 86%
rename from public/app/features/datasources/settings/HttpSettingsCtrl.ts
rename to public/app/angular/components/HttpSettingsCtrl.ts
index 190fe246f62..611dd12be7a 100644
--- a/public/app/features/datasources/settings/HttpSettingsCtrl.ts
+++ b/public/app/angular/components/HttpSettingsCtrl.ts
@@ -8,7 +8,7 @@ coreModule.directive('datasourceHttpSettings', () => {
noDirectAccess: '@',
showForwardOAuthIdentityOption: '@',
},
- templateUrl: 'public/app/features/datasources/partials/http_settings_next.html',
+ templateUrl: 'public/app/angular/partials/http_settings_next.html',
link: {
pre: ($scope: any) => {
// do not show access option if direct access is disabled
diff --git a/public/app/features/datasources/settings/TlsAuthSettingsCtrl.ts b/public/app/angular/components/TlsAuthSettingsCtrl.ts
similarity index 67%
rename from public/app/features/datasources/settings/TlsAuthSettingsCtrl.ts
rename to public/app/angular/components/TlsAuthSettingsCtrl.ts
index 3cf49145496..a6e85aa1baf 100644
--- a/public/app/features/datasources/settings/TlsAuthSettingsCtrl.ts
+++ b/public/app/angular/components/TlsAuthSettingsCtrl.ts
@@ -5,6 +5,6 @@ coreModule.directive('datasourceTlsAuthSettings', () => {
scope: {
current: '=',
},
- templateUrl: 'public/app/features/datasources/partials/tls_auth_settings.html',
+ templateUrl: 'public/app/angular/partials/tls_auth_settings.html',
};
});
diff --git a/public/app/features/plugins/plugin_component.ts b/public/app/angular/components/plugin_component.ts
similarity index 94%
rename from public/app/features/plugins/plugin_component.ts
rename to public/app/angular/components/plugin_component.ts
index 59d7e55cee0..be9b7a8e450 100644
--- a/public/app/features/plugins/plugin_component.ts
+++ b/public/app/angular/components/plugin_component.ts
@@ -5,21 +5,11 @@ import config from 'app/core/config';
import coreModule from 'app/angular/core_module';
import { DataSourceApi, PanelEvents } from '@grafana/data';
-import { importDataSourcePlugin, importAppPlugin } from './plugin_loader';
-import { importPanelPlugin } from './importPanelPlugin';
-import DatasourceSrv from './datasource_srv';
-import { GrafanaRootScope } from 'app/angular/GrafanaCtrl';
+import { importDataSourcePlugin, importAppPlugin } from '../../features/plugins/plugin_loader';
+import { importPanelPlugin } from '../../features/plugins/importPanelPlugin';
/** @ngInject */
-function pluginDirectiveLoader(
- $compile: any,
- datasourceSrv: DatasourceSrv,
- $rootScope: GrafanaRootScope,
- $http: any,
- $templateCache: any,
- $timeout: any,
- $location: ILocationService
-) {
+function pluginDirectiveLoader($compile: any, $http: any, $templateCache: any, $location: ILocationService) {
function getTemplate(component: { template: any; templateUrl: any }) {
if (component.template) {
return Promise.resolve(component.template);
diff --git a/public/app/angular/index.ts b/public/app/angular/index.ts
index 88e6d011480..2dcaee03cab 100644
--- a/public/app/angular/index.ts
+++ b/public/app/angular/index.ts
@@ -31,6 +31,9 @@ import './components/info_popover';
import './components/spectrum_picker';
import './components/code_editor/code_editor';
import './components/sql_part/sql_part_editor';
+import './components/HttpSettingsCtrl';
+import './components/TlsAuthSettingsCtrl';
+import './components/plugin_component';
import './GrafanaCtrl';
export { AngularApp } from './AngularApp';
diff --git a/public/app/features/datasources/partials/http_settings.html b/public/app/angular/partials/http_settings.html
similarity index 100%
rename from public/app/features/datasources/partials/http_settings.html
rename to public/app/angular/partials/http_settings.html
diff --git a/public/app/features/datasources/partials/http_settings_next.html b/public/app/angular/partials/http_settings_next.html
similarity index 100%
rename from public/app/features/datasources/partials/http_settings_next.html
rename to public/app/angular/partials/http_settings_next.html
diff --git a/public/app/features/datasources/partials/tls_auth_settings.html b/public/app/angular/partials/tls_auth_settings.html
similarity index 100%
rename from public/app/features/datasources/partials/tls_auth_settings.html
rename to public/app/angular/partials/tls_auth_settings.html
diff --git a/public/app/angular/registerComponents.ts b/public/app/angular/registerComponents.ts
index 6b3546e6288..0ef2f7c9a70 100644
--- a/public/app/angular/registerComponents.ts
+++ b/public/app/angular/registerComponents.ts
@@ -1,6 +1,7 @@
import { getBackendSrv, getDataSourceSrv } from '@grafana/runtime';
import { contextSrv } from 'app/core/core';
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
+import { validationSrv } from 'app/features/manage-dashboards/services/ValidationSrv';
import { getLinkSrv } from 'app/features/panel/panellinks/link_srv';
import coreModule from './core_module';
import { AnnotationsSrv } from './services/annotations_srv';
@@ -11,5 +12,6 @@ export function registerComponents() {
coreModule.factory('dashboardSrv', () => getDashboardSrv());
coreModule.factory('datasourceSrv', () => getDataSourceSrv());
coreModule.factory('linkSrv', () => getLinkSrv());
+ coreModule.factory('validationSrv', () => validationSrv);
coreModule.service('annotationsSrv', AnnotationsSrv);
}
diff --git a/public/app/features/all.ts b/public/app/features/all.ts
index ad19a4a89b0..ec007011106 100644
--- a/public/app/features/all.ts
+++ b/public/app/features/all.ts
@@ -1,6 +1,3 @@
import './plugins/all';
import './dashboard';
-import './manage-dashboards';
import './profile/all';
-import './datasources/settings/HttpSettingsCtrl';
-import './datasources/settings/TlsAuthSettingsCtrl';
diff --git a/public/app/features/dashboard/components/FolderPicker/FolderPickerCtrl.ts b/public/app/features/dashboard/components/FolderPicker/FolderPickerCtrl.ts
deleted file mode 100644
index 2604b54f4ec..00000000000
--- a/public/app/features/dashboard/components/FolderPicker/FolderPickerCtrl.ts
+++ /dev/null
@@ -1,205 +0,0 @@
-import { map, find } from 'lodash';
-import { IScope } from 'angular';
-import { AppEvents } from '@grafana/data';
-
-import coreModule from 'app/angular/core_module';
-import appEvents from 'app/core/app_events';
-import { backendSrv } from 'app/core/services/backend_srv';
-import { ValidationSrv } from 'app/features/manage-dashboards';
-import { ContextSrv } from 'app/core/services/context_srv';
-import { promiseToDigest } from '../../../../angular/promiseToDigest';
-import { createFolder } from 'app/features/manage-dashboards/state/actions';
-
-export class FolderPickerCtrl {
- declare initialTitle: string;
- initialFolderId?: number;
- labelClass?: string;
- onChange: any;
- onLoad: any;
- onCreateFolder: any;
- enterFolderCreation: any;
- exitFolderCreation: any;
- declare enableCreateNew: boolean;
- declare enableReset: boolean;
- rootName = 'General';
- folder: any;
- createNewFolder?: boolean;
- newFolderName?: string;
- newFolderNameTouched?: boolean;
- hasValidationError?: boolean;
- validationError: any;
- isEditor: boolean;
- dashboardId?: number;
-
- /** @ngInject */
- constructor(private validationSrv: ValidationSrv, private contextSrv: ContextSrv, private $scope: IScope) {
- this.isEditor = this.contextSrv.isEditor;
-
- if (this.labelClass === undefined) {
- this.labelClass = 'width-7';
- }
-
- this.loadInitialValue();
- }
-
- getOptions(query: string) {
- const params = {
- query,
- type: 'dash-folder',
- permission: 'Edit',
- };
-
- return promiseToDigest(this.$scope)(
- backendSrv.get('api/search', params).then((result: any) => {
- if (
- this.isEditor &&
- (query === '' ||
- query.toLowerCase() === 'g' ||
- query.toLowerCase() === 'ge' ||
- query.toLowerCase() === 'gen' ||
- query.toLowerCase() === 'gene' ||
- query.toLowerCase() === 'gener' ||
- query.toLowerCase() === 'genera' ||
- query.toLowerCase() === 'general')
- ) {
- result.unshift({ title: this.rootName, id: 0 });
- }
-
- if (this.isEditor && this.enableCreateNew && query === '') {
- result.unshift({ title: '-- New folder --', id: -1 });
- }
-
- if (this.enableReset && query === '' && this.initialTitle !== '') {
- result.unshift({ title: this.initialTitle, id: null });
- }
-
- return map(result, (item) => {
- return { text: item.title, value: item.id };
- });
- })
- );
- }
-
- onFolderChange(option: { value: number; text: string }) {
- if (!option) {
- option = { value: 0, text: this.rootName };
- } else if (option.value === -1) {
- this.createNewFolder = true;
- this.enterFolderCreation();
- return;
- }
- this.onChange({ $folder: { id: option.value, title: option.text } });
- }
-
- newFolderNameChanged() {
- this.newFolderNameTouched = true;
-
- this.validationSrv
- .validateNewFolderName(this.newFolderName)
- .then(() => {
- this.hasValidationError = false;
- })
- .catch((err: any) => {
- this.hasValidationError = true;
- this.validationError = err.message;
- });
- }
-
- createFolder(evt: any) {
- if (evt) {
- evt.stopPropagation();
- evt.preventDefault();
- }
-
- return promiseToDigest(this.$scope)(
- createFolder({ title: this.newFolderName }).then((result: { title: string; id: number }) => {
- appEvents.emit(AppEvents.alertSuccess, ['Folder created', 'OK']);
-
- this.closeCreateFolder();
- this.folder = { text: result.title, value: result.id };
- this.onFolderChange(this.folder);
- })
- );
- }
-
- cancelCreateFolder(evt: any) {
- if (evt) {
- evt.stopPropagation();
- evt.preventDefault();
- }
-
- this.closeCreateFolder();
- this.loadInitialValue();
- }
-
- private closeCreateFolder() {
- this.exitFolderCreation();
- this.createNewFolder = false;
- this.hasValidationError = false;
- this.validationError = null;
- this.newFolderName = '';
- this.newFolderNameTouched = false;
- }
-
- private loadInitialValue() {
- const resetFolder: { text: string; value: any } = { text: this.initialTitle, value: null };
- const rootFolder: { text: string; value: any } = { text: this.rootName, value: 0 };
-
- this.getOptions('').then((result: any[]) => {
- let folder: { text: string; value: any } | undefined;
-
- if (this.initialFolderId) {
- // @ts-ignore
- folder = find(result, { value: this.initialFolderId });
- } else if (this.enableReset && this.initialTitle && this.initialFolderId === null) {
- folder = resetFolder;
- }
-
- if (!folder) {
- if (this.isEditor) {
- folder = rootFolder;
- } else {
- // We shouldn't assign a random folder without the user actively choosing it on a persisted dashboard
- const isPersistedDashBoard = this.dashboardId ? true : false;
- if (isPersistedDashBoard) {
- folder = resetFolder;
- } else {
- folder = result.length > 0 ? result[0] : resetFolder;
- }
- }
- }
-
- this.folder = folder;
-
- // if this is not the same as our initial value notify parent
- if (this.folder.value !== this.initialFolderId) {
- this.onChange({ $folder: { id: this.folder.value, title: this.folder.text } });
- }
- });
- }
-}
-
-export function folderPicker() {
- return {
- restrict: 'E',
- templateUrl: 'public/app/features/dashboard/components/FolderPicker/template.html',
- controller: FolderPickerCtrl,
- bindToController: true,
- controllerAs: 'ctrl',
- scope: {
- initialTitle: '<',
- initialFolderId: '<',
- labelClass: '@',
- rootName: '@',
- onChange: '&',
- onCreateFolder: '&',
- enterFolderCreation: '&',
- exitFolderCreation: '&',
- enableCreateNew: '@',
- enableReset: '@',
- dashboardId: '',
- },
- };
-}
-
-coreModule.directive('folderPicker', folderPicker);
diff --git a/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardAsForm.test.tsx b/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardAsForm.test.tsx
index a267266f4b7..d58801a2c68 100644
--- a/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardAsForm.test.tsx
+++ b/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardAsForm.test.tsx
@@ -8,7 +8,9 @@ import * as api from 'app/features/manage-dashboards/state/actions';
jest.mock('app/features/plugins/datasource_srv', () => ({}));
jest.mock('app/features/expressions/ExpressionDatasource', () => ({}));
jest.mock('app/features/manage-dashboards/services/ValidationSrv', () => ({
- validateNewDashboardName: () => true,
+ validationSrv: {
+ validateNewDashboardName: () => true,
+ },
}));
jest.spyOn(api, 'searchFolders').mockResolvedValue([]);
diff --git a/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardAsForm.tsx b/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardAsForm.tsx
index bae756865cf..69d5e4ba025 100644
--- a/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardAsForm.tsx
+++ b/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardAsForm.tsx
@@ -3,7 +3,7 @@ import { Button, Input, Switch, Form, Field, InputControl, Modal } from '@grafan
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
import { FolderPicker } from 'app/core/components/Select/FolderPicker';
import { SaveDashboardFormProps } from '../types';
-import validationSrv from 'app/features/manage-dashboards/services/ValidationSrv';
+import { validationSrv } from 'app/features/manage-dashboards/services/ValidationSrv';
interface SaveDashboardAsFormDTO {
title: string;
diff --git a/public/app/features/folders/components/NewDashboardsFolder.tsx b/public/app/features/folders/components/NewDashboardsFolder.tsx
index 80ff2c2a10a..a3ef23bf5bc 100644
--- a/public/app/features/folders/components/NewDashboardsFolder.tsx
+++ b/public/app/features/folders/components/NewDashboardsFolder.tsx
@@ -5,7 +5,7 @@ import Page from 'app/core/components/Page/Page';
import { createNewFolder } from '../state/actions';
import { getNavModel } from 'app/core/selectors/navModel';
import { StoreState } from 'app/types';
-import validationSrv from '../../manage-dashboards/services/ValidationSrv';
+import { validationSrv } from '../../manage-dashboards/services/ValidationSrv';
const mapStateToProps = (state: StoreState) => ({
navModel: getNavModel(state.navIndex, 'manage-dashboards'),
diff --git a/public/app/features/manage-dashboards/components/UploadDashboard/index.ts b/public/app/features/manage-dashboards/components/UploadDashboard/index.ts
deleted file mode 100644
index 828b4f76982..00000000000
--- a/public/app/features/manage-dashboards/components/UploadDashboard/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { uploadDashboardDirective } from './uploadDashboardDirective';
diff --git a/public/app/features/manage-dashboards/components/UploadDashboard/uploadDashboardDirective.ts b/public/app/features/manage-dashboards/components/UploadDashboard/uploadDashboardDirective.ts
deleted file mode 100644
index 5cf013fb472..00000000000
--- a/public/app/features/manage-dashboards/components/UploadDashboard/uploadDashboardDirective.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-import coreModule from 'app/angular/core_module';
-import appEvents from 'app/core/app_events';
-import angular from 'angular';
-import { AppEvents } from '@grafana/data';
-
-const template = `
-
-
-`;
-
-/** @ngInject */
-export function uploadDashboardDirective() {
- return {
- restrict: 'E',
- template: template,
- scope: {
- onUpload: '&',
- btnText: '@?',
- },
- link: (scope: any, elem: JQuery) => {
- scope.btnText = angular.isDefined(scope.btnText) ? scope.btnText : 'Upload .json file';
-
- function file_selected(evt: any) {
- const files = evt.target.files; // FileList object
- const readerOnload = () => {
- return (e: any) => {
- let dash: any;
- try {
- dash = JSON.parse(e.target.result);
- } catch (err) {
- console.error(err);
- appEvents.emit(AppEvents.alertError, [
- 'Import failed',
- 'JSON -> JS serialization failed: ' + err.message,
- ]);
- return;
- }
-
- scope.$apply(() => {
- scope.onUpload({ dash });
- });
- };
- };
-
- let i = 0;
- let file = files[i];
-
- while (file) {
- const reader = new FileReader();
- reader.onload = readerOnload();
- reader.readAsText(file);
- i += 1;
- file = files[i];
- }
- }
-
- const wnd: any = window;
- // Check for the various File API support.
- if (wnd.File && wnd.FileReader && wnd.FileList && wnd.Blob) {
- // Something
- elem[0].addEventListener('change', file_selected, false);
- } else {
- appEvents.emit(AppEvents.alertError, ['Oops', 'The HTML5 file APIs are not fully supported in this browser']);
- }
- },
- };
-}
-
-coreModule.directive('dashUpload', uploadDashboardDirective);
diff --git a/public/app/features/manage-dashboards/index.ts b/public/app/features/manage-dashboards/index.ts
deleted file mode 100644
index a1790ce0340..00000000000
--- a/public/app/features/manage-dashboards/index.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-// Services
-export { ValidationSrv } from './services/ValidationSrv';
-
-// Components
-export * from './components/UploadDashboard';
diff --git a/public/app/features/manage-dashboards/services/ValidationSrv.ts b/public/app/features/manage-dashboards/services/ValidationSrv.ts
index f0d4cbb50f1..0e4c570d4f6 100644
--- a/public/app/features/manage-dashboards/services/ValidationSrv.ts
+++ b/public/app/features/manage-dashboards/services/ValidationSrv.ts
@@ -1,4 +1,3 @@
-import coreModule from 'app/angular/core_module';
import { backendSrv } from 'app/core/services/backend_srv';
const hitTypes = {
@@ -63,8 +62,4 @@ export class ValidationSrv {
}
}
-const validationSrv = new ValidationSrv();
-
-export default validationSrv;
-
-coreModule.service('validationSrv', ValidationSrv);
+export const validationSrv = new ValidationSrv();
diff --git a/public/app/features/manage-dashboards/utils/validation.ts b/public/app/features/manage-dashboards/utils/validation.ts
index d60b3fc95b4..f68d3c30e37 100644
--- a/public/app/features/manage-dashboards/utils/validation.ts
+++ b/public/app/features/manage-dashboards/utils/validation.ts
@@ -1,4 +1,4 @@
-import validationSrv from '../services/ValidationSrv';
+import { validationSrv } from '../services/ValidationSrv';
import { getBackendSrv } from '@grafana/runtime';
export const validateDashboardJson = (json: string) => {
diff --git a/public/app/features/plugins/all.ts b/public/app/features/plugins/all.ts
index 9776a8e0b93..fe460be0708 100644
--- a/public/app/features/plugins/all.ts
+++ b/public/app/features/plugins/all.ts
@@ -1,3 +1 @@
import './datasource_srv';
-import './plugin_component';
-import './variableQueryEditorLoader';
diff --git a/public/app/features/plugins/variableQueryEditorLoader.tsx b/public/app/features/plugins/variableQueryEditorLoader.tsx
deleted file mode 100644
index 98e187281d1..00000000000
--- a/public/app/features/plugins/variableQueryEditorLoader.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import coreModule from 'app/angular/core_module';
-import { importDataSourcePlugin } from './plugin_loader';
-import React from 'react';
-import ReactDOM from 'react-dom';
-import { LegacyVariableQueryEditor } from '../variables/editor/LegacyVariableQueryEditor';
-import { DataSourcePluginMeta } from '@grafana/data';
-import { TemplateSrv } from '@grafana/runtime';
-
-async function loadComponent(meta: DataSourcePluginMeta) {
- const dsPlugin = await importDataSourcePlugin(meta);
- if (dsPlugin.components.VariableQueryEditor) {
- return dsPlugin.components.VariableQueryEditor;
- } else {
- return LegacyVariableQueryEditor;
- }
-}
-
-/** @ngInject */
-function variableQueryEditorLoader(templateSrv: TemplateSrv) {
- return {
- restrict: 'E',
- link: async (scope: any, elem: JQuery) => {
- const Component = await loadComponent(scope.currentDatasource.meta);
- const props = {
- datasource: scope.currentDatasource,
- query: scope.current.query,
- onChange: scope.onQueryChange,
- templateSrv,
- };
- ReactDOM.render(, elem[0]);
- scope.$on('$destroy', () => {
- ReactDOM.unmountComponentAtNode(elem[0]);
- });
- },
- };
-}
-
-coreModule.directive('variableQueryEditorLoader', variableQueryEditorLoader);