Initial commit

This commit is contained in:
zhongjin
2020-06-15 10:58:47 +08:00
commit 4f1dfe7564
8590 changed files with 1516878 additions and 0 deletions
@@ -0,0 +1,87 @@
var CoreView = require('backbone/core-view');
var ModalExportDataView = require('builder/components/modals/export-data/modal-export-data-view');
var SyncInfoView = require('./dataset-content-sync-view');
var template = require('./dataset-content-options.tpl');
var checkAndBuildOpts = require('builder/helpers/required-opts');
var REQUIRED_OPTS = [
'analysisDefinitionNodeModel',
'configModel',
'modals',
'userModel'
];
module.exports = CoreView.extend({
className: 'Dataset-viewOptions u-flex u-justifySpace u-alignCenter',
events: {
'click .js-addRow': '_onAddRowClick',
'click .js-addColumn': '_onAddColumnClick',
'click .js-export': '_onExportClick'
},
initialize: function (opts) {
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
this._tableModel = this._analysisDefinitionNodeModel.getTableModel();
this._querySchemaModel = this._analysisDefinitionNodeModel.querySchemaModel;
this._queryGeometryModel = this._analysisDefinitionNodeModel.queryGeometryModel;
this._syncModel = this._tableModel.getSyncModel();
this._initBinds();
},
render: function () {
this.clearSubViews();
this.$el.html(
template({
isEditable: !this._analysisDefinitionNodeModel.isReadOnly(),
isCustomQueryApplied: this._analysisDefinitionNodeModel.isCustomQueryApplied()
})
);
this._initViews();
return this;
},
_initBinds: function () {
this.listenTo(this._querySchemaModel, 'change:query', this.render);
this.listenTo(this._syncModel, 'destroy', this.render);
},
_initViews: function () {
if (this._tableModel.isSync() && this._tableModel.isOwner(this._userModel)) {
var syncInfo = new SyncInfoView({
modals: this._modals,
syncModel: this._syncModel,
tableModel: this._tableModel,
querySchemaModel: this._querySchemaModel
});
this.$('.js-sync').html(syncInfo.render().el);
this.addView(syncInfo);
}
},
_onExportClick: function () {
this._modals.create(function (modalModel) {
return new ModalExportDataView({
modalModel: modalModel,
fromView: 'dataset',
configModel: this._configModel,
filename: this._tableModel.getUnquotedName(),
queryGeometryModel: this._queryGeometryModel,
querySchemaModel: this._querySchemaModel,
canHideColumns: false
});
}.bind(this));
},
_onAddRowClick: function () {
this.trigger('addRow', this);
},
_onAddColumnClick: function () {
this.trigger('addColumn', this);
}
});
@@ -0,0 +1,61 @@
<div class="js-sync"></div>
<div class="js-dataset">
<ul class="u-flex u-justifySpace">
<% if (isEditable) { %>
<li>
<button class="CDB-Text CDB-Size-small is-semibold u-actionTextColor u-upperCase js-addRow">
<div class="u-flex u-alignCenter">
<svg width="16px" height="18px" viewBox="0 0 16 6" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path d="M4,3 L4,0 L3,0 L3,3 L0,3 L0,4 L3,4 L3,7 L4,7 L4,4 L7,4 L7,3 L4,3 Z" id="path-1"></path>
<mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="7" height="7" fill="white">
<use xlink:href="#path-1"></use>
</mask>
</defs>
<g id="Add-Row" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<use id="Combined-Shape" stroke="#1181FB" mask="url(#mask-2)" stroke-width="2" xlink:href="#path-1"></use>
<path d="M16,0 L16,3 L9,3 L9,0 L16,0 Z M10.0020142,1 L10.000989,2.01795972 L14.9926249,2.00301586 L14.9962966,1.00580263 L10.0020142,1 Z" id="Combined-Shape" fill="#1181FB"></path>
<path d="M16,4 L16,7 L9,7 L9,4 L16,4 Z M10.0020142,5 L10.000989,6.01795972 L14.9926249,6.00301586 L14.9962966,5.00580263 L10.0020142,5 Z" id="Combined-Shape-Copy" fill="#1181FB"></path>
</g>
</svg>
<span class="u-lSpace">
<%- _t('dataset.options.add-row') %>
</span>
</div>
</button>
</li>
<li class="u-lSpace--xl">
<button class="CDB-Text CDB-Size-small is-semibold u-actionTextColor u-upperCase js-addColumn">
<div class="u-flex u-alignCenter">
<svg width="16px" height="18px" viewBox="0 4 16 6" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Add-Column" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(0.000000, 4.000000)">
<path d="M4,3 L4,0 L3,0 L3,3 L0,3 L0,4 L3,4 L3,7 L4,7 L4,4 L7,4 L7,3 L4,3 Z" id="Combined-Shape" fill="#1181FB"></path>
<path d="M9,0 L12,0 L12,7 L9,7 L9,0 Z M10,1 L11,1 L11,6 L10,6 L10,1 Z" id="Combined-Shape" fill="#1181FB"></path>
<path d="M13,0 L16,0 L16,7 L13,7 L13,0 Z M14,1 L15,1 L15,6 L14,6 L14,1 Z" id="Combined-Shape-Copy-2" fill="#1181FB"></path>
</g>
</svg>
<span class="u-lSpace">
<%- _t('dataset.options.add-column') %>
</span>
</div>
</button>
</li>
<% } %>
<li class="u-lSpace--xl">
<button class="CDB-Text CDB-Size-small is-semibold u-actionTextColor u-upperCase is-disabled js-export">
<div class="u-flex u-alignCenter">
<svg width="11px" height="18px" viewBox="-1 2 11 10" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Esport" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(0.000000, 3.000000)" stroke-linecap="square">
<path d="M4.5,0.5 L4.5,6.5" id="Line" stroke="#1181FB"></path>
<path d="M4.5,7.5 L8.5,3.5" id="Line" stroke="#1181FB"></path>
<path d="M4.5,7.5 L0.5,3.5" id="Line" stroke="#1181FB"></path>
</g>
</svg>
<span class="u-lSpace">
<%- _t('dataset.options.export') %>
</span>
</div>
</button>
</li>
</ul>
</div>
@@ -0,0 +1,165 @@
var CoreView = require('backbone/core-view');
var TipsyTooltipView = require('builder/components/tipsy-tooltip-view');
var CreationModalView = require('builder/components/modals/creation/modal-creation-view');
var SyncOptionsModalView = require('builder/components/modals/sync-options/sync-options-modal-view');
var SyncModel = require('builder/data/synchronization-model');
var template = require('./dataset-content-sync.tpl');
var moment = require('moment');
var checkAndBuildOpts = require('builder/helpers/required-opts');
var REQUIRED_OPTS = [
'syncModel',
'tableModel',
'querySchemaModel',
'modals'
];
module.exports = CoreView.extend({
tagName: 'div',
className: 'SyncInfo',
events: {
'click .js-options': '_onClickOptions',
'click .js-syncNow': '_onClickSyncNow'
},
initialize: function (opts) {
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
this._startSync = this._startSync.bind(this);
this._initBinds();
// Check sync now button
if (this._syncModel.isSyncing()) {
this._showSyncNowModal();
}
},
render: function () {
this.clearSubViews();
var runAt = this._syncModel.get('run_at');
var d = {
canSyncNow: this._syncModel.canSyncNow(),
fromExternalSource: this._syncModel.get('from_external_source'),
ranAt: moment(this._syncModel.get('ran_at') || new Date()).fromNow(),
runAt: moment(runAt).fromNow(),
state: this._syncModel.get('state'),
errorCode: this._syncModel.get('error_code'),
errorMessage: this._syncModel.get('error_message')
};
// Due to the time we need to polling, we have to display to the user
// that the sync will be in a moment
if (!runAt || (new Date(runAt) <= new Date())) {
d.runAt = _t('dataset.sync.in-a-moment');
}
this.$el
.html(template(d))
.removeClass()
.addClass(this.className + ' ' + 'is-' + d.state);
// Tipsy
var tooltip = new TipsyTooltipView({
el: this.$('.js-syncNowDisabled'),
title: function () {
return _t('dataset.sync.disabled', {
gap: SyncModel.SYNC_GAP / (1000 * 60)
});
}
});
this.addView(tooltip);
return this;
},
_initBinds: function () {
// Unbind in clean method
this._syncModel.bind('change', this.render, this);
},
_bindChangeSyncEvent: function () {
this._syncModel.bind('change:state', this._finishSync, this);
},
_unbindChangeSyncEvent: function () {
this._syncModel.unbind(null, null, this);
},
_onClickSyncNow: function (e) {
if (e) this.killEvent(e);
if (this._syncModel.canSyncNow()) {
this._showSyncNowModal();
}
},
_onClickOptions: function (e) {
var self = this;
var tableName = this._tableModel.getUnqualifiedName();
this._modals.create(function (modalModel) {
return new SyncOptionsModalView({
modalModel: modalModel,
syncModel: self._syncModel,
tableName: tableName
});
});
},
_startSync: function () {
this.render();
this._bindChangeSyncEvent();
this._syncModel.pollCheck();
},
_finishSync: function () {
if (!this._syncModel.isSyncing()) {
this._unbindChangeSyncEvent();
this._syncModel.destroyCheck();
// Reload table
this._querySchemaModel.set({
status: 'unfetched',
query: 'SELECT * FROM ' + this._tableModel.getUnquotedName()
});
this.render();
}
},
_showSyncNowModal: function (e) {
var self = this;
var tableName = this._tableModel.getUnqualifiedName();
this._modals.create(function (modalModel) {
return new CreationModalView({
modalModel: modalModel,
loadingTitle: _t('dataset.sync.loading', { tableName: tableName }),
errorTitle: _t('dataset.sync.error', { tableName: tableName }),
runAction: function (opts) {
self._syncModel.set({
state: 'syncing',
error_code: '',
error_message: ''
});
self._syncModel.bind('change:state', function () {
if (!self._syncModel.isSyncing()) {
modalModel.destroy();
}
}, self);
self._syncModel.syncNow(self._startSync);
}
});
});
},
clean: function () {
this._unbindChangeSyncEvent();
CoreView.prototype.clean.apply(this);
}
});
@@ -0,0 +1,30 @@
<p class="CDB-Text CDB-Size-small u-secondaryTextColor">
<span class="SyncInfo-state SyncInfo-state--small SyncInfo-state--<%- state %> u-rSpace--s"></span>
<span class="u-upperCase">
<% if (state === "success") { %>
<%- _t('dataset.sync.synced', { ranAt: ranAt }) %>.
<% } else if (state === "syncing") { %>
<%- _t('dataset.sync.syncing') %>...
<% } else if (state === "failure") { %>
<%- _t('dataset.sync.sync-failed') %>.
<% } %>
</span>
<% if (state === "success") { %>
<%- _t('dataset.sync.next', { runAt: runAt }) %>.
<% } else if (state === "syncing") { %>
<% /* There's no need to add extra text in this case. */ %>
<% } else if (errorCode || errorMessage) { %>
<%- _t('dataset.sync.error-code', { errorCode: errorCode }) %>: <%- errorMessage %>.
<% } %>
<% if (!fromExternalSource) { %>
<% if (state !== "syncing") { %>
<button class="<% if (canSyncNow) { %>u-actionTextColor js-syncNow<% } else { %>is-disabled js-syncNowDisabled<% } %>"><%- _t('dataset.sync.sync-now') %></button>.
<% } %>
<% } %>
<% if (state !== "syncing") { %>
<button class="js-options u-actionTextColor"><%- _t('dataset.sync.view-options') %></button>.
<% } %>
</p>
@@ -0,0 +1,60 @@
var CoreView = require('backbone/core-view');
var TableManager = require('builder/components/table/table-manager');
var DatasetContentOptionsView = require('./dataset-content-options-view');
var checkAndBuildOpts = require('builder/helpers/required-opts');
var REQUIRED_OPTS = [
'analysisDefinitionNodeModel',
'configModel',
'modals',
'userModel',
'visModel'
];
module.exports = CoreView.extend({
initialize: function (opts) {
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
this.listenTo(this._visModel, 'change:name', this._onChangeTableVisName);
},
render: function () {
this.clearSubViews();
this._initViews();
return this;
},
_initViews: function () {
this._tableView = TableManager.create({
relativePositionated: true,
analysisDefinitionNodeModel: this._analysisDefinitionNodeModel,
configModel: this._configModel,
modals: this._modals,
userModel: this._userModel
});
this.addView(this._tableView);
this.$el.append(this._tableView.render().el);
var datasetContentOptionsView = new DatasetContentOptionsView({
modals: this._modals,
userModel: this._userModel,
analysisDefinitionNodeModel: this._analysisDefinitionNodeModel,
configModel: this._configModel
});
datasetContentOptionsView.bind('addColumn', function () {
this._tableView.addColumn();
}, this);
datasetContentOptionsView.bind('addRow', function () {
this._tableView.addRow();
}, this);
this.addView(datasetContentOptionsView);
this.$el.prepend(datasetContentOptionsView.render().el);
},
_onChangeTableVisName: function () {
// Although all operations related with table rename are managed in the analysis-definition-source-node-model
// this columnsCollection doesn't belong to it and we need to take from it is generated.
this._tableView && this._tableView.getColumnsCollection().setTableName(this._visModel.get('name'));
}
});