mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
206 lines
6.5 KiB
JavaScript
206 lines
6.5 KiB
JavaScript
|
// External dependencies
|
||
|
const _ = require('underscore');
|
||
|
const ko = require('knockout');
|
||
|
const BackboneEvents = require('backbone').Events;
|
||
|
|
||
|
// Grist client libs
|
||
|
const dispose = require('../lib/dispose');
|
||
|
const dom = require('../lib/dom');
|
||
|
const kd = require('../lib/koDom');
|
||
|
const kf = require('../lib/koForm');
|
||
|
const ModalDialog = require('./ModalDialog');
|
||
|
const gutil = require('app/common/gutil');
|
||
|
|
||
|
const BASE_URL = 'https://syvvdfor2a.execute-api.us-east-1.amazonaws.com/test';
|
||
|
|
||
|
/**
|
||
|
* EmbedForm - Handles logic and dom for the modal embedding instruction box.
|
||
|
*/
|
||
|
function EmbedForm(gristDoc) {
|
||
|
this._docComm = gristDoc.docComm;
|
||
|
this._login = gristDoc.app.login;
|
||
|
this._basketId = gristDoc.docInfo.basketId;
|
||
|
this._tableIds = gristDoc.docModel.allTableIds.peek().sort();
|
||
|
|
||
|
// Arrays of published and unpublished tables, initialized in this._refreshTables()
|
||
|
this._published = ko.observable([]);
|
||
|
this._unpublished = ko.observable([]);
|
||
|
|
||
|
// Notify strings which are displayed to the user when set
|
||
|
this._errorNotify = ko.observable();
|
||
|
this._updateNotify = ko.observable();
|
||
|
|
||
|
// The state of initialization, either 'connecting', 'failed', or 'done'.
|
||
|
this._initState = ko.observable('connecting');
|
||
|
|
||
|
this._embedDialog = this.autoDispose(ModalDialog.create({
|
||
|
title: 'Upload for External Embedding',
|
||
|
body: this._buildEmbedDom(),
|
||
|
width: '420px'
|
||
|
}));
|
||
|
this._embedDialog.show();
|
||
|
|
||
|
this.listenTo(this._embedDialog, 'close', () => this.dispose());
|
||
|
|
||
|
// Perform the initial fetch to see which tables are published.
|
||
|
this._initFetch();
|
||
|
}
|
||
|
_.extend(EmbedForm.prototype, BackboneEvents);
|
||
|
dispose.makeDisposable(EmbedForm);
|
||
|
|
||
|
/**
|
||
|
* Performs the initial fetch to see which tables are published.
|
||
|
* Times out after 4 seconds, giving the user the option to retry.
|
||
|
*/
|
||
|
EmbedForm.prototype._initFetch = function() {
|
||
|
this._initState('connecting');
|
||
|
return this._refreshTables()
|
||
|
.timeout(4000)
|
||
|
.then(() => {
|
||
|
this._initState('done');
|
||
|
})
|
||
|
.catch(err => {
|
||
|
console.error("EmbedForm._initFetch failed", err);
|
||
|
this._initState('failed');
|
||
|
});
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Calls on basket to see which tables are published, then updates the published
|
||
|
* and unpublished local observables.
|
||
|
*/
|
||
|
EmbedForm.prototype._refreshTables = function() {
|
||
|
// Fetch the tables from the basket
|
||
|
return this._login.getBasketTables(this._docComm)
|
||
|
.then(basketTableIds => {
|
||
|
let published = [];
|
||
|
let unpublished = [];
|
||
|
gutil.sortedScan(this._tableIds, basketTableIds.sort(), (local, cloud) => {
|
||
|
let item = {
|
||
|
tableId: local || cloud,
|
||
|
local: Boolean(local),
|
||
|
cloud: Boolean(cloud)
|
||
|
};
|
||
|
if (cloud) {
|
||
|
published.push(item);
|
||
|
} else {
|
||
|
unpublished.push(item);
|
||
|
}
|
||
|
});
|
||
|
this._published(published);
|
||
|
this._unpublished(unpublished);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Builds the part of the form showing the table names and their status, and
|
||
|
* the buttons to change their status.
|
||
|
*/
|
||
|
EmbedForm.prototype._buildTablesDom = function() {
|
||
|
return dom('div.embed-form-tables',
|
||
|
kd.scope(this._published, published => {
|
||
|
return published.length > 0 ? dom('div.embed-form-published',
|
||
|
dom('div.embed-form-desc', `Published to Basket (basketId: ${this._basketId()})`),
|
||
|
published.map(t => {
|
||
|
return kf.row(
|
||
|
16, dom('a.embed-form-table-id', { href: this._getUrl(t.tableId), target: "_blank" },
|
||
|
t.tableId),
|
||
|
8, t.local ? this._makeButton('Update', t.tableId, 'update') : 'Only in Basket',
|
||
|
1, dom('div'),
|
||
|
2, this._makeButton('x', t.tableId, 'delete')
|
||
|
);
|
||
|
})
|
||
|
) : null;
|
||
|
}),
|
||
|
dom('div.embed-form-unpublished',
|
||
|
kd.scope(this._unpublished, unpublished => {
|
||
|
return unpublished.map(t => {
|
||
|
return kf.row(
|
||
|
16, dom('span.embed-form-table-id', t.tableId),
|
||
|
8, this._makeButton('Publish', t.tableId, 'add'),
|
||
|
3, dom('div')
|
||
|
);
|
||
|
});
|
||
|
})
|
||
|
)
|
||
|
);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Builds the body of the table publishing modal form.
|
||
|
*/
|
||
|
EmbedForm.prototype._buildEmbedDom = function() {
|
||
|
// TODO: Include links to the npm page and to download basket-api.js.
|
||
|
return dom('div.embed-form',
|
||
|
kd.scope(this._initState, state => {
|
||
|
switch (state) {
|
||
|
case 'connecting':
|
||
|
return dom('div.embed-form-connect', 'Connecting...');
|
||
|
case 'failed':
|
||
|
return dom('div',
|
||
|
dom('div.embed-form-connect', 'Connection to Basket failed'),
|
||
|
kf.buttonGroup(
|
||
|
kf.button(() => {
|
||
|
this._initFetch();
|
||
|
}, 'Retry')
|
||
|
)
|
||
|
);
|
||
|
case 'done':
|
||
|
return dom('div',
|
||
|
dom('div.embed-form-desc', 'Manage tables published to the cloud via Grist Basket.'),
|
||
|
dom('div.embed-form-desc', 'Note that by default, published tables are public.'),
|
||
|
this._buildTablesDom(),
|
||
|
dom('div.embed-form-desc', 'Basket is used to provide easy access to cloud-synced data:'),
|
||
|
dom('div.embed-form-link',
|
||
|
dom('a', { href: 'https://github.com/gristlabs/basket-api', target: "_blank" },
|
||
|
'Basket API on GitHub')
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
}),
|
||
|
kd.maybe(this._updateNotify, update => {
|
||
|
return dom('div.login-success-notify',
|
||
|
dom('div.login-success-text', update)
|
||
|
);
|
||
|
}),
|
||
|
kd.maybe(this._errorNotify, err => {
|
||
|
return dom('div.login-error-notify',
|
||
|
dom('div.login-error-text', err)
|
||
|
);
|
||
|
})
|
||
|
);
|
||
|
};
|
||
|
|
||
|
// Helper to perform embedAction ('add' | 'update' | 'delete') on tableId.
|
||
|
EmbedForm.prototype._embedTable = function(tableId, embedAction) {
|
||
|
this._errorNotify('');
|
||
|
this._updateNotify('');
|
||
|
return this._docComm.embedTable(tableId, embedAction)
|
||
|
.then(() => {
|
||
|
return this._refreshTables();
|
||
|
})
|
||
|
.then(() => {
|
||
|
if (embedAction === 'update') {
|
||
|
this._updateNotify(`Updated table ${tableId}`);
|
||
|
}
|
||
|
})
|
||
|
.catch(err => {
|
||
|
this._errorNotify(err.message);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
// Helper to make a button with text, that when pressed performs embedAction
|
||
|
// ('add' | 'update' | 'delete') on tableId.
|
||
|
EmbedForm.prototype._makeButton = function(text, tableId, embedAction) {
|
||
|
return kf.buttonGroup(
|
||
|
kf.button(() => this._embedTable(tableId, embedAction), text)
|
||
|
);
|
||
|
};
|
||
|
|
||
|
// Returns the URL to see the hosted data for tableId.
|
||
|
EmbedForm.prototype._getUrl = function(tableId) {
|
||
|
return `${BASE_URL}/${this._basketId()}/tables/${tableId}`;
|
||
|
};
|
||
|
|
||
|
module.exports = EmbedForm;
|