mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) move client code to core
Summary: This moves all client code to core, and makes minimal fix-ups to get grist and grist-core to compile correctly. The client works in core, but I'm leaving clean-up around the build and bundles to follow-up. Test Plan: existing tests pass; server-dev bundle looks sane Reviewers: dsagal Reviewed By: dsagal Differential Revision: https://phab.getgrist.com/D2627
This commit is contained in:
136
app/client/models/BaseRowModel.js
Normal file
136
app/client/models/BaseRowModel.js
Normal file
@@ -0,0 +1,136 @@
|
||||
var _ = require('underscore');
|
||||
var ko = require('knockout');
|
||||
|
||||
var gutil = require('app/common/gutil');
|
||||
|
||||
var dispose = require('../lib/dispose');
|
||||
|
||||
var modelUtil = require('./modelUtil');
|
||||
|
||||
|
||||
/**
|
||||
* BaseRowModel is an observable model for a record (or row) of a data (DataRowModel) or meta
|
||||
* (MetaRowModel) table. It takes a reference to the containing TableModel, and a list of
|
||||
* column names, and creates an observable for each field.
|
||||
* TODO: We need to have a way to dispose RowModels, and have them dispose individual fields,
|
||||
* which should in turn unsubscribe from various events on disposal. And it all should be tested.
|
||||
*
|
||||
*/
|
||||
function BaseRowModel(tableModel, colNames) {
|
||||
this._table = tableModel;
|
||||
this._fields = colNames.slice(0);
|
||||
this._index = ko.observable(null); // The index in the observable to which it belongs.
|
||||
this._rowId = null;
|
||||
|
||||
// Create a field for everything in `_fields`.
|
||||
this._fields.forEach(function(colName) {
|
||||
this._createField(colName);
|
||||
}, this);
|
||||
}
|
||||
dispose.makeDisposable(BaseRowModel);
|
||||
|
||||
// This adds the dispatchAction() method to RowModel.
|
||||
_.extend(BaseRowModel.prototype, modelUtil.ActionDispatcher);
|
||||
|
||||
/**
|
||||
* Returns the rowId to which this RowModel is assigned. This is also normally available as the
|
||||
* `rowModel.id` observable.
|
||||
*/
|
||||
BaseRowModel.prototype.getRowId = function() {
|
||||
return this._rowId;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a field for colName. This is either a top level observable like this[colName]
|
||||
* for MetaRowModels or a property field like this[name][prop] for DataRowModels
|
||||
*/
|
||||
BaseRowModel.prototype._createField = function(colName) {
|
||||
this[colName] = modelUtil.addSaveInterface(ko.observable(), v => this._saveField(colName, v));
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper method to send a user action to save a field of the current row to the server.
|
||||
*/
|
||||
BaseRowModel.prototype._saveField = function(colName, value) {
|
||||
var colValues = {};
|
||||
colValues[colName] = value;
|
||||
return this.updateColValues(colValues);
|
||||
};
|
||||
|
||||
/**
|
||||
* Send an update to the server to update multiple columns for this row.
|
||||
* @param {Object} colValues: Maps colIds to values.
|
||||
* @returns {Promise} Resolved when the update succeeds.
|
||||
*/
|
||||
BaseRowModel.prototype.updateColValues = function(colValues) {
|
||||
return this._table.sendTableAction(["UpdateRecord", this._rowId, colValues]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Assigns the field of this RowModel named by `colName` to its corresponding value.
|
||||
*/
|
||||
BaseRowModel.prototype._assignColumn = function(colName) {
|
||||
throw new Error("Not Implemented");
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Implements the interface expected by modelUtil.ActionDispatcher. We only implement the
|
||||
* actions that affect individual rows. Note that BulkUpdateRecord needs to be translated to individual
|
||||
* UpdateRecords for RowModel to know what to do. Messages not here must be implemented by subclasses.
|
||||
* Some of these require helper methods defined in subclasses
|
||||
*/
|
||||
|
||||
BaseRowModel.prototype._process_RemoveColumn = function(action, tableId, colId) {
|
||||
if (!gutil.arrayRemove(this._fields, colId)) {
|
||||
console.error("RowModel #RemoveColumn %s %s: column not found", tableId, colId);
|
||||
}
|
||||
delete this[colId];
|
||||
};
|
||||
|
||||
BaseRowModel.prototype._process_ModifyColumn = function(action, tableId, colId, colInfo) {
|
||||
// No-op for us, because we don't care about any of the column properties.
|
||||
};
|
||||
|
||||
BaseRowModel.prototype._process_UpdateRecord = function(action, tableId, rowId, columnValues) {
|
||||
for (var colName in columnValues) {
|
||||
this._assignColumn(colName);
|
||||
}
|
||||
};
|
||||
|
||||
BaseRowModel.prototype._process_BulkUpdateRecord = function(action, tableId, rowId, columnValues) {
|
||||
// We get notified when a BulkUpdateRecord affects us, but since we just update all fields from
|
||||
// the underlying data, we don't need to find our row in the action.
|
||||
for (var colName in columnValues) {
|
||||
this._assignColumn(colName);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: if AddColumn messages aren't sent for properties, we will need to find a different
|
||||
// way to create and set the properties than here
|
||||
BaseRowModel.prototype._process_AddColumn = function(action, tableId, colId, colInfo) {
|
||||
this._fields.push(colId);
|
||||
this._createField(colId);
|
||||
this._assignColumn(colId);
|
||||
};
|
||||
|
||||
BaseRowModel.prototype._process_RenameColumn = function(action, tableId, oldColId, newColId) {
|
||||
// handle standard renames differently
|
||||
if (this._fields.indexOf(newColId) !== -1) {
|
||||
console.error("RowModel #RenameColumn %s %s %s: already exists", tableId, oldColId, newColId);
|
||||
}
|
||||
var index = this._fields.indexOf(oldColId);
|
||||
if (index === -1) {
|
||||
console.error("RowModel #RenameColumn %s %s %s: not found", tableId, oldColId, newColId);
|
||||
}
|
||||
this._fields[index] = newColId;
|
||||
|
||||
// Reuse the old observable, but replace its "save" family of functions.
|
||||
this[newColId] = this[oldColId];
|
||||
modelUtil.addSaveInterface(this[newColId], this._saveField.bind(this, newColId));
|
||||
this._assignColumn(newColId);
|
||||
delete this[oldColId];
|
||||
};
|
||||
|
||||
module.exports = BaseRowModel;
|
||||
Reference in New Issue
Block a user