(core) Support user variable in dropdown conditions

Summary:
Dropdown conditions can now reference a `user` variable, similar to the
one available in Access Rules.

Test Plan: Browser test.

Reviewers: jarek, paulfitz

Reviewed By: jarek, paulfitz

Differential Revision: https://phab.getgrist.com/D4255
This commit is contained in:
George Gevoian
2024-05-29 14:55:21 -07:00
parent 50077540e2
commit 72066bf0e4
27 changed files with 426 additions and 268 deletions

View File

@@ -23,6 +23,7 @@ import {Features, mergedFeatures, Product} from 'app/common/Features';
import {buildUrlId, IGristUrlState, parseUrlId, UrlIdParts} from 'app/common/gristUrls';
import {getReconnectTimeout} from 'app/common/gutil';
import {canEdit, isOwner} from 'app/common/roles';
import {UserInfo} from 'app/common/User';
import {Document, NEW_DOCUMENT_CODE, Organization, UserAPI, Workspace} from 'app/common/UserAPI';
import {Holder, Observable, subscribe} from 'grainjs';
import {Computed, Disposable, dom, DomArg, DomElementArg} from 'grainjs';
@@ -38,6 +39,7 @@ export interface DocInfo extends Document {
isPreFork: boolean;
isFork: boolean;
isRecoveryMode: boolean;
user: UserInfo|null;
userOverride: UserOverride|null;
isBareFork: boolean; // a document created without logging in, which is treated as a
// fork without an original.
@@ -78,6 +80,7 @@ export interface DocPageModel {
isPrefork: Observable<boolean>;
isFork: Observable<boolean>;
isRecoveryMode: Observable<boolean>;
user: Observable<UserInfo|null>;
userOverride: Observable<UserOverride|null>;
isBareFork: Observable<boolean>;
isSnapshot: Observable<boolean>;
@@ -134,6 +137,7 @@ export class DocPageModelImpl extends Disposable implements DocPageModel {
public readonly isFork = Computed.create(this, this.currentDoc, (use, doc) => doc ? doc.isFork : false);
public readonly isRecoveryMode = Computed.create(this, this.currentDoc,
(use, doc) => doc ? doc.isRecoveryMode : false);
public readonly user = Computed.create(this, this.currentDoc, (use, doc) => doc ? doc.user : null);
public readonly userOverride = Computed.create(this, this.currentDoc, (use, doc) => doc ? doc.userOverride : null);
public readonly isBareFork = Computed.create(this, this.currentDoc, (use, doc) => doc ? doc.isBareFork : false);
public readonly isSnapshot = Computed.create(this, this.currentDoc, (use, doc) => doc ? doc.isSnapshot : false);
@@ -265,8 +269,9 @@ export class DocPageModelImpl extends Disposable implements DocPageModel {
// TODO It would be bad if a new doc gets opened while this getDoc() is pending...
const newDoc = await getDoc(this._api, urlId);
const isRecoveryMode = Boolean(this.currentDoc.get()?.isRecoveryMode);
const user = this.currentDoc.get()?.user || null;
const userOverride = this.currentDoc.get()?.userOverride || null;
this.currentDoc.set({...buildDocInfo(newDoc, openMode), isRecoveryMode, userOverride});
this.currentDoc.set({...buildDocInfo(newDoc, openMode), isRecoveryMode, user, userOverride});
return newDoc;
}
@@ -407,11 +412,13 @@ It also disables formulas. [{{error}}]", {error: err.message})
linkParameters,
originalUrlId: options.originalUrlId,
});
if (openDocResponse.recoveryMode || openDocResponse.userOverride) {
doc.isRecoveryMode = Boolean(openDocResponse.recoveryMode);
doc.userOverride = openDocResponse.userOverride || null;
this.currentDoc.set({...doc});
const {user, recoveryMode, userOverride} = openDocResponse;
doc.user = user;
if (recoveryMode || userOverride) {
doc.isRecoveryMode = Boolean(recoveryMode);
doc.userOverride = userOverride || null;
}
this.currentDoc.set({...doc});
if (openDocResponse.docUsage) {
this.updateCurrentDocUsage(openDocResponse.docUsage);
}
@@ -520,6 +527,7 @@ function buildDocInfo(doc: Document, mode: OpenDocMode | undefined): DocInfo {
...doc,
isFork,
isRecoveryMode: false, // we don't know yet, will learn when doc is opened.
user: null, // ditto.
userOverride: null, // ditto.
isPreFork,
isBareFork,