mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Add rules to eslint to better match our coding conventions.
Summary: We used tslint earlier, and on switching to eslint, some rules were not transfered. This moves more rules over, for consistent conventions or helpful warnings. - Name private members with a leading underscore. - Prefer interface over a type alias. - Use consistent spacing around ':' in type annotations. - Use consistent spacing around braces of code blocks. - Use semicolons consistently at the ends of statements. - Use braces around even one-liner blocks, like conditionals and loops. - Warn about shadowed variables. Test Plan: Fixed all new warnings. Should be no behavior changes in code. Reviewers: paulfitz Reviewed By: paulfitz Differential Revision: https://phab.getgrist.com/D2831
This commit is contained in:
@@ -1067,7 +1067,7 @@ class ObsUserAttributeRule extends Disposable {
|
||||
// TODO this weirdly only works on the first click
|
||||
(editor as any).completer?.showPopup(editor);
|
||||
}
|
||||
})
|
||||
});
|
||||
})
|
||||
}),
|
||||
testId('rule-userattr-attr'),
|
||||
|
||||
@@ -440,7 +440,7 @@ export class ActionLog extends dispose.Disposable implements IDomComponent {
|
||||
const fieldIndex = viewSection.viewFields().peek().findIndex((f: any) => f.colId.peek() === colId);
|
||||
|
||||
// Finally, move cursor position to the section, column (if we found it), and row.
|
||||
this._gristDoc.moveToCursorPos({rowId, sectionId, fieldIndex}).catch(() => { /* do nothing */});
|
||||
this._gristDoc.moveToCursorPos({rowId, sectionId, fieldIndex}).catch(() => { /* do nothing */ });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,8 +28,9 @@ export function samePosition(a: CellPosition, b: CellPosition) {
|
||||
* @param docModel Document model
|
||||
*/
|
||||
export function fromCursor(position: CursorPos, docModel: DocModel): CellPosition | null {
|
||||
if (!position.sectionId || !position.rowId || position.fieldIndex == null)
|
||||
if (!position.sectionId || !position.rowId || position.fieldIndex == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const section = docModel.viewSections.getRowModel(position.sectionId);
|
||||
const colRef = section.viewFields().peek()[position.fieldIndex]?.colRef.peek();
|
||||
|
||||
@@ -31,6 +31,7 @@ CodeEditorPanel.prototype.buildDom = function() {
|
||||
kd.scope(this._schema, function(schema) {
|
||||
// The reason to scope and rebuild instead of using `kd.text(schema)` is because
|
||||
// hljs.highlightBlock(elem) replaces `elem` with a whole new dom tree.
|
||||
if (!schema) { return null; }
|
||||
return dom(
|
||||
'code.g-code-viewer.python',
|
||||
schema,
|
||||
|
||||
@@ -204,15 +204,16 @@ export class Comm extends dispose.Disposable implements GristServerAPI, DocListA
|
||||
public pendingRequests: Map<number, CommRequestInFlight>;
|
||||
public nextRequestNumber: number = 0;
|
||||
|
||||
protected listenTo: BackboneEvents["listenTo"]; // set by Backbone
|
||||
protected trigger: BackboneEvents["trigger"]; // set by Backbone
|
||||
protected stopListening: BackboneEvents["stopListening"]; // set by Backbone
|
||||
|
||||
// This is a map from docId to the connection for the server that manages
|
||||
// that docId. In classic Grist, which doesn't have fixed docIds or multiple
|
||||
// servers, the key is always "null".
|
||||
private _connections: Map<string|null, GristWSConnection> = new Map();
|
||||
private _collectedUserActions: UserAction[] | null;
|
||||
private _singleWorkerMode: boolean = getInitialDocAssignment() === null; // is this classic Grist?
|
||||
private listenTo: BackboneEvents["listenTo"]; // set by Backbone
|
||||
private trigger: BackboneEvents["trigger"]; // set by Backbone
|
||||
private stopListening: BackboneEvents["stopListening"]; // set by Backbone
|
||||
|
||||
public create() {
|
||||
this.autoDisposeCallback(() => {
|
||||
|
||||
@@ -79,7 +79,7 @@ export class Cursor extends Disposable {
|
||||
optCursorPos = optCursorPos || {};
|
||||
this.viewData = baseView.viewData;
|
||||
|
||||
this._sectionId = this.autoDispose(ko.computed(() => baseView.viewSection.id()))
|
||||
this._sectionId = this.autoDispose(ko.computed(() => baseView.viewSection.id()));
|
||||
this._rowId = ko.observable(optCursorPos.rowId || 0);
|
||||
this.rowIndex = this.autoDispose(ko.computed({
|
||||
read: () => {
|
||||
|
||||
@@ -48,33 +48,33 @@ export class CursorMonitor extends Disposable {
|
||||
// whenever current position changes, store it in the memory
|
||||
this.autoDispose(doc.cursorPosition.addListener(pos => {
|
||||
// if current position is not restored yet, don't change it
|
||||
if (!this._restored) return;
|
||||
if (pos) this.storePosition(pos);
|
||||
}))
|
||||
if (!this._restored) { return; }
|
||||
if (pos) { this._storePosition(pos); }
|
||||
}));
|
||||
}
|
||||
|
||||
private _whenDocumentLoadsRestorePosition(doc: GristDoc) {
|
||||
// on view shown
|
||||
this.autoDispose(doc.currentView.addListener(async view => {
|
||||
// if the position was restored for this document do nothing
|
||||
if (this._restored) return;
|
||||
if (this._restored) { return; }
|
||||
// set that we already restored the position, as some view is shown to the user
|
||||
this._restored = true;
|
||||
// if view wasn't rendered (page is displaying history or code view) do nothing
|
||||
if (!view) return;
|
||||
if (!view) { return; }
|
||||
const viewId = doc.activeViewId.get();
|
||||
const position = this.restoreLastPosition(viewId);
|
||||
const position = this._restoreLastPosition(viewId);
|
||||
if (position) {
|
||||
await doc.recursiveMoveToCursorPos(position, true);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private storePosition(pos: ViewCursorPos) {
|
||||
private _storePosition(pos: ViewCursorPos) {
|
||||
this._store.update(this._docId, pos);
|
||||
}
|
||||
|
||||
private restoreLastPosition(view: IDocPage) {
|
||||
private _restoreLastPosition(view: IDocPage) {
|
||||
const lastPosition = this._store.read(this._docId);
|
||||
this._store.clear(this._docId);
|
||||
if (lastPosition && lastPosition.position.viewId == view) {
|
||||
@@ -87,13 +87,13 @@ export class CursorMonitor extends Disposable {
|
||||
// Internal implementations for working with local storage
|
||||
class StorageWrapper {
|
||||
|
||||
constructor(private storage = getStorage()) {
|
||||
constructor(private _storage = getStorage()) {
|
||||
|
||||
}
|
||||
|
||||
public update(docId: string, position: ViewCursorPos): void {
|
||||
try {
|
||||
const storage = this.storage;
|
||||
const storage = this._storage;
|
||||
const data = { docId, position, timestamp: Date.now() };
|
||||
storage.setItem(this._key(docId), JSON.stringify(data));
|
||||
} catch (e) {
|
||||
@@ -102,14 +102,14 @@ class StorageWrapper {
|
||||
}
|
||||
|
||||
public clear(docId: string,): void {
|
||||
const storage = this.storage;
|
||||
const storage = this._storage;
|
||||
storage.removeItem(this._key(docId));
|
||||
}
|
||||
|
||||
public read(docId: string): { docId: string; position: ViewCursorPos; } | undefined {
|
||||
const storage = this.storage;
|
||||
const storage = this._storage;
|
||||
const result = storage.getItem(this._key(docId));
|
||||
if (!result) return undefined;
|
||||
if (!result) { return undefined; }
|
||||
return JSON.parse(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ export class EditorMonitor extends Disposable {
|
||||
this._store = new EditMemoryStorage(doc.docId(), store);
|
||||
|
||||
// listen to document events to handle view load event
|
||||
this._listenToReload(doc)
|
||||
this._listenToReload(doc);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,7 +67,7 @@ export class EditorMonitor extends Disposable {
|
||||
}
|
||||
executed = true;
|
||||
// if view wasn't rendered (page is displaying history or code view) do nothing
|
||||
if (!view) return;
|
||||
if (!view) { return; }
|
||||
const lastEdit = this._restorePosition();
|
||||
if (lastEdit) {
|
||||
// set the cursor at right cell
|
||||
@@ -98,11 +98,11 @@ function typedListener(owner: IDisposableOwner) {
|
||||
type EditorState = any;
|
||||
|
||||
// Schema for value stored in the local storage
|
||||
type LastEditData = {
|
||||
interface LastEditData {
|
||||
// absolute position for a cell
|
||||
position: CellPosition,
|
||||
position: CellPosition;
|
||||
// editor's state
|
||||
value: EditorState
|
||||
value: EditorState;
|
||||
}
|
||||
|
||||
// Abstraction for working with local storage
|
||||
@@ -111,7 +111,7 @@ class EditMemoryStorage {
|
||||
private _entry: LastEditData | null = null;
|
||||
private _timestamp = 0;
|
||||
|
||||
constructor(private _docId: string, private storage = getStorage()) {
|
||||
constructor(private _docId: string, private _storage = getStorage()) {
|
||||
}
|
||||
|
||||
public updateValue(pos: CellPosition, value: EditorState): void {
|
||||
@@ -138,7 +138,7 @@ class EditMemoryStorage {
|
||||
}
|
||||
|
||||
protected load() {
|
||||
const storage = this.storage;
|
||||
const storage = this._storage;
|
||||
const data = storage.getItem(this._key());
|
||||
this._entry = null;
|
||||
this._timestamp = 0;
|
||||
@@ -150,7 +150,7 @@ class EditMemoryStorage {
|
||||
console.error("[EditMemory] Data in local storage has a different structure");
|
||||
return;
|
||||
}
|
||||
this._entry = entry
|
||||
this._entry = entry;
|
||||
this._timestamp = timestamp;
|
||||
} catch (e) {
|
||||
console.error("[EditMemory] Can't deserialize date from local storage");
|
||||
@@ -159,7 +159,7 @@ class EditMemoryStorage {
|
||||
}
|
||||
|
||||
protected save(): void {
|
||||
const storage = this.storage;
|
||||
const storage = this._storage;
|
||||
|
||||
// if entry was removed - clear the storage
|
||||
if (!this._entry) {
|
||||
|
||||
@@ -111,10 +111,10 @@ export class GristDoc extends DisposableWithEvents {
|
||||
public readonly fieldEditorHolder = Holder.create(this);
|
||||
|
||||
// Holds current view that is currently rendered
|
||||
public currentView : Observable<BaseView | null>;
|
||||
public currentView: Observable<BaseView | null>;
|
||||
|
||||
// Holds current cursor position with a view id
|
||||
public cursorPosition : Computed<ViewCursorPos | undefined>;
|
||||
public cursorPosition: Computed<ViewCursorPos | undefined>;
|
||||
|
||||
private _actionLog: ActionLog;
|
||||
private _undoStack: UndoStack;
|
||||
@@ -250,22 +250,22 @@ export class GristDoc extends DisposableWithEvents {
|
||||
});
|
||||
// then listen if the view is present, because we still need to wait for it load properly
|
||||
this.autoDispose(viewInstance.addListener(async (view) => {
|
||||
if (!view) return;
|
||||
if (!view) { return; }
|
||||
await view.getLoadingDonePromise();
|
||||
this.currentView.set(view);
|
||||
}))
|
||||
}));
|
||||
|
||||
// create observable for current cursor position
|
||||
this.cursorPosition = Computed.create<ViewCursorPos | undefined>(this, use => {
|
||||
// get the BaseView
|
||||
const view = use(viewInstance);
|
||||
if (!view) return undefined;
|
||||
if (!view) { return undefined; }
|
||||
// get current viewId
|
||||
const viewId = use(this.activeViewId);
|
||||
if (typeof viewId != 'number') return undefined;
|
||||
if (typeof viewId != 'number') { return undefined; }
|
||||
// read latest position
|
||||
const currentPosition = use(view.cursor.currentPosition);
|
||||
if (currentPosition) return { ...currentPosition, viewId }
|
||||
if (currentPosition) { return { ...currentPosition, viewId }; }
|
||||
return undefined;
|
||||
});
|
||||
|
||||
@@ -333,7 +333,7 @@ export class GristDoc extends DisposableWithEvents {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const viewInstance = await this._switchToSectionId(cursorPos.sectionId)
|
||||
const viewInstance = await this._switchToSectionId(cursorPos.sectionId);
|
||||
if (viewInstance) {
|
||||
viewInstance.setCursorPos(cursorPos);
|
||||
}
|
||||
@@ -643,7 +643,7 @@ export class GristDoc extends DisposableWithEvents {
|
||||
}
|
||||
const view: ViewRec = section.view.peek();
|
||||
const viewId = view.getRowId();
|
||||
if (viewId != this.activeViewId.get()) await this.openDocPage(view.getRowId());
|
||||
if (viewId != this.activeViewId.get()) { await this.openDocPage(view.getRowId()); }
|
||||
if (setAsActiveSection) { view.activeSectionId(cursorPos.sectionId); }
|
||||
const fieldIndex = cursorPos.fieldIndex;
|
||||
const viewInstance = await waitObs(section.viewInstance);
|
||||
@@ -669,14 +669,14 @@ export class GristDoc extends DisposableWithEvents {
|
||||
* @param input Optional. Cell's initial value
|
||||
*/
|
||||
public async activateEditorAtCursor(options: { init?: string, state?: any}) {
|
||||
const view = await this.waitForView();
|
||||
const view = await this._waitForView();
|
||||
view?.activateEditorAtCursor(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a view to be ready
|
||||
*/
|
||||
private async waitForView() {
|
||||
private async _waitForView() {
|
||||
const view = await waitObs(this.viewModel.activeSection.peek().viewInstance);
|
||||
await view?.getLoadingDonePromise();
|
||||
return view;
|
||||
@@ -788,13 +788,13 @@ export class GristDoc extends DisposableWithEvents {
|
||||
* Convert a url hash to a cursor position.
|
||||
*/
|
||||
private _getCursorPosFromHash(hash: HashLink): CursorPos {
|
||||
const cursorPos : CursorPos = { rowId: hash.rowId, sectionId: hash.sectionId };
|
||||
const cursorPos: CursorPos = { rowId: hash.rowId, sectionId: hash.sectionId };
|
||||
if (cursorPos.sectionId != undefined && hash.colRef !== undefined){
|
||||
// translate colRef to a fieldIndex
|
||||
const section = this.docModel.viewSections.getRowModel(cursorPos.sectionId);
|
||||
const fieldIndex = section.viewFields.peek().all()
|
||||
.findIndex(x=> x.colRef.peek() == hash.colRef);
|
||||
if (fieldIndex >= 0) cursorPos.fieldIndex = fieldIndex;
|
||||
if (fieldIndex >= 0) { cursorPos.fieldIndex = fieldIndex; }
|
||||
}
|
||||
return cursorPos;
|
||||
}
|
||||
|
||||
@@ -106,6 +106,8 @@ export class GristWSConnection extends Disposable {
|
||||
public useCount: number = 0;
|
||||
public on: BackboneEvents['on']; // set by Backbone
|
||||
|
||||
protected trigger: BackboneEvents['trigger']; // set by Backbone
|
||||
|
||||
private _clientId: string|null;
|
||||
private _clientCounter: string; // Identifier of this GristWSConnection object in this browser tab session
|
||||
private _assignmentId: string|null;
|
||||
@@ -118,7 +120,6 @@ export class GristWSConnection extends Disposable {
|
||||
private _reconnectAttempts: number = 0;
|
||||
private _wantReconnect: boolean = true;
|
||||
private _ws: WebSocket|null = null;
|
||||
private trigger: BackboneEvents['trigger']; // set by Backbone
|
||||
|
||||
constructor(private _settings: GristWSSettings = new GristWSSettingsBrowser()) {
|
||||
super();
|
||||
|
||||
@@ -28,8 +28,8 @@ import pickBy = require('lodash/pickBy');
|
||||
* Creates an instance of TypeTransform for a single field. Extends ColumnTransform.
|
||||
*/
|
||||
export class TypeTransform extends ColumnTransform {
|
||||
private reviseTypeChange = Observable.create(this, false);
|
||||
private transformWidget: Computed<NewAbstractWidget|null>;
|
||||
private _reviseTypeChange = Observable.create(this, false);
|
||||
private _transformWidget: Computed<NewAbstractWidget|null>;
|
||||
|
||||
constructor(gristDoc: GristDoc, fieldBuilder: FieldBuilder) {
|
||||
super(gristDoc, fieldBuilder);
|
||||
@@ -37,7 +37,7 @@ export class TypeTransform extends ColumnTransform {
|
||||
|
||||
// The display widget of the new transform column. Used to build the transform config menu.
|
||||
// Only set while transforming.
|
||||
this.transformWidget = Computed.create(this, fromKo(fieldBuilder.widgetImpl), (use, widget) => {
|
||||
this._transformWidget = Computed.create(this, fromKo(fieldBuilder.widgetImpl), (use, widget) => {
|
||||
return use(this.origColumn.isTransforming) ? widget : null;
|
||||
});
|
||||
}
|
||||
@@ -49,12 +49,12 @@ export class TypeTransform extends ColumnTransform {
|
||||
// An observable to disable all buttons before the dom get removed.
|
||||
const disableButtons = Observable.create(null, false);
|
||||
|
||||
this.reviseTypeChange.set(false);
|
||||
this._reviseTypeChange.set(false);
|
||||
this.editor = this.autoDispose(AceEditor.create({ observable: this.transformColumn.formula }));
|
||||
return dom('div',
|
||||
testId('type-transform-top'),
|
||||
dom.maybe(this.transformWidget, transformWidget => transformWidget.buildTransformConfigDom()),
|
||||
dom.maybe(this.reviseTypeChange, () =>
|
||||
dom.maybe(this._transformWidget, transformWidget => transformWidget.buildTransformConfigDom()),
|
||||
dom.maybe(this._reviseTypeChange, () =>
|
||||
dom('div.transform_editor', this.buildEditorDom(),
|
||||
testId("type-transform-formula")
|
||||
)
|
||||
@@ -64,7 +64,7 @@ export class TypeTransform extends ColumnTransform {
|
||||
'Cancel', testId("type-transform-cancel"),
|
||||
dom.cls('disabled', disableButtons)
|
||||
),
|
||||
dom.domComputed(this.reviseTypeChange, revising => {
|
||||
dom.domComputed(this._reviseTypeChange, revising => {
|
||||
if (revising) {
|
||||
return basicButton(dom.on('click', () => this.editor.writeObservable()),
|
||||
'Preview', testId("type-transform-update"),
|
||||
@@ -72,7 +72,7 @@ export class TypeTransform extends ColumnTransform {
|
||||
{ title: 'Update formula (Shift+Enter)' }
|
||||
);
|
||||
} else {
|
||||
return basicButton(dom.on('click', () => { this.reviseTypeChange.set(true); }),
|
||||
return basicButton(dom.on('click', () => { this._reviseTypeChange.set(true); }),
|
||||
'Revise', testId("type-transform-revise"),
|
||||
dom.cls('disabled', disableButtons)
|
||||
);
|
||||
|
||||
@@ -117,13 +117,13 @@ export class UndoStack extends dispose.Disposable {
|
||||
// context where the change was originally made. We jump first immediately to feel more
|
||||
// responsive, then again when the action is done. The second jump matters more for most
|
||||
// changes, but the first is the important one when Undoing an AddRecord.
|
||||
this._gristDoc.moveToCursorPos(ag.cursorPos, ag).catch(() => {/* do nothing */})
|
||||
this._gristDoc.moveToCursorPos(ag.cursorPos, ag).catch(() => { /* do nothing */ });
|
||||
await this._gristDoc.docComm.applyUserActionsById(
|
||||
actionGroups.map(a => a.actionNum),
|
||||
actionGroups.map(a => a.actionHash),
|
||||
isUndo,
|
||||
{ otherId: ag.actionNum });
|
||||
this._gristDoc.moveToCursorPos(ag.cursorPos, ag).catch(() => {/* do nothing */})
|
||||
this._gristDoc.moveToCursorPos(ag.cursorPos, ag).catch(() => { /* do nothing */ });
|
||||
} catch (err) {
|
||||
err.message = `Failed to apply ${isUndo ? 'undo' : 'redo'} action: ${err.message}`;
|
||||
throw err;
|
||||
|
||||
@@ -18,7 +18,7 @@ export async function duplicatePage(gristDoc: GristDoc, pageId: number) {
|
||||
const pagesTable = gristDoc.docModel.pages;
|
||||
const pageName = pagesTable.rowModels[pageId].view.peek().name.peek();
|
||||
let inputEl: HTMLInputElement;
|
||||
setTimeout(() => {inputEl.focus(); inputEl.select(); }, 100);
|
||||
setTimeout(() => { inputEl.focus(); inputEl.select(); }, 100);
|
||||
|
||||
confirmModal('Duplicate page', 'Save', () => makeDuplicate(gristDoc, pageId, inputEl.value), (
|
||||
dom('div', [
|
||||
|
||||
8
app/client/declarations.d.ts
vendored
8
app/client/declarations.d.ts
vendored
@@ -45,9 +45,9 @@ declare module "app/client/components/BaseView" {
|
||||
import {DomArg} from 'grainjs';
|
||||
import {IOpenController} from 'popweasel';
|
||||
|
||||
type Options = {
|
||||
init? : string,
|
||||
state? : any
|
||||
interface Options {
|
||||
init?: string;
|
||||
state?: any;
|
||||
}
|
||||
|
||||
namespace BaseView {}
|
||||
@@ -68,7 +68,7 @@ declare module "app/client/components/BaseView" {
|
||||
public createFilterMenu(ctl: IOpenController, field: ViewFieldRec, onClose?: () => void): HTMLElement;
|
||||
public buildTitleControls(): DomArg;
|
||||
public getLoadingDonePromise(): Promise<void>;
|
||||
public activateEditorAtCursor(options?: Options) : void;
|
||||
public activateEditorAtCursor(options?: Options): void;
|
||||
public onResize(): void;
|
||||
public prepareToPrint(onOff: boolean): void;
|
||||
public moveEditRowToCursor(): DataRowModel;
|
||||
|
||||
@@ -55,18 +55,18 @@ export class Autocomplete<Item extends ACItem> extends Disposable {
|
||||
|
||||
constructor(
|
||||
private _triggerElem: HTMLInputElement | HTMLTextAreaElement,
|
||||
private readonly options: IAutocompleteOptions<Item>,
|
||||
private readonly _options: IAutocompleteOptions<Item>,
|
||||
) {
|
||||
super();
|
||||
|
||||
const content = cssMenuWrap(
|
||||
this._menuContent = cssMenu({class: options.menuCssClass || ''},
|
||||
dom.forEach(this._items, (item) => options.renderItem(item, this._highlightFunc)),
|
||||
this._menuContent = cssMenu({class: _options.menuCssClass || ''},
|
||||
dom.forEach(this._items, (item) => _options.renderItem(item, this._highlightFunc)),
|
||||
dom.style('min-width', _triggerElem.getBoundingClientRect().width + 'px'),
|
||||
dom.on('mouseleave', (ev) => this._setSelected(-1, true)),
|
||||
dom.on('click', (ev) => {
|
||||
this._setSelected(this._findTargetItem(ev.target), true);
|
||||
if (options.onClick) { options.onClick(); }
|
||||
if (_options.onClick) { _options.onClick(); }
|
||||
})
|
||||
),
|
||||
// Prevent trigger element from being blurred on click.
|
||||
@@ -91,7 +91,7 @@ export class Autocomplete<Item extends ACItem> extends Disposable {
|
||||
this.onDispose(() => { dom.domDispose(content); content.remove(); });
|
||||
|
||||
// Prepare and create the Popper instance, which places the content according to the options.
|
||||
const popperOptions = merge({}, defaultPopperOptions, options.popperOptions);
|
||||
const popperOptions = merge({}, defaultPopperOptions, _options.popperOptions);
|
||||
this._popper = createPopper(_triggerElem, content, popperOptions);
|
||||
this.onDispose(() => this._popper.destroy());
|
||||
}
|
||||
@@ -110,7 +110,7 @@ export class Autocomplete<Item extends ACItem> extends Disposable {
|
||||
const elem = (this._menuContent.children[index] as HTMLElement) || null;
|
||||
const prev = this._selected;
|
||||
if (elem !== prev) {
|
||||
const clsName = this.options.selectedCssClass || 'selected';
|
||||
const clsName = this._options.selectedCssClass || 'selected';
|
||||
if (prev) { prev.classList.remove(clsName); }
|
||||
if (elem) {
|
||||
elem.classList.add(clsName);
|
||||
@@ -123,7 +123,7 @@ export class Autocomplete<Item extends ACItem> extends Disposable {
|
||||
if (updateValue) {
|
||||
// Update trigger's value with the selected choice, or else with the last typed value.
|
||||
if (elem) {
|
||||
this._triggerElem.value = this.options.getItemText(this.getSelectedItem()!);
|
||||
this._triggerElem.value = this._options.getItemText(this.getSelectedItem()!);
|
||||
} else {
|
||||
this._triggerElem.value = this._lastAsTyped;
|
||||
}
|
||||
@@ -147,7 +147,7 @@ export class Autocomplete<Item extends ACItem> extends Disposable {
|
||||
this._lastAsTyped = inputVal;
|
||||
// TODO We should perhaps debounce the search() call in some clever way, to avoid unnecessary
|
||||
// searches while typing. Today, search() is synchronous in practice, so it doesn't matter.
|
||||
const acResults = await this.options.search(inputVal);
|
||||
const acResults = await this._options.search(inputVal);
|
||||
this._highlightFunc = acResults.highlightFunc;
|
||||
this._items.set(acResults.items);
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ export function isEquivalentFilter(state: FilterState, spec: FilterSpec): boolea
|
||||
const other = makeFilterState(spec);
|
||||
if (state.include !== other.include) { return false; }
|
||||
if (state.values.size !== other.values.size) { return false; }
|
||||
for (const val of other.values) { if (!state.values.has(val)) { return false; }}
|
||||
for (const val of other.values) { if (!state.values.has(val)) { return false; } }
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ export class SearchModelImpl extends Disposable implements SearchModel {
|
||||
this.autoDispose(this.value.addListener(v => { void findFirst(v); }));
|
||||
|
||||
// Set this.noMatch to false when multiPage gets turned ON.
|
||||
this.autoDispose(this.multiPage.addListener(v => { if (v) { this.noMatch.set(false); }}));
|
||||
this.autoDispose(this.multiPage.addListener(v => { if (v) { this.noMatch.set(false); } }));
|
||||
|
||||
// Schedule a search restart when user changes pages (otherwise search would resume from the
|
||||
// previous page that is not shown anymore). Also revert noMatch flag when in single page mode.
|
||||
|
||||
@@ -207,7 +207,7 @@ export class TreeNodeRecord implements TreeNode {
|
||||
// Get all the records included in this item.
|
||||
public getRecords(): TreeRecord[] {
|
||||
const records = [] as TreeRecord[];
|
||||
if (this.index !== "root") {records.push(this._records[this.index]); }
|
||||
if (this.index !== "root") { records.push(this._records[this.index]); }
|
||||
walkTree(this, (item: TreeItemRecord) => records.push(this._records[item.index]));
|
||||
return records;
|
||||
}
|
||||
@@ -255,7 +255,7 @@ export function find(model: TreeNode, func: (item: TreeItem) => boolean): TreeIt
|
||||
if (children) {
|
||||
for (const child of children.get()) {
|
||||
const found = func(child) && child || find(child, func);
|
||||
if (found) {return found; }
|
||||
if (found) { return found; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ function _getLoginLogoutUrl(method: 'login'|'logout'|'signin', nextUrl: string):
|
||||
* only public interface is the urlState() accessor.
|
||||
*/
|
||||
export class UrlStateImpl {
|
||||
constructor(private window: {gristConfig?: Partial<GristLoadConfig>}) {}
|
||||
constructor(private _window: {gristConfig?: Partial<GristLoadConfig>}) {}
|
||||
|
||||
/**
|
||||
* The actual serialization of a url state into a URL. The URL has the form
|
||||
@@ -105,7 +105,7 @@ export class UrlStateImpl {
|
||||
* localhost:8080/o/<org>
|
||||
*/
|
||||
public encodeUrl(state: IGristUrlState, baseLocation: Location | URL): string {
|
||||
const gristConfig = this.window.gristConfig || {};
|
||||
const gristConfig = this._window.gristConfig || {};
|
||||
return encodeUrl(gristConfig, state, baseLocation);
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ export class UrlStateImpl {
|
||||
* Parse a URL location into an IGristUrlState object. See encodeUrl() documentation.
|
||||
*/
|
||||
public decodeUrl(location: Location | URL): IGristUrlState {
|
||||
const gristConfig = this.window.gristConfig || {};
|
||||
const gristConfig = this._window.gristConfig || {};
|
||||
return decodeUrl(gristConfig, location);
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ export class UrlStateImpl {
|
||||
* a matter of DocWorker requiring a different version (e.g. /v/OTHER/doc/...).
|
||||
*/
|
||||
public needPageLoad(prevState: IGristUrlState, newState: IGristUrlState): boolean {
|
||||
const gristConfig = this.window.gristConfig || {};
|
||||
const gristConfig = this._window.gristConfig || {};
|
||||
const orgReload = prevState.org !== newState.org;
|
||||
// Reload when moving to/from a document or between doc and non-doc.
|
||||
const docReload = prevState.doc !== newState.doc;
|
||||
|
||||
@@ -368,25 +368,25 @@ export class FilteredRowSource extends BaseFilteredRowSource {
|
||||
* Private helper object that maintains a set of rows for a particular group.
|
||||
*/
|
||||
class RowGroupHelper<Value> extends RowSource {
|
||||
private rows: Set<RowId> = new Set();
|
||||
private _rows: Set<RowId> = new Set();
|
||||
constructor(public readonly groupValue: Value) {
|
||||
super();
|
||||
}
|
||||
|
||||
public getAllRows() {
|
||||
return this.rows.values();
|
||||
return this._rows.values();
|
||||
}
|
||||
|
||||
public getNumRows(): number {
|
||||
return this.rows.size;
|
||||
return this._rows.size;
|
||||
}
|
||||
|
||||
public _addAll(rows: RowList) {
|
||||
for (const r of rows) { this.rows.add(r); }
|
||||
for (const r of rows) { this._rows.add(r); }
|
||||
}
|
||||
|
||||
public _removeAll(rows: RowList) {
|
||||
for (const r of rows) { this.rows.delete(r); }
|
||||
for (const r of rows) { this._rows.delete(r); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -245,8 +245,8 @@ function buildWorkspaceDocBlock(home: HomeModel, workspace: Workspace, flashDocI
|
||||
// The flash value may change to true, and then immediately to false. We highlight it
|
||||
// using a transition, and scroll into view, when it turns back to false.
|
||||
transition(flash, {
|
||||
prepare(elem, val) { if (!val) { elem.style.backgroundColor = colors.slate.toString(); }},
|
||||
run(elem, val) { if (!val) { elem.style.backgroundColor = ''; scrollIntoViewIfNeeded(elem); }},
|
||||
prepare(elem, val) { if (!val) { elem.style.backgroundColor = colors.slate.toString(); } },
|
||||
run(elem, val) { if (!val) { elem.style.backgroundColor = ''; scrollIntoViewIfNeeded(elem); } },
|
||||
})
|
||||
),
|
||||
css.docRowWrapper.cls('-renaming', isRenaming),
|
||||
|
||||
@@ -45,7 +45,7 @@ export abstract class MultiItemSelector<Item extends BaseItem> extends Disposabl
|
||||
return cssMultiSelectorWrapper(
|
||||
cssItemList(testId('list'),
|
||||
dom.forEach(this._incItems, item => this.buildItemDom(item)),
|
||||
this.buildAddItemDom(this._options.addItemLabel, this._options.addItemText)
|
||||
this._buildAddItemDom(this._options.addItemLabel, this._options.addItemText)
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -60,7 +60,7 @@ export abstract class MultiItemSelector<Item extends BaseItem> extends Disposabl
|
||||
|
||||
// Called with an item from `_allItems`
|
||||
protected async remove(item: Item): Promise<void> {
|
||||
const idx = this.findIncIndex(item);
|
||||
const idx = this._findIncIndex(item);
|
||||
if (idx === -1) { return; }
|
||||
this._incItems.splice(idx, 1);
|
||||
}
|
||||
@@ -70,7 +70,7 @@ export abstract class MultiItemSelector<Item extends BaseItem> extends Disposabl
|
||||
|
||||
// Replaces an existing item (if found) with a new one
|
||||
protected async changeItem(item: Item, newItem: Item): Promise<void> {
|
||||
const idx = this.findIncIndex(item);
|
||||
const idx = this._findIncIndex(item);
|
||||
if (idx === -1) { return; }
|
||||
this._incItems.splice(idx, 1, newItem);
|
||||
}
|
||||
@@ -82,7 +82,7 @@ export abstract class MultiItemSelector<Item extends BaseItem> extends Disposabl
|
||||
selectCb: (newItem: Item) => void,
|
||||
selectOptions?: {}): Element {
|
||||
const obs = computed(use => selectedValue).onWrite(async value => {
|
||||
const newItem = this.findItemByValue(value);
|
||||
const newItem = this._findItemByValue(value);
|
||||
if (newItem) {
|
||||
selectCb(newItem);
|
||||
}
|
||||
@@ -115,17 +115,17 @@ export abstract class MultiItemSelector<Item extends BaseItem> extends Disposabl
|
||||
}
|
||||
|
||||
// Returns the index (order) of the item if it's been included, or -1 otherwise.
|
||||
private findIncIndex(item: Item): number {
|
||||
private _findIncIndex(item: Item): number {
|
||||
return this._incItems.get().findIndex(_item => _item === item);
|
||||
}
|
||||
|
||||
// Returns the item object given it's value, or undefined if not found.
|
||||
private findItemByValue(value: string): Item | undefined {
|
||||
private _findItemByValue(value: string): Item | undefined {
|
||||
return this._allItems.get().find(_item => _item.value === value);
|
||||
}
|
||||
|
||||
// Builds the about-to-be-added item
|
||||
private buildAddItemDom(defLabel: string, defText: string): Element {
|
||||
private _buildAddItemDom(defLabel: string, defText: string): Element {
|
||||
const addNewItem: Observable<boolean> = observable(false);
|
||||
return dom('li', testId('add-item'),
|
||||
dom.domComputed(addNewItem, isAdding => isAdding
|
||||
|
||||
@@ -196,7 +196,7 @@ export function buildPageWidgetPicker(
|
||||
dom.create(PageWidgetSelect, value, tables, columns, onSaveCB, options),
|
||||
|
||||
// gives focus and binds keydown events
|
||||
(elem: any) => {setTimeout(() => elem.focus(), 0); },
|
||||
(elem: any) => { setTimeout(() => elem.focus(), 0); },
|
||||
onKeyDown({
|
||||
Escape: () => ctl.close(),
|
||||
Enter: () => isValid() && onSaveCB()
|
||||
|
||||
@@ -82,7 +82,7 @@ function buildColorPicker(ctl: IOpenController, textColor: Observable<string>, f
|
||||
}),
|
||||
|
||||
// gives focus and binds keydown events
|
||||
(elem: any) => {setTimeout(() => elem.focus(), 0); },
|
||||
(elem: any) => { setTimeout(() => elem.focus(), 0); },
|
||||
onKeyDown({
|
||||
Escape: () => { revert(); },
|
||||
Enter: () => { ctl.close(); },
|
||||
@@ -158,7 +158,7 @@ class PickerComponent extends Disposable {
|
||||
),
|
||||
cssHexBox(
|
||||
this._color,
|
||||
async (val) => { if (isValidHex(val)) {this._model.setValue(val); }},
|
||||
async (val) => { if (isValidHex(val)) { this._model.setValue(val); } },
|
||||
testId(`${title}-hex`),
|
||||
// select the hex value on click. Doing it using settimeout allows to avoid some
|
||||
// sporadically losing the selection just after the click.
|
||||
|
||||
@@ -105,7 +105,7 @@ export function rawTextInput(value: Observable<string>, save: SaveFunc, onChange
|
||||
let inputEl: HTMLInputElement;
|
||||
|
||||
// When label changes updates the input, unless in the middle of editing.
|
||||
const lis = value.addListener((val) => { if (status !== Status.EDITING) { setValue(val); }});
|
||||
const lis = value.addListener((val) => { if (status !== Status.EDITING) { setValue(val); } });
|
||||
|
||||
function setValue(val: string) {
|
||||
inputEl.value = val;
|
||||
|
||||
@@ -128,8 +128,8 @@ export function searchBar(model: SearchModel, testId: TestId = noTestId) {
|
||||
find: () => { inputElem.focus(); inputElem.select(); },
|
||||
// On Mac, Firefox has a default behaviour witch causes to close the search bar on Cmd+g and
|
||||
// Cmd+shirt+G. Returning false is a Mousetrap convenience which prevents that.
|
||||
findNext: () => {model.findNext().catch(reportError); return false; },
|
||||
findPrev: () => {model.findPrev().catch(reportError); return false; },
|
||||
findNext: () => { model.findNext().catch(reportError); return false; },
|
||||
findPrev: () => { model.findPrev().catch(reportError); return false; },
|
||||
}, null, true);
|
||||
|
||||
const toggleMenu = debounce((_value?: boolean) => {
|
||||
|
||||
@@ -105,7 +105,7 @@ export class AttachmentsEditor extends NewBaseEditor {
|
||||
}),
|
||||
// Close if clicking into the background. (The default modal's behavior for this isn't
|
||||
// triggered because our content covers the whole screen.)
|
||||
dom.on('click', (ev, elem) => { if (ev.target === elem) { ctl.close(); }}),
|
||||
dom.on('click', (ev, elem) => { if (ev.target === elem) { ctl.close(); } }),
|
||||
...this._buildDom(ctl)
|
||||
];
|
||||
}, {noEscapeKey: true});
|
||||
|
||||
@@ -66,30 +66,30 @@ export class FieldBuilder extends Disposable {
|
||||
public readonly widgetImpl: ko.Computed<NewAbstractWidget>;
|
||||
public readonly diffImpl: NewAbstractWidget;
|
||||
|
||||
private readonly availableTypes: Computed<Array<IOptionFull<string>>>;
|
||||
private readonly readOnlyPureType: ko.PureComputed<string>;
|
||||
private readonly isRightType: ko.PureComputed<(value: CellValue, options?: any) => boolean>;
|
||||
private readonly refTableId: ko.Computed<string | null>;
|
||||
private readonly isRef: ko.Computed<boolean>;
|
||||
private readonly _availableTypes: Computed<Array<IOptionFull<string>>>;
|
||||
private readonly _readOnlyPureType: ko.PureComputed<string>;
|
||||
private readonly _isRightType: ko.PureComputed<(value: CellValue, options?: any) => boolean>;
|
||||
private readonly _refTableId: ko.Computed<string | null>;
|
||||
private readonly _isRef: ko.Computed<boolean>;
|
||||
private readonly _rowMap: Map<DataRowModel, Element>;
|
||||
private readonly isTransformingFormula: ko.Computed<boolean>;
|
||||
private readonly isTransformingType: ko.Computed<boolean>;
|
||||
private readonly _isTransformingFormula: ko.Computed<boolean>;
|
||||
private readonly _isTransformingType: ko.Computed<boolean>;
|
||||
private readonly _fieldEditorHolder: Holder<IDisposable>;
|
||||
private readonly widgetCons: ko.Computed<{create: (...args: any[]) => NewAbstractWidget}>;
|
||||
private readonly docModel: DocModel;
|
||||
private readonly _widgetCons: ko.Computed<{create: (...args: any[]) => NewAbstractWidget}>;
|
||||
private readonly _docModel: DocModel;
|
||||
|
||||
public constructor(public readonly gristDoc: GristDoc, public readonly field: ViewFieldRec,
|
||||
private _cursor: Cursor) {
|
||||
super();
|
||||
|
||||
this.docModel = gristDoc.docModel;
|
||||
this._docModel = gristDoc.docModel;
|
||||
this.origColumn = field.column();
|
||||
this.options = field.widgetOptionsJson;
|
||||
|
||||
this.readOnlyPureType = ko.pureComputed(() => this.field.column().pureType());
|
||||
this._readOnlyPureType = ko.pureComputed(() => this.field.column().pureType());
|
||||
|
||||
// Observable with a list of available types.
|
||||
this.availableTypes = Computed.create(this, (use) => {
|
||||
this._availableTypes = Computed.create(this, (use) => {
|
||||
const isFormula = use(this.origColumn.isFormula);
|
||||
const types: Array<IOptionFull<string>> = [];
|
||||
_.each(UserType.typeDefs, (def: any, key: string|number) => {
|
||||
@@ -108,17 +108,17 @@ export class FieldBuilder extends Disposable {
|
||||
});
|
||||
|
||||
// Observable which evaluates to a *function* that decides if a value is valid.
|
||||
this.isRightType = ko.pureComputed(function() {
|
||||
return gristTypes.isRightType(this.readOnlyPureType()) || _.constant(false);
|
||||
this._isRightType = ko.pureComputed(function() {
|
||||
return gristTypes.isRightType(this._readOnlyPureType()) || _.constant(false);
|
||||
}, this);
|
||||
|
||||
// Returns a boolean indicating whether the column is type Reference.
|
||||
this.isRef = this.autoDispose(ko.computed(() => {
|
||||
this._isRef = this.autoDispose(ko.computed(() => {
|
||||
return gutil.startsWith(this.field.column().type(), 'Ref:');
|
||||
}));
|
||||
|
||||
// Gives the table ID to which the reference points.
|
||||
this.refTableId = this.autoDispose(ko.computed({
|
||||
this._refTableId = this.autoDispose(ko.computed({
|
||||
read: () => gutil.removePrefix(this.field.column().type(), "Ref:"),
|
||||
write: val => this._setType(`Ref:${val}`)
|
||||
}));
|
||||
@@ -148,11 +148,11 @@ export class FieldBuilder extends Disposable {
|
||||
this.columnTransform = null;
|
||||
|
||||
// Returns a boolean indicating whether a formula transform is in progress.
|
||||
this.isTransformingFormula = this.autoDispose(ko.computed(() => {
|
||||
this._isTransformingFormula = this.autoDispose(ko.computed(() => {
|
||||
return this.field.column().isTransforming() && this.columnTransform instanceof FormulaTransform;
|
||||
}));
|
||||
// Returns a boolean indicating whether a type transform is in progress.
|
||||
this.isTransformingType = this.autoDispose(ko.computed(() => {
|
||||
this._isTransformingType = this.autoDispose(ko.computed(() => {
|
||||
return (this.field.column().isTransforming() || this.isCallPending()) &&
|
||||
(this.columnTransform instanceof TypeTransform);
|
||||
}));
|
||||
@@ -165,14 +165,14 @@ export class FieldBuilder extends Disposable {
|
||||
this._rowMap = new Map();
|
||||
|
||||
// Returns the constructor for the widget, and only notifies subscribers on changes.
|
||||
this.widgetCons = this.autoDispose(koUtil.withKoUtils(ko.computed(function() {
|
||||
this._widgetCons = this.autoDispose(koUtil.withKoUtils(ko.computed(function() {
|
||||
return UserTypeImpl.getWidgetConstructor(this.options().widget,
|
||||
this.readOnlyPureType());
|
||||
this._readOnlyPureType());
|
||||
}, this)).onlyNotifyUnequal());
|
||||
|
||||
// Computed builder for the widget.
|
||||
this.widgetImpl = this.autoDispose(koUtil.computedBuilder(() => {
|
||||
const cons = this.widgetCons();
|
||||
const cons = this._widgetCons();
|
||||
// Must subscribe to `colId` so that field.colId is rechecked on transform.
|
||||
return cons.create.bind(cons, this.field, this.field.colId());
|
||||
}, this).extend({ deferred: true }));
|
||||
@@ -180,11 +180,8 @@ export class FieldBuilder extends Disposable {
|
||||
this.diffImpl = this.autoDispose(DiffBox.create(this.field));
|
||||
}
|
||||
|
||||
// dispose.makeDisposable(FieldBuilder);
|
||||
|
||||
|
||||
public buildSelectWidgetDom() {
|
||||
return grainjsDom.maybe((use) => !use(this.isTransformingType) && use(this.readOnlyPureType), type => {
|
||||
return grainjsDom.maybe((use) => !use(this._isTransformingType) && use(this._readOnlyPureType), type => {
|
||||
const typeWidgets = getTypeDefinition(type).widgets;
|
||||
const widgetOptions = Object.keys(typeWidgets).map(label => ({
|
||||
label,
|
||||
@@ -206,32 +203,32 @@ export class FieldBuilder extends Disposable {
|
||||
* Build the type change dom.
|
||||
*/
|
||||
public buildSelectTypeDom() {
|
||||
const selectType = Computed.create(null, (use) => use(fromKo(this.readOnlyPureType)));
|
||||
selectType.onWrite(newType => newType === this.readOnlyPureType.peek() || this._setType(newType));
|
||||
const selectType = Computed.create(null, (use) => use(fromKo(this._readOnlyPureType)));
|
||||
selectType.onWrite(newType => newType === this._readOnlyPureType.peek() || this._setType(newType));
|
||||
const onDispose = () => (this.isDisposed() || selectType.set(this.field.column().pureType()));
|
||||
|
||||
return [
|
||||
cssRow(
|
||||
grainjsDom.autoDispose(selectType),
|
||||
select(selectType, this.availableTypes, {
|
||||
disabled: (use) => use(this.isTransformingFormula) || use(this.origColumn.disableModifyBase) ||
|
||||
select(selectType, this._availableTypes, {
|
||||
disabled: (use) => use(this._isTransformingFormula) || use(this.origColumn.disableModifyBase) ||
|
||||
use(this.isCallPending)
|
||||
}),
|
||||
testId('type-select')
|
||||
),
|
||||
grainjsDom.maybe((use) => use(this.isRef) && !use(this.isTransformingType), () => this._buildRefTableSelect()),
|
||||
grainjsDom.maybe(this.isTransformingType, () => {
|
||||
grainjsDom.maybe((use) => use(this._isRef) && !use(this._isTransformingType), () => this._buildRefTableSelect()),
|
||||
grainjsDom.maybe(this._isTransformingType, () => {
|
||||
// Editor dom must be built before preparing transform.
|
||||
return dom('div.type_transform_prompt',
|
||||
kf.prompt(
|
||||
dom('div',
|
||||
grainjsDom.maybe(this.isRef, () => this._buildRefTableSelect()),
|
||||
grainjsDom.maybe(this._isRef, () => this._buildRefTableSelect()),
|
||||
grainjsDom.maybe((use) => use(this.field.column().isTransforming),
|
||||
() => this.columnTransform!.buildDom())
|
||||
)
|
||||
)
|
||||
),
|
||||
grainjsDom.onDispose(onDispose)
|
||||
);
|
||||
);
|
||||
})
|
||||
];
|
||||
}
|
||||
@@ -242,7 +239,7 @@ export class FieldBuilder extends Disposable {
|
||||
// Do not type transform a new/empty column or a formula column. Just make a best guess for
|
||||
// the full type, and set it.
|
||||
const column = this.field.column();
|
||||
column.type.setAndSave(addColTypeSuffix(newType, column, this.docModel)).catch(reportError);
|
||||
column.type.setAndSave(addColTypeSuffix(newType, column, this._docModel)).catch(reportError);
|
||||
} else if (!this.columnTransform) {
|
||||
this.columnTransform = TypeTransform.create(null, this.gristDoc, this);
|
||||
return this.columnTransform.prepare(newType);
|
||||
@@ -256,7 +253,7 @@ export class FieldBuilder extends Disposable {
|
||||
// Builds the reference type table selector. Built when the column is type reference.
|
||||
public _buildRefTableSelect() {
|
||||
const allTables = Computed.create(null, (use) =>
|
||||
use(this.docModel.allTableIds.getObservable()).map(tableId => ({
|
||||
use(this._docModel.allTableIds.getObservable()).map(tableId => ({
|
||||
value: tableId,
|
||||
label: tableId,
|
||||
icon: 'FieldTable' as const
|
||||
@@ -266,7 +263,7 @@ export class FieldBuilder extends Disposable {
|
||||
cssLabel('DATA FROM TABLE'),
|
||||
cssRow(
|
||||
dom.autoDispose(allTables),
|
||||
select(fromKo(this.refTableId), allTables),
|
||||
select(fromKo(this._refTableId), allTables),
|
||||
testId('ref-table-select')
|
||||
)
|
||||
];
|
||||
@@ -301,15 +298,15 @@ export class FieldBuilder extends Disposable {
|
||||
kf.checkButton(transformButton,
|
||||
dom('span.glyphicon.glyphicon-flash'),
|
||||
dom.testId("FieldBuilder_editTransform"),
|
||||
kd.toggleClass('disabled', () => this.isTransformingType() || this.origColumn.isFormula() ||
|
||||
kd.toggleClass('disabled', () => this._isTransformingType() || this.origColumn.isFormula() ||
|
||||
this.origColumn.disableModifyBase())
|
||||
)
|
||||
)
|
||||
),
|
||||
kd.maybe(this.isTransformingFormula, () => {
|
||||
kd.maybe(this._isTransformingFormula, () => {
|
||||
return this.columnTransform!.buildDom();
|
||||
})
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -319,7 +316,7 @@ export class FieldBuilder extends Disposable {
|
||||
// NOTE: adding a grainjsDom .maybe here causes the disposable order of the widgetImpl and
|
||||
// the dom created by the widgetImpl to get out of sync.
|
||||
return dom('div',
|
||||
kd.maybe(() => !this.isTransformingType() && this.widgetImpl(), (widget: NewAbstractWidget) =>
|
||||
kd.maybe(() => !this._isTransformingType() && this.widgetImpl(), (widget: NewAbstractWidget) =>
|
||||
dom('div',
|
||||
widget.buildConfigDom(),
|
||||
widget.buildColorConfigDom(),
|
||||
@@ -401,7 +398,7 @@ export class FieldBuilder extends Disposable {
|
||||
if (this.isDisposed()) { return null; } // Work around JS errors during field removal.
|
||||
const value = row.cells[this.field.colId()];
|
||||
const cell = value && value();
|
||||
if (value && this.isRightType()(cell, this.options) || row._isAddRow.peek()) {
|
||||
if (value && this._isRightType()(cell, this.options) || row._isAddRow.peek()) {
|
||||
return this.widgetImpl();
|
||||
} else if (gristTypes.isVersions(cell)) {
|
||||
return this.diffImpl;
|
||||
@@ -462,7 +459,7 @@ export class FieldBuilder extends Disposable {
|
||||
return;
|
||||
}
|
||||
|
||||
const editorCtor = UserTypeImpl.getEditorConstructor(this.options().widget, this.readOnlyPureType());
|
||||
const editorCtor = UserTypeImpl.getEditorConstructor(this.options().widget, this._readOnlyPureType());
|
||||
// constructor may be null for a read-only non-formula field, though not today.
|
||||
if (!editorCtor) {
|
||||
// Actually, we only expect buildEditorDom() to be called when isEditorActive() is false (i.e.
|
||||
|
||||
@@ -47,10 +47,10 @@ export async function setAndSave(editRow: DataRowModel, field: ViewFieldRec, val
|
||||
}
|
||||
}
|
||||
|
||||
export type FieldEditorStateEvent = {
|
||||
position : CellPosition,
|
||||
currentState : any,
|
||||
type: string
|
||||
export interface FieldEditorStateEvent {
|
||||
position: CellPosition;
|
||||
currentState: any;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export class FieldEditor extends Disposable {
|
||||
@@ -125,7 +125,7 @@ export class FieldEditor extends Disposable {
|
||||
unmakeFormula: () => this._unmakeFormula(),
|
||||
};
|
||||
|
||||
const state : any = options.state;
|
||||
const state: any = options.state;
|
||||
|
||||
this.rebuildEditor(isFormula, editValue, Number.POSITIVE_INFINITY, state);
|
||||
|
||||
@@ -141,7 +141,7 @@ export class FieldEditor extends Disposable {
|
||||
}
|
||||
|
||||
// cursorPos refers to the position of the caret within the editor.
|
||||
public rebuildEditor(isFormula: boolean, editValue: string|undefined, cursorPos: number, state? : any) {
|
||||
public rebuildEditor(isFormula: boolean, editValue: string|undefined, cursorPos: number, state?: any) {
|
||||
const editorCtor: IEditorConstructor = isFormula ? FormulaEditor : this._editorCtor;
|
||||
|
||||
const column = this._field.column();
|
||||
@@ -168,11 +168,11 @@ export class FieldEditor extends Disposable {
|
||||
// if editor supports live changes, connect it to the change emitter
|
||||
if (editor.editorState) {
|
||||
editor.autoDispose(editor.editorState.addListener((currentState) => {
|
||||
const event : FieldEditorStateEvent = {
|
||||
position : this.cellPosition(),
|
||||
const event: FieldEditorStateEvent = {
|
||||
position: this._cellPosition(),
|
||||
currentState,
|
||||
type : this._field.column.peek().pureType.peek()
|
||||
}
|
||||
type: this._field.column.peek().pureType.peek()
|
||||
};
|
||||
this.changeEmitter.emit(event);
|
||||
}));
|
||||
}
|
||||
@@ -181,7 +181,7 @@ export class FieldEditor extends Disposable {
|
||||
}
|
||||
|
||||
// calculate current cell's absolute position
|
||||
private cellPosition() {
|
||||
private _cellPosition() {
|
||||
const rowId = this._editRow.getRowId();
|
||||
const colRef = this._field.colRef.peek();
|
||||
const sectionId = this._field.viewSection.peek().id.peek();
|
||||
@@ -189,7 +189,7 @@ export class FieldEditor extends Disposable {
|
||||
rowId,
|
||||
colRef,
|
||||
sectionId
|
||||
}
|
||||
};
|
||||
return position;
|
||||
}
|
||||
|
||||
@@ -240,11 +240,11 @@ export class FieldEditor extends Disposable {
|
||||
|
||||
// Cancels the edit
|
||||
private _cancelEdit() {
|
||||
const event : FieldEditorStateEvent = {
|
||||
position : this.cellPosition(),
|
||||
currentState : this._editorHolder.get()?.editorState?.get(),
|
||||
type : this._field.column.peek().pureType.peek()
|
||||
}
|
||||
const event: FieldEditorStateEvent = {
|
||||
position: this._cellPosition(),
|
||||
currentState: this._editorHolder.get()?.editorState?.get(),
|
||||
type: this._field.column.peek().pureType.peek()
|
||||
};
|
||||
this.cancelEmitter.emit(event);
|
||||
this.dispose();
|
||||
}
|
||||
@@ -296,11 +296,11 @@ export class FieldEditor extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
const event : FieldEditorStateEvent = {
|
||||
position : this.cellPosition(),
|
||||
currentState : this._editorHolder.get()?.editorState?.get(),
|
||||
type : this._field.column.peek().pureType.peek()
|
||||
}
|
||||
const event: FieldEditorStateEvent = {
|
||||
position: this._cellPosition(),
|
||||
currentState: this._editorHolder.get()?.editorState?.get(),
|
||||
type: this._field.column.peek().pureType.peek()
|
||||
};
|
||||
this.saveEmitter.emit(event);
|
||||
|
||||
const cursor = this._cursor;
|
||||
|
||||
@@ -13,7 +13,7 @@ import {dom, Observable} from 'grainjs';
|
||||
|
||||
export class NTextEditor extends NewBaseEditor {
|
||||
// Observable with current editor state (used by drafts or latest edit/position component)
|
||||
public readonly editorState : Observable<string>;
|
||||
public readonly editorState: Observable<string>;
|
||||
|
||||
protected cellEditorDiv: HTMLElement;
|
||||
protected textInput: HTMLTextAreaElement;
|
||||
@@ -29,7 +29,7 @@ export class NTextEditor extends NewBaseEditor {
|
||||
constructor(options: Options) {
|
||||
super(options);
|
||||
|
||||
const initialValue : string = undef(
|
||||
const initialValue: string = undef(
|
||||
options.state as string | undefined,
|
||||
options.editValue, String(options.cellValue ?? ""));
|
||||
this.editorState = Observable.create<string>(this, initialValue);
|
||||
@@ -96,10 +96,10 @@ export class NTextEditor extends NewBaseEditor {
|
||||
*/
|
||||
protected onInput() {
|
||||
// Resize the textbox whenever user types in it.
|
||||
this.resizeInput()
|
||||
this.resizeInput();
|
||||
|
||||
// notify about current state
|
||||
this.editorState.set(String(this.getTextValue()))
|
||||
this.editorState.set(String(this.getTextValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,7 @@ export interface Options {
|
||||
editValue?: string;
|
||||
cursorPos: number;
|
||||
commands: IEditorCommandGroup;
|
||||
state? : any;
|
||||
state?: any;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,7 +58,7 @@ export abstract class NewBaseEditor extends Disposable {
|
||||
/**
|
||||
* Current state of the editor. Optional, not all editors will report theirs current state.
|
||||
*/
|
||||
public editorState? : Observable<any>;
|
||||
public editorState?: Observable<any>;
|
||||
|
||||
constructor(protected options: Options) {
|
||||
super();
|
||||
|
||||
Reference in New Issue
Block a user