mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) control the distribution of attachment metadata
Summary: for users who don't automatically have deep rights to the document, provide them with attachment metadata only for rows they have access to. This is a little tricky to do efficiently. We provide attachment metadata when an individual table is fetched, rather than on initial document load, so we don't block that load on a full document scan. We provide attachment metadata to a client when we see that we are shipping rows mentioning particular attachments, without making any effort to keep track of the metadata they already have. Test Plan: updated tests Reviewers: dsagal, jarek Reviewed By: dsagal, jarek Differential Revision: https://phab.getgrist.com/D3722
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
* TableData maintains a single table's data.
|
||||
*/
|
||||
import {ActionDispatcher} from 'app/common/ActionDispatcher';
|
||||
import {BulkColValues, CellValue, ColInfo, ColInfoWithId, ColValues, DocAction,
|
||||
import {
|
||||
BulkAddRecord, BulkColValues, CellValue, ColInfo, ColInfoWithId, ColValues, DocAction,
|
||||
isSchemaAction, ReplaceTableData, RowRecord, TableDataAction} from 'app/common/DocActions';
|
||||
import {getDefaultForType} from 'app/common/gristTypes';
|
||||
import {arrayRemove, arraySplice, getDistinctValues} from 'app/common/gutil';
|
||||
@@ -250,16 +251,40 @@ export class TableData extends ActionDispatcher implements SkippableRows {
|
||||
|
||||
/**
|
||||
* Return data in TableDataAction form ['TableData', tableId, [...rowIds], {...}]
|
||||
* Optionally takes a list of row ids to return data from. If a row id is
|
||||
* not actually present in the table, a row of nulls will be returned for it.
|
||||
*/
|
||||
public getTableDataAction(): TableDataAction {
|
||||
const rowIds = this.getRowIds();
|
||||
public getTableDataAction(desiredRowIds?: number[]): TableDataAction {
|
||||
const rowIds = desiredRowIds || this.getRowIds();
|
||||
let bulkColValues: {[colId: string]: CellValue[]};
|
||||
if (desiredRowIds) {
|
||||
const len = rowIds.length;
|
||||
bulkColValues = {};
|
||||
for (const colId of this.getColIds()) { bulkColValues[colId] = Array(len); }
|
||||
for (let i = 0; i < len; i++) {
|
||||
const index = this._rowMap.get(rowIds[i]);
|
||||
for (const {colId, values} of this._colArray) {
|
||||
const value = (index === undefined) ? null : values[index];
|
||||
bulkColValues[colId][i] = value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bulkColValues = fromPairs(
|
||||
this.getColIds()
|
||||
.filter(colId => colId !== 'id')
|
||||
.map(colId => [colId, this.getColValues(colId)! as CellValue[]]));
|
||||
}
|
||||
return ['TableData',
|
||||
this.tableId,
|
||||
rowIds as number[],
|
||||
fromPairs(
|
||||
this.getColIds()
|
||||
.filter(colId => colId !== 'id')
|
||||
.map(colId => [colId, this.getColValues(colId)! as CellValue[]]))];
|
||||
bulkColValues];
|
||||
}
|
||||
|
||||
public getBulkAddRecord(desiredRowIds?: number[]): BulkAddRecord {
|
||||
const tableData = this.getTableDataAction(desiredRowIds?.sort((a, b) => a - b));
|
||||
return [
|
||||
'BulkAddRecord', tableData[1], tableData[2], tableData[3],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -357,6 +382,13 @@ export class TableData extends ActionDispatcher implements SkippableRows {
|
||||
// ---- The following methods implement ActionDispatcher interface ----
|
||||
|
||||
protected onAddRecord(action: DocAction, tableId: string, rowId: number, colValues: ColValues): void {
|
||||
if (this._rowMap.get(rowId) !== undefined) {
|
||||
// If adding a record that already exists, act like an update.
|
||||
// We rely on this behavior for distributing attachment
|
||||
// metadata.
|
||||
this.onUpdateRecord(action, tableId, rowId, colValues);
|
||||
return;
|
||||
}
|
||||
const index: number = this._rowIdCol.length;
|
||||
this._rowMap.set(rowId, index);
|
||||
this._rowIdCol[index] = rowId;
|
||||
@@ -366,14 +398,28 @@ export class TableData extends ActionDispatcher implements SkippableRows {
|
||||
}
|
||||
|
||||
protected onBulkAddRecord(action: DocAction, tableId: string, rowIds: number[], colValues: BulkColValues): void {
|
||||
const index: number = this._rowIdCol.length;
|
||||
let destIndex: number = this._rowIdCol.length;
|
||||
for (let i = 0; i < rowIds.length; i++) {
|
||||
this._rowMap.set(rowIds[i], index + i);
|
||||
this._rowIdCol[index + i] = rowIds[i];
|
||||
}
|
||||
for (const {colId, defl, values} of this._colArray) {
|
||||
for (let i = 0; i < rowIds.length; i++) {
|
||||
values[index + i] = colValues.hasOwnProperty(colId) ? colValues[colId][i] : defl;
|
||||
const srcIndex = this._rowMap.get(rowIds[i]);
|
||||
if (srcIndex !== undefined) {
|
||||
// If adding a record that already exists, act like an update.
|
||||
// We rely on this behavior for distributing attachment
|
||||
// metadata.
|
||||
for (const colId in colValues) {
|
||||
if (colValues.hasOwnProperty(colId)) {
|
||||
const colData = this._columns.get(colId);
|
||||
if (colData) {
|
||||
colData.values[srcIndex] = colValues[colId][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this._rowMap.set(rowIds[i], destIndex);
|
||||
this._rowIdCol[destIndex] = rowIds[i];
|
||||
for (const {colId, defl, values} of this._colArray) {
|
||||
values[destIndex] = colValues.hasOwnProperty(colId) ? colValues[colId][i] : defl;
|
||||
}
|
||||
destIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user