gethue
Version:
Hue is an Open source SQL Query Editor for Databases/Warehouses
263 lines (238 loc) • 8.85 kB
JavaScript
// Licensed to Cloudera, Inc. under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. Cloudera, Inc. licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import $ from 'jquery';
import * as ko from 'knockout';
import { getComputes, getNamespaces } from '../../../catalog/contextCatalog';
import { NAMESPACES_REFRESHED_TOPIC } from '../../../catalog/events';
import AssistDbNamespace from '../../../ko/components/assist/assistDbNamespace';
import huePubSub from '../../../utils/huePubSub';
import { getFromLocalStorage } from '../../../utils/storageUtils';
class AssistDbSource {
/**
* @param {Object} options
* @param {Object} options.i18n
* @param {string} options.type
* @param {Namespace} [options.initialNamespace] - Optional initial namespace to use
* @param {Compute} [options.initialCompute] - Optional initial compute to use
* @param {Connector} options.connector
* @param {string} options.name
* @param {boolean} options.nonSqlType - Optional, default false
* @param {Object} options.navigationSettings
* @constructor
*/
constructor(options) {
const self = this;
// TODO: Get rid of sourceType
self.sourceType = options.type;
self.connector = options.connector;
self.name = options.name;
self.i18n = options.i18n;
self.nonSqlType = options.nonSqlType;
self.navigationSettings = options.navigationSettings;
self.initialNamespace =
options.initialNamespace || getFromLocalStorage('contextSelector.lastSelectedNamespace');
self.initialCompute =
options.initialCompute || getFromLocalStorage('contextSelector.lastSelectedCompute');
self.selectedNamespace = ko.observable();
self.namespaces = ko.observableArray();
self.loadedDeferred = $.Deferred();
self.loading = ko.observable(false);
self.hasErrors = ko.observable(false);
self.filter = {
querySpec: ko.observable({}).extend({ rateLimit: 300 })
};
self.filteredNamespaces = ko.pureComputed(() => {
if (
!self.filter.querySpec() ||
typeof self.filter.querySpec().query === 'undefined' ||
!self.filter.querySpec().query
) {
return self.namespaces();
}
return self
.namespaces()
.filter(
namespace =>
namespace.name.toLowerCase().indexOf(self.filter.querySpec().query.toLowerCase()) !== -1
);
});
self.autocompleteFromNamespaces = (nonPartial, partial) => {
const result = [];
const partialLower = partial.toLowerCase();
self.namespaces().forEach(namespace => {
if (namespace.name.toLowerCase().indexOf(partialLower) === 0) {
result.push(nonPartial + partial + namespace.name.substring(partial.length));
}
});
return result;
};
const ensureDbSet = () => {
if (self.nonSqlType) {
if (!self.selectedNamespace().selectedDatabase()) {
self.selectedNamespace().selectedDatabase(self.selectedNamespace().databases()[0]);
self.selectedNamespace().selectedDatabaseChanged();
}
}
};
self.selectedNamespace.subscribe(namespace => {
if (namespace && !namespace.loaded() && !namespace.loading()) {
namespace.initDatabases(ensureDbSet);
} else {
ensureDbSet();
}
});
self.hasNamespaces = ko.pureComputed(() => self.namespaces().length > 0);
huePubSub.subscribe(NAMESPACES_REFRESHED_TOPIC, connectorId => {
if (self.connector.id !== connectorId) {
return;
}
self.loading(true);
getNamespaces({ connector: self.connector })
.then(context => {
const newNamespaces = [];
const existingNamespaceIndex = {};
self.namespaces().forEach(assistNamespace => {
existingNamespaceIndex[assistNamespace.namespace.id] = assistNamespace;
});
context.namespaces.forEach(newNamespace => {
if (existingNamespaceIndex[newNamespace.id]) {
existingNamespaceIndex[newNamespace.id].namespace = newNamespace;
existingNamespaceIndex[newNamespace.id].name = newNamespace.name;
existingNamespaceIndex[newNamespace.id].status(newNamespace.status);
newNamespaces.push(existingNamespaceIndex[newNamespace.id]);
} else {
newNamespaces.push(
new AssistDbNamespace({
sourceType: self.sourceType,
connector: self.connector,
namespace: newNamespace,
i18n: self.i18n,
nonSqlType: self.nonSqlType,
navigationSettings: self.navigationSettings
})
);
}
});
self.namespaces(newNamespaces);
})
.catch()
.finally(() => {
self.loading(false);
});
});
}
whenLoaded(callback) {
const self = this;
self.loadedDeferred.done(callback);
}
loadNamespaces(refresh) {
const self = this;
self.loading(true);
if (refresh) {
getComputes({ connector: self.connector, clearCache: true }).catch();
}
return getNamespaces({ connector: self.connector, clearCache: refresh })
.then(context => {
const assistNamespaces = [];
let activeNamespace;
let activeCompute;
context.namespaces.forEach(namespace => {
const assistNamespace = new AssistDbNamespace({
sourceType: self.sourceType,
namespace: namespace,
connector: self.connector,
i18n: self.i18n,
nonSqlType: self.nonSqlType,
navigationSettings: self.navigationSettings
});
if (self.initialNamespace && namespace.id === self.initialNamespace.id) {
activeNamespace = assistNamespace;
if (self.initialCompute) {
activeNamespace.namespace.computes.some(compute => {
if (compute.id === self.initialCompute.id) {
activeCompute = compute;
}
});
}
}
assistNamespaces.push(assistNamespace);
});
self.namespaces(assistNamespaces);
if (!refresh) {
if (activeNamespace) {
self.selectedNamespace(activeNamespace);
} else if (assistNamespaces.length) {
self.selectedNamespace(assistNamespaces[0]);
}
if (activeCompute) {
self.selectedNamespace().compute(activeCompute);
} else if (
self.selectedNamespace() &&
self.selectedNamespace().namespace &&
self.selectedNamespace().namespace.computes &&
self.selectedNamespace().namespace.computes.length
) {
self.selectedNamespace().compute(self.selectedNamespace().namespace.computes[0]);
}
}
})
.catch(() => {
self.hasErrors(true);
})
.finally(() => {
self.loadedDeferred.resolve();
self.loading(false);
});
}
highlightInside(catalogEntry) {
const self = this;
if (self.navigationSettings.rightAssist) {
return;
}
const whenLoaded = () => {
self.namespaces().some(namespace => {
if (namespace.namespace.id === catalogEntry.namespace.id) {
if (self.selectedNamespace() !== namespace) {
self.selectedNamespace(namespace);
}
if (self.selectedNamespace().hasEntries()) {
self.selectedNamespace().highlightInside(catalogEntry);
} else {
self.selectedNamespace().initDatabases(() => {
self.selectedNamespace().highlightInside(catalogEntry);
});
}
return true;
}
});
};
if (self.namespaces().length) {
whenLoaded();
} else if (self.loading()) {
const loadingSub = self.loading.subscribe(() => {
loadingSub.dispose();
whenLoaded();
});
} else {
self.loadNamespaces().then(whenLoaded);
}
}
triggerRefresh() {
const self = this;
self.loadNamespaces(true);
}
}
export default AssistDbSource;