mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Comments
Summary: First iteration for comments system for Grist. - Comments are stored in a generic metatable `_grist_Cells` - Each comment is connected to a particular cell (hence the generic name of the table) - Access level works naturally for records stored in this table -- User can add/read comments for cells he can see -- User can't update/remove comments that he doesn't own, but he can delete them by removing cells (rows/columns) -- Anonymous users can't see comments at all. - Each comment can have replies (but replies can't have more replies) Comments are hidden by default, they can be enabled by COMMENTS=true env variable. Some things for follow-up - Avatars, currently the user's profile image is not shown or retrieved from the server - Virtual rendering for comments list in creator panel. Currently, there is a limit of 200 comments. Test Plan: New and existing tests Reviewers: georgegevoian, paulfitz Reviewed By: georgegevoian Subscribers: paulfitz Differential Revision: https://phab.getgrist.com/D3509
This commit is contained in:
@@ -26,6 +26,7 @@ import {DisposableWithEvents} from 'app/common/DisposableWithEvents';
|
||||
import {CompareFunc, sortedIndex} from 'app/common/gutil';
|
||||
import {SkippableRows} from 'app/common/TableData';
|
||||
import {RowFilterFunc} from "app/common/RowFilterFunc";
|
||||
import {Observable} from 'grainjs';
|
||||
|
||||
/**
|
||||
* Special constant value that can be used for the `rows` array for the 'rowNotify'
|
||||
@@ -390,7 +391,10 @@ class RowGroupHelper<Value> extends RowSource {
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Helper function that does map.get(key).push(r), creating an Array for the given key if
|
||||
* necessary.
|
||||
*/
|
||||
function _addToMapOfArrays<K, V>(map: Map<K, V[]>, key: K, r: V): void {
|
||||
let arr = map.get(key);
|
||||
if (!arr) { map.set(key, arr = []); }
|
||||
@@ -437,11 +441,6 @@ export class RowGrouping<Value> extends RowListener {
|
||||
|
||||
// Implementation of the RowListener interface.
|
||||
|
||||
/**
|
||||
* Helper function that does map.get(key).push(r), creating an Array for the given key if
|
||||
* necessary.
|
||||
*/
|
||||
|
||||
public onAddRows(rows: RowList) {
|
||||
const groupedRows = new Map();
|
||||
for (const r of rows) {
|
||||
@@ -707,6 +706,41 @@ export class SortedRowSet extends RowListener {
|
||||
}
|
||||
}
|
||||
|
||||
type RowTester = (rowId: RowId) => boolean;
|
||||
/**
|
||||
* RowWatcher is a RowListener that maintains an observable function that checks whether a row
|
||||
* is in the connected RowSource.
|
||||
*/
|
||||
export class RowWatcher extends RowListener {
|
||||
/**
|
||||
* Observable function that returns true if the row is in the connected RowSource.
|
||||
*/
|
||||
public rowFilter: Observable<RowTester> = Observable.create(this, () => false);
|
||||
// We count the number of times the row is added or removed from the source.
|
||||
// In most cases row is added and removed only once.
|
||||
private _rowCounter: Map<RowId, number> = new Map();
|
||||
|
||||
public clear() {
|
||||
this._rowCounter.clear();
|
||||
this.rowFilter.set(() => false);
|
||||
this.stopListening();
|
||||
}
|
||||
|
||||
protected onAddRows(rows: RowList) {
|
||||
for (const r of rows) {
|
||||
this._rowCounter.set(r, (this._rowCounter.get(r) || 0) + 1);
|
||||
}
|
||||
this.rowFilter.set((row) => (this._rowCounter.get(row) ?? 0) > 0);
|
||||
}
|
||||
|
||||
protected onRemoveRows(rows: RowList) {
|
||||
for (const r of rows) {
|
||||
this._rowCounter.set(r, (this._rowCounter.get(r) || 0) - 1);
|
||||
}
|
||||
this.rowFilter.set((row) => (this._rowCounter.get(row) ?? 0) > 0);
|
||||
}
|
||||
}
|
||||
|
||||
function isSmallChange(rows: RowList) {
|
||||
return Array.isArray(rows) && rows.length <= 2;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user