Hide shcema browser when it's not relevant

This commit is contained in:
Arik Fraimovich
2017-12-07 16:31:34 +02:00
parent c1d7e0401f
commit 6bb05106cd
4 changed files with 125 additions and 67 deletions

View File

@@ -72,8 +72,10 @@ function queryEditor(QuerySnippet) {
$scope.$watch('schema', (newSchema, oldSchema) => {
if (newSchema !== oldSchema) {
const tokensCount =
newSchema.reduce((totalLength, table) => totalLength + table.columns.length, 0);
if (newSchema === undefined) {
return;
}
const tokensCount = newSchema.reduce((totalLength, table) => totalLength + table.columns.length, 0);
// If there are too many tokens we disable live autocomplete,
// as it makes typing slower.
if (tokensCount > 5000) {
@@ -92,7 +94,6 @@ function queryEditor(QuerySnippet) {
},
};
const schemaCompleter = {
getCompletions(state, session, pos, prefix, callback) {
if (prefix.length === 0 || !$scope.schema) {
@@ -112,19 +113,17 @@ function queryEditor(QuerySnippet) {
});
});
$scope.schema.keywords = map(keywords, (v, k) =>
({
name: k,
value: k,
score: 0,
meta: v,
}));
$scope.schema.keywords = map(keywords, (v, k) => ({
name: k,
value: k,
score: 0,
meta: v,
}));
}
callback(null, $scope.schema.keywords);
},
};
window.ace.acequire(['ace/ext/language_tools'], (langTools) => {
langTools.addCompleter(schemaCompleter);
});

View File

@@ -1,4 +1,4 @@
<div class="schema-container">
<div class="schema-container" ng-if="$ctrl.schema">
<div class="schema-control">
<input type="text" placeholder="Search schema..." class="form-control" ng-model="$ctrl.schemaFilter" ng-disabled="$ctrl.isEmpty()">
<button class="btn btn-default"

View File

@@ -1,10 +1,25 @@
import { pick, any, some, find, min, isObject } from 'underscore';
import { SCHEMA_NOT_SUPPORTED, SCHEMA_LOAD_ERROR } from '@/services/data-source';
import template from './query.html';
function QueryViewCtrl(
$scope, Events, $route, $routeParams, $location, $window, $q,
KeyboardShortcuts, Title, AlertDialog, Notifications, clientConfig, toastr, $uibModal,
currentUser, Query, DataSource,
$scope,
Events,
$route,
$routeParams,
$location,
$window,
$q,
KeyboardShortcuts,
Title,
AlertDialog,
Notifications,
clientConfig,
toastr,
$uibModal,
currentUser,
Query,
DataSource,
) {
function getQueryResult(maxAge) {
if (maxAge === undefined) {
@@ -31,8 +46,7 @@ function QueryViewCtrl(
// If we had an invalid value in localStorage (e.g. nothing, deleted source),
// then use the first data source
const isValidDataSourceId = !isNaN(dataSourceId) && some($scope.dataSources, ds =>
ds.id === dataSourceId);
const isValidDataSourceId = !isNaN(dataSourceId) && some($scope.dataSources, ds => ds.id === dataSourceId);
if (!isValidDataSourceId) {
dataSourceId = $scope.dataSources[0].id;
@@ -46,16 +60,16 @@ function QueryViewCtrl(
// TODO: is it possible this will be called before dataSource is set?
$scope.schema = [];
$scope.dataSource.getSchema(refresh).then((data) => {
data = data.data;
const hasPrevSchema = refresh ? ($scope.schema && ($scope.schema.length > 0)) : false;
const hasSchema = data && (data.length > 0);
if (hasSchema) {
$scope.schema = data;
data.forEach((table) => {
if (data.schema) {
$scope.schema = data.schema;
$scope.schema.forEach((table) => {
table.collapsed = true;
});
} else if (hasPrevSchema) {
} else if (data.error.code === SCHEMA_NOT_SUPPORTED) {
$scope.schema = undefined;
} else if (data.error.code === SCHEMA_LOAD_ERROR) {
toastr.error('Schema refresh failed. Please try again later.');
} else {
toastr.error('Schema refresh failed. Please try again later.');
}
});
@@ -65,8 +79,10 @@ function QueryViewCtrl(
function updateDataSources(dataSources) {
// Filter out data sources the user can't query (or used by current query):
$scope.dataSources = dataSources.filter(dataSource =>
!dataSource.view_only || dataSource.id === $scope.query.data_source_id);
function canUseDataSource(dataSource) {
return !dataSource.view_only || dataSource.id === $scope.query.data_source_id;
}
$scope.dataSources = dataSources.filter(canUseDataSource);
if ($scope.dataSources.length === 0) {
$scope.noDataSources = true;
@@ -123,7 +139,7 @@ function QueryViewCtrl(
}
$scope.queryExecuting = false;
$scope.isQueryOwner = (currentUser.id === $scope.query.user.id) || currentUser.hasPermission('admin');
$scope.isQueryOwner = currentUser.id === $scope.query.user.id || currentUser.hasPermission('admin');
$scope.canEdit = currentUser.canEdit($scope.query) || $scope.query.can_edit;
$scope.canViewSource = currentUser.hasPermission('view_source');
@@ -167,25 +183,47 @@ function QueryViewCtrl(
request.id = $scope.query.id;
request.version = $scope.query.version;
} else {
request = pick($scope.query, ['schedule', 'query', 'id', 'description', 'name', 'data_source_id', 'options', 'latest_query_data_id', 'version', 'is_draft']);
request = pick($scope.query, [
'schedule',
'query',
'id',
'description',
'name',
'data_source_id',
'options',
'latest_query_data_id',
'version',
'is_draft',
]);
}
const options = Object.assign({}, {
successMessage: 'Query saved',
errorMessage: 'Query could not be saved',
}, customOptions);
const options = Object.assign(
{},
{
successMessage: 'Query saved',
errorMessage: 'Query could not be saved',
},
customOptions,
);
return Query.save(request, (updatedQuery) => {
toastr.success(options.successMessage);
$scope.query.version = updatedQuery.version;
}, (error) => {
if (error.status === 409) {
toastr.error('It seems like the query has been modified by another user. ' +
'Please copy/backup your changes and reload this page.', { autoDismiss: false });
} else {
toastr.error(options.errorMessage);
}
}).$promise;
return Query.save(
request,
(updatedQuery) => {
toastr.success(options.successMessage);
$scope.query.version = updatedQuery.version;
},
(error) => {
if (error.status === 409) {
toastr.error(
'It seems like the query has been modified by another user. ' +
'Please copy/backup your changes and reload this page.',
{ autoDismiss: false },
);
} else {
toastr.error(options.errorMessage);
}
},
).$promise;
};
// toastr.success('It seems like the query has been modified by another user. ' +
@@ -220,16 +258,21 @@ function QueryViewCtrl(
$scope.archiveQuery = () => {
function archive() {
Query.delete({ id: $scope.query.id }, () => {
$scope.query.is_archived = true;
$scope.query.schedule = null;
}, () => {
toastr.error('Query could not be archived.');
});
Query.delete(
{ id: $scope.query.id },
() => {
$scope.query.is_archived = true;
$scope.query.schedule = null;
},
() => {
toastr.error('Query could not be archived.');
},
);
}
const title = 'Archive Query';
const message = 'Are you sure you want to archive this query?<br/> All alerts and dashboard widgets created with its visualizations will be deleted.';
const message =
'Are you sure you want to archive this query?<br/> All alerts and dashboard widgets created with its visualizations will be deleted.';
const confirm = { class: 'btn-warning', title: 'Archive' };
AlertDialog.open(title, message, confirm).then(archive);

View File

@@ -1,31 +1,47 @@
function DataSource($resource, $http) {
const actions = {
get: { method: 'GET', cache: false, isArray: false },
query: { method: 'GET', cache: false, isArray: true },
test: {
method: 'POST', cache: false, isArray: false, url: 'api/data_sources/:id/test',
},
// getSchema: {
// method: 'GET', cache: false, isArray: true, url: 'api/data_sources/:id/schema',
// },
};
export const SCHEMA_NOT_SUPPORTED = 1;
export const SCHEMA_LOAD_ERROR = 2;
const DataSourceResource = $resource('api/data_sources/:id', { id: '@id' }, actions);
DataSourceResource.prototype.getSchema = function getSchema(refresh = false) {
function DataSource($q, $resource, $http) {
function fetchSchema(dataSourceId, refresh = false) {
const params = {};
if (refresh) {
params.refresh = true;
}
return $http.get(`api/data_sources/${this.id}/schema`, { params });
return $http.get(`api/data_sources/${dataSourceId}/schema`, { params });
}
const actions = {
get: { method: 'GET', cache: false, isArray: false },
query: { method: 'GET', cache: false, isArray: true },
test: {
method: 'POST',
cache: false,
isArray: false,
url: 'api/data_sources/:id/test',
},
};
const DataSourceResource = $resource('api/data_sources/:id', { id: '@id' }, actions);
DataSourceResource.prototype.getSchema = function getSchema(refresh = false) {
if (this._schema === undefined || refresh) {
return fetchSchema(this.id, refresh).then((response) => {
const data = response.data;
this._schema = data;
return data;
});
}
return $q.resolve(this._schema);
};
return DataSourceResource;
}
export default function init(ngModule) {
ngModule.factory('DataSource', DataSource);
}