gethue
Version:
Hue is an Open source SQL Query Editor for Databases/Warehouses
234 lines (209 loc) • 7.05 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 apiHelper from '../../../api/apiHelper';
import huePubSub from '../../../utils/huePubSub';
import { ASSIST_DB_HIGHLIGHT_EVENT } from '../../../ko/components/assist/events';
class DataCatalogContext {
constructor(options) {
const self = this;
self.popover = options.popover;
self.catalogEntry = ko.observable(options.catalogEntry);
self.parentIsView = ko.observable(false);
const checkIfParentIsView = catalogEntry => {
if (!catalogEntry) {
self.parentIsView(false);
return;
}
catalogEntry
.getParent()
.then(parentEntry => {
self.parentIsView(parentEntry.isView());
})
.catch(() => {
self.parentIsView(false);
});
};
checkIfParentIsView(self.catalogEntry());
self.catalogEntry.subscribe(checkIfParentIsView);
self.loading = ko.observable(false);
self.hasErrors = ko.observable(false);
self.activePromises = [];
self.errorText = ko.observable();
self.onSampleClick = options.popover.onSampleClick;
self.analysis = ko.observable();
self.comment = ko.observable();
self.commentExpanded = ko.observable(false);
self.viewSql = ko.observable();
self.viewSqlVisible = ko.observable(false);
self.openActionsEnabled = ko.pureComputed(() => {
return self.catalogEntry() && self.catalogEntry().path.length <= 2;
});
self.catalogEntry.subscribe(self.load.bind(self));
self.breadCrumbs = ko.pureComputed(() => {
const result = [];
const catalogEntry = self.catalogEntry();
if (catalogEntry) {
for (let i = 0; i < catalogEntry.path.length; i++) {
const path = catalogEntry.path.slice(0, i + 1);
result.push({
name: catalogEntry.path[i],
isActive: i === catalogEntry.path.length - 1,
path,
catalogEntry: self.catalogEntry,
makeActive: function () {
self
.catalogEntry()
.dataCatalog.getEntry({
namespace: self.catalogEntry().namespace,
compute: self.catalogEntry().compute,
connector: self.catalogEntry().connector,
path,
temporaryOnly: self.catalogEntry().isTemporary
})
.then(self.catalogEntry)
.catch(err => {
console.warn(err);
});
}
});
}
}
return result;
});
self.originalCatalogEntry = options.catalogEntry;
self.load();
}
setEntry(entry) {
this.catalogEntry(entry);
}
refresh() {
const self = this;
self.catalogEntry().clearCache({ cascade: true }).finally(self.load.bind(self));
}
load() {
const self = this;
self.loading(true);
self.hasErrors(false);
self.cancelActivePromises();
const viewSqlDeferred = $.Deferred().done(self.viewSql);
self.activePromises.push(viewSqlDeferred.promise());
self.activePromises.push(
self
.catalogEntry()
.getSourceMeta({ cancellable: true })
.catch(() => {
self.hasErrors(true);
})
);
// TODO: Use connector attributes in dataCatalogContext
if (
self.catalogEntry().getDialect() === 'impala' ||
self.catalogEntry().getDialect() === 'hive'
) {
self.activePromises.push(
self
.catalogEntry()
.getAnalysis({
silenceErrors: true,
cancellable: true
})
.then(analysis => {
const found =
analysis.properties &&
analysis.properties.some(property => {
if (property.col_name.toLowerCase() === 'view original text:') {
apiHelper
.formatSql({ statements: property.data_type })
.then(formatResponse => {
if (formatResponse.status === 0) {
viewSqlDeferred.resolve(formatResponse.formatted_statements);
} else {
viewSqlDeferred.resolve(property.data_type);
}
})
.catch(() => {
viewSqlDeferred.resolve(property.data_type);
});
return true;
}
});
if (!found) {
viewSqlDeferred.resolve();
}
self.analysis(analysis);
})
.catch(viewSqlDeferred.reject)
);
} else {
viewSqlDeferred.reject();
}
self.activePromises.push(
self.catalogEntry().getComment({ silenceErrors: true, cancellable: true }).then(self.comment)
);
$.when.apply($, self.activePromises).always(() => {
self.loading(false);
self.activePromises.length = 0;
});
}
cancelActivePromises() {
const self = this;
while (self.activePromises.length) {
const promise = self.activePromises.pop();
if (promise.cancel) {
promise.cancel();
}
}
}
dispose() {
const self = this;
self.cancelActivePromises();
}
showInAssist() {
const self = this;
huePubSub.publish(ASSIST_DB_HIGHLIGHT_EVENT, self.catalogEntry());
huePubSub.publish('global.search.close');
}
openInDashboard() {
const self = this;
huePubSub.publish(
'open.link',
'/hue/dashboard/browse/' +
self.catalogEntry().path.join('.') +
'?engine=' +
self.catalogEntry().getConnector().id
);
huePubSub.publish('context.popover.hide');
huePubSub.publish('global.search.close');
}
openInTableBrowser() {
const self = this;
huePubSub.publish(
'open.link',
'/metastore/table' +
(self.catalogEntry().isTableOrView() ? '/' : 's/') +
self.catalogEntry().path.join('/') +
'?connector_id=' +
self.catalogEntry().getConnector().id +
'&namespace=' +
self.catalogEntry().namespace.id
);
huePubSub.publish('context.popover.hide');
huePubSub.publish('global.search.close');
}
}
export default DataCatalogContext;