aboutsummaryrefslogtreecommitdiff
path: root/src/fields/Doc.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/fields/Doc.ts')
-rw-r--r--src/fields/Doc.ts686
1 files changed, 217 insertions, 469 deletions
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index feacdc9c5..ff416bbe7 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1,44 +1,23 @@
-import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { saveAs } from 'file-saver';
-import { action, computed, observable, ObservableMap, ObservableSet, runInAction } from 'mobx';
+import { action, computed, makeObservable, observable, ObservableMap, ObservableSet, runInAction } from 'mobx';
import { computedFn } from 'mobx-utils';
import { alias, map, serializable } from 'serializr';
import { DocServer } from '../client/DocServer';
-import { DocumentType } from '../client/documents/DocumentTypes';
+import { CollectionViewType, DocumentType } from '../client/documents/DocumentTypes';
import { LinkManager } from '../client/util/LinkManager';
import { scriptingGlobal, ScriptingGlobals } from '../client/util/ScriptingGlobals';
import { afterDocDeserialize, autoObject, Deserializable, SerializationHelper } from '../client/util/SerializationHelper';
import { undoable } from '../client/util/UndoManager';
+import { DocumentView } from '../client/views/nodes/DocumentView';
import { decycle } from '../decycler/decycler';
import * as JSZipUtils from '../JSZipUtils';
-import { DashColor, incrementTitleCopy, intersectRect, Utils } from '../Utils';
+import { incrementTitleCopy, Utils } from '../Utils';
import { DateField } from './DateField';
import {
- AclAdmin,
- AclAugment,
- AclEdit,
- AclPrivate,
- AclReadonly,
- Animation,
- AudioPlay,
- CachedUpdates,
- DirectLinks,
- DocAcl,
- DocCss,
- DocData,
- DocFields,
- DocLayout,
- FieldKeys,
- FieldTuples,
- ForceServerWrite,
- Height,
- Highlight,
- Initializing,
- Self,
- SelfProxy,
- UpdatingFromServer,
- Width,
-} from './DocSymbols';
+ AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, Animation, AudioPlay, Brushed, CachedUpdates, DirectLinks,
+ DocAcl, DocCss, DocData, DocFields, DocLayout, DocViews, FieldKeys, FieldTuples, ForceServerWrite, Height, Highlight,
+ Initializing, Self, SelfProxy, UpdatingFromServer, Width
+} from './DocSymbols'; // prettier-ignore
import { Copy, FieldChanged, HandleUpdate, Id, Parent, ToScriptString, ToString } from './FieldSymbols';
import { InkField, InkTool } from './InkField';
import { List, ListFieldName } from './List';
@@ -50,8 +29,9 @@ import { listSpec } from './Schema';
import { ComputedField, ScriptField } from './ScriptField';
import { BoolCast, Cast, DocCast, FieldValue, NumCast, StrCast, ToConstructor } from './Types';
import { AudioField, CsvField, ImageField, PdfField, VideoField, WebField } from './URLField';
-import { containedFieldChangedHandler, deleteProperty, GetEffectiveAcl, getField, getter, makeEditable, makeReadOnly, normalizeEmail, setter, SharingPermissions, TraceMobx } from './util';
-import JSZip = require('jszip');
+import { containedFieldChangedHandler, deleteProperty, GetEffectiveAcl, getField, getter, makeEditable, makeReadOnly, setter, SharingPermissions } from './util';
+import * as JSZip from 'jszip';
+import { FieldViewProps } from '../client/views/nodes/FieldView';
export const LinkedTo = '-linkedTo';
export namespace Field {
export function toKeyValueString(doc: Doc, key: string): string {
@@ -63,25 +43,23 @@ export namespace Field {
: ''
: (onDelegate ? '=' : '') + (field instanceof ComputedField ? `:=${field.script.originalScript}` : field instanceof ScriptField ? `$=${field.script.originalScript}` : Field.toScriptString(field));
}
- export function toScriptString(field: Field): string {
+ export function toScriptString(field: Field) {
switch (typeof field) {
- case 'string':
- if (field.startsWith('{"')) return `'${field}'`; // bcz: hack ... want to quote the string the right way. if there are nested "'s, then use ' instead of ". In this case, test for the start of a JSON string of the format {"property": ... } and use outer 's instead of "s
- return !field.includes('`') ? `\`${field}\`` : `"${field}"`;
+ case 'string': if (field.startsWith('{"')) return `'${field}'`; // bcz: hack ... want to quote the string the right way. if there are nested "'s, then use ' instead of ". In this case, test for the start of a JSON string of the format {"property": ... } and use outer 's instead of "s
+ return !field.includes('`') ? `\`${field}\`` : `"${field}"`;
case 'number':
- case 'boolean':
- return String(field);
- }
- return field?.[ToScriptString]?.() ?? 'null';
+ case 'boolean':return String(field);
+ default: return field?.[ToScriptString]?.() ?? 'null';
+ } // prettier-ignore
}
- export function toString(field: Field): string {
+ export function toString(field: Field) {
if (typeof field === 'string' || typeof field === 'number' || typeof field === 'boolean') return String(field);
return field?.[ToString]?.() || '';
}
export function IsField(field: any): field is Field;
export function IsField(field: any, includeUndefined: true): field is Field | undefined;
export function IsField(field: any, includeUndefined: boolean = false): field is Field | undefined {
- return typeof field === 'string' || typeof field === 'number' || typeof field === 'boolean' || field instanceof ObjectField || field instanceof RefField || (includeUndefined && field === undefined);
+ return ['string', 'number', 'boolean'].includes(typeof field) || field instanceof ObjectField || field instanceof RefField || (includeUndefined && field === undefined);
}
export function Copy(field: any) {
return field instanceof ObjectField ? ObjectField.MakeCopy(field) : field;
@@ -104,11 +82,6 @@ export function DocListCastAsync(field: FieldResult, defaultValue?: Doc[]) {
const list = Cast(field, listSpec(Doc));
return list ? Promise.all(list).then(() => list) : Promise.resolve(defaultValue);
}
-
-export async function DocCastAsync(field: FieldResult): Promise<Opt<Doc>> {
- return Cast(field, Doc);
-}
-
export function NumListCast(field: FieldResult, defaultVal: number[] = []) {
return Cast(field, listSpec('number'), defaultVal);
}
@@ -159,142 +132,55 @@ export function updateCachedAcls(doc: Doc) {
@Deserializable('Doc', updateCachedAcls, ['id'])
export class Doc extends RefField {
@observable public static RecordingEvent = 0;
+ @observable public static GuestDashboard: Doc | undefined = undefined;
+ @observable public static GuestTarget: Doc | undefined = undefined;
+ @observable public static GuestMobile: Doc | undefined = undefined;
+ public static CurrentUserEmail: string = '';
- // this isn't really used at the moment, but is intended to indicate whether ink stroke are passed through a gesture recognizer
- static GetRecognizeGestures() {
- return BoolCast(Doc.UserDoc()._recognizeGestures);
- }
- static SetRecognizeGestures(show: boolean) {
- Doc.UserDoc()._recognizeGestures = show;
- }
-
- //
- // This controls whether fontIconButtons will display labels under their icons or not
- //
- static GetShowIconLabels() {
- return BoolCast(Doc.UserDoc()._showLabel);
- }
- static SetShowIconLabels(show: boolean) {
- Doc.UserDoc()._showLabel = show;
- }
- @observable public static CurrentlyLoading: Doc[] = []; // this assignment doesn't work. the actual assignment happens in DocumentManager's constructor
- // removes from currently loading display
- @action
- public static removeCurrentlyLoading(doc: Doc) {
- if (Doc.CurrentlyLoading) {
- const index = Doc.CurrentlyLoading.indexOf(doc);
- index !== -1 && Doc.CurrentlyLoading.splice(index, 1);
- }
- }
-
- // adds doc to currently loading display
- @action
- public static addCurrentlyLoading(doc: Doc) {
- if (Doc.CurrentlyLoading.indexOf(doc) === -1) {
- Doc.CurrentlyLoading.push(doc);
- }
- }
+ public static get MySharedDocs() { return DocCast(Doc.UserDoc().mySharedDocs); } // prettier-ignore
+ public static get MyUserDocView() { return DocCast(Doc.UserDoc().myUserDocView); } // prettier-ignore
+ public static get MyDockedBtns() { return DocCast(Doc.UserDoc().myDockedBtns); } // prettier-ignore
+ public static get MySearcher() { return DocCast(Doc.UserDoc().mySearcher); } // prettier-ignore
+ public static get MyHeaderBar() { return DocCast(Doc.UserDoc().myHeaderBar); } // prettier-ignore
+ public static get MyLeftSidebarMenu() { return DocCast(Doc.UserDoc().myLeftSidebarMenu); } // prettier-ignore
+ public static get MyLeftSidebarPanel() { return DocCast(Doc.UserDoc().myLeftSidebarPanel); } // prettier-ignore
+ public static get MyContextMenuBtns() { return DocCast(Doc.UserDoc().myContextMenuBtns); } // prettier-ignore
+ public static get MyTopBarBtns() { return DocCast(Doc.UserDoc().myTopBarBtns); } // prettier-ignore
+ public static get MyRecentlyClosed() { return DocCast(Doc.UserDoc().myRecentlyClosed); } // prettier-ignore
+ public static get MyTrails() { return DocCast(Doc.ActiveDashboard?.myTrails); } // prettier-ignore
+ public static get MyCalendars() { return DocCast(Doc.ActiveDashboard?.myCalendars); } // prettier-ignore
+ public static get MyOverlayDocs() { return DocListCast(Doc.ActiveDashboard?.myOverlayDocs ?? DocCast(Doc.UserDoc().myOverlayDocs)?.data); } // prettier-ignore
+ public static get MyPublishedDocs() { return DocListCast(Doc.ActiveDashboard?.myPublishedDocs ?? DocCast(Doc.UserDoc().myPublishedDocs)?.data); } // prettier-ignore
+ public static get MyDashboards() { return DocCast(Doc.UserDoc().myDashboards); } // prettier-ignore
+ public static get MyTemplates() { return DocCast(Doc.UserDoc().myTemplates); } // prettier-ignore
+ public static get MyImports() { return DocCast(Doc.UserDoc().myImports); } // prettier-ignore
+ public static get MyFilesystem() { return DocCast(Doc.UserDoc().myFilesystem); } // prettier-ignore
+ public static get MyTools() { return DocCast(Doc.UserDoc().myTools); } // prettier-ignore
+ public static get noviceMode() { return BoolCast(Doc.UserDoc().noviceMode); } // prettier-ignore
+ public static set noviceMode(val) { Doc.UserDoc().noviceMode = val; } // prettier-ignore
+ public static get IsSharingEnabled() { return BoolCast(Doc.UserDoc().isSharingEnabled); } // prettier-ignore
+ public static set IsSharingEnabled(val) { Doc.UserDoc().isSharingEnabled = val; } // prettier-ignore
+ public static get defaultAclPrivate() { return Doc.UserDoc().defaultAclPrivate; } // prettier-ignore
+ public static set defaultAclPrivate(val) { Doc.UserDoc().defaultAclPrivate = val; } // prettier-ignore
+ public static get ActivePage() { return StrCast(Doc.UserDoc().activePage); } // prettier-ignore
+ public static set ActivePage(val) { Doc.UserDoc().activePage = val; } // prettier-ignore
+ public static get ActiveTool(): InkTool { return StrCast(Doc.UserDoc().activeTool, InkTool.None) as InkTool; } // prettier-ignore
+ public static set ActiveTool(tool:InkTool){ Doc.UserDoc().activeTool = tool; } // prettier-ignore
+ public static get ActivePresentation() { return DocCast(Doc.ActiveDashboard?.activePresentation) as Opt<Doc>; } // prettier-ignore
+ public static set ActivePresentation(val) { Doc.ActiveDashboard && (Doc.ActiveDashboard.activePresentation = val) } // prettier-ignore
+ public static get ActiveDashboard() { return DocCast(Doc.UserDoc().activeDashboard); } // prettier-ignore
+ public static set ActiveDashboard(val: Opt<Doc>) { Doc.UserDoc().activeDashboard = val; } // prettier-ignore
+
+ public static IsInMyOverlay(doc: Doc) { return Doc.MyOverlayDocs.includes(doc); } // prettier-ignore
+ public static AddToMyOverlay(doc: Doc) { Doc.ActiveDashboard?.myOverlayDocs ? Doc.AddDocToList(Doc.ActiveDashboard, 'myOverlayDocs', doc) : Doc.AddDocToList(DocCast(Doc.UserDoc().myOverlayDocs), undefined, doc); } // prettier-ignore
+ public static RemFromMyOverlay(doc: Doc) { Doc.ActiveDashboard?.myOverlayDocs ? Doc.RemoveDocFromList(Doc.ActiveDashboard,'myOverlayDocs', doc) : Doc.RemoveDocFromList(DocCast(Doc.UserDoc().myOverlayDocs), undefined, doc); } // prettier-ignore
+ public static AddToMyPublished(doc: Doc) { Doc.ActiveDashboard?.myPublishedDocs ? Doc.AddDocToList(Doc.ActiveDashboard, 'myPublishedDocs', doc) : Doc.AddDocToList(DocCast(Doc.UserDoc().myPublishedDocs), undefined, doc); } // prettier-ignore
+ public static RemFromMyPublished(doc: Doc){ Doc.ActiveDashboard?.myPublishedDocs ? Doc.RemoveDocFromList(Doc.ActiveDashboard,'myPublishedDocs', doc) : Doc.RemoveDocFromList(DocCast(Doc.UserDoc().myPublishedDocs), undefined, doc); } // prettier-ignore
+ public static IsComicStyle(doc?: Doc) { return doc && Doc.ActiveDashboard && !Doc.IsSystem(doc) && Doc.UserDoc().renderStyle === 'comic' ; } // prettier-ignore
- @observable public static GuestDashboard: Doc | undefined;
- @observable public static GuestTarget: Doc | undefined;
- @observable public static GuestMobile: Doc | undefined;
- public static get MySharedDocs() {
- return DocCast(Doc.UserDoc().mySharedDocs);
- }
- public static get MyUserDocView() {
- return DocCast(Doc.UserDoc().myUserDocView);
- }
- public static get MyDockedBtns() {
- return DocCast(Doc.UserDoc().myDockedBtns);
- }
- public static get MySearcher() {
- return DocCast(Doc.UserDoc().mySearcher);
- }
- public static get MyHeaderBar() {
- return DocCast(Doc.UserDoc().myHeaderBar);
- }
- public static get MyLeftSidebarMenu() {
- return DocCast(Doc.UserDoc().myLeftSidebarMenu);
- }
- public static get MyLeftSidebarPanel() {
- return DocCast(Doc.UserDoc().myLeftSidebarPanel);
- }
- public static get MyContextMenuBtns() {
- return DocCast(Doc.UserDoc().myContextMenuBtns);
- }
- public static get MyTopBarBtns() {
- return DocCast(Doc.UserDoc().myTopBarBtns);
- }
- public static get MyRecentlyClosed() {
- return DocCast(Doc.UserDoc().myRecentlyClosed);
- }
- public static get MyTrails() {
- return DocCast(Doc.ActiveDashboard?.myTrails);
- }
- public static IsInMyOverlay(doc: Doc) {
- return DocListCast(Doc.MyOverlayDocs?.data).includes(doc);
- }
- public static AddToMyOverlay(doc: Doc) {
- Doc.AddDocToList(Doc.MyOverlayDocs, undefined, doc);
- }
- public static RemFromMyOverlay(doc: Doc) {
- Doc.RemoveDocFromList(Doc.MyOverlayDocs, undefined, doc);
- }
- public static get MyOverlayDocs() {
- return DocCast(Doc.UserDoc().myOverlayDocs);
- }
- public static get MyPublishedDocs() {
- return DocCast(Doc.UserDoc().myPublishedDocs);
- }
- public static get MyDashboards() {
- return DocCast(Doc.UserDoc().myDashboards);
- }
- public static get MyTemplates() {
- return DocCast(Doc.UserDoc().myTemplates);
- }
- public static get MyImports() {
- return DocCast(Doc.UserDoc().myImports);
- }
- public static get MyFilesystem() {
- return DocCast(Doc.UserDoc().myFilesystem);
- }
- public static get MyTools() {
- return DocCast(Doc.UserDoc().myTools);
- }
- public static get ActivePage() {
- return StrCast(Doc.UserDoc().activePage);
- }
- public static set ActivePage(val) {
- Doc.UserDoc().activePage = val;
- DocServer.UPDATE_SERVER_CACHE();
- }
- public static IsComicStyle(doc?: Doc) {
- return doc && Doc.ActiveDashboard && !Doc.IsSystem(doc) && Doc.UserDoc().renderStyle === 'comic';
- }
- public static get ActiveDashboard() {
- return DocCast(Doc.UserDoc().activeDashboard);
- }
- public static set ActiveDashboard(val: Doc | undefined) {
- const overlays = Cast(Doc.MyOverlayDocs.data, listSpec(Doc), null);
- overlays && (overlays.length = 0);
- Doc.UserDoc().activeDashboard = val;
- }
- public static set ActiveTool(tool: InkTool) {
- Doc.UserDoc().activeTool = tool;
- }
- public static get ActiveTool(): InkTool {
- return StrCast(Doc.UserDoc().activeTool, InkTool.None) as InkTool;
- }
- public static get ActivePresentation(): Opt<Doc> {
- return DocCast(Doc.ActiveDashboard?.activePresentation);
- }
- public static set ActivePresentation(val) {
- if (Doc.ActiveDashboard) {
- Doc.ActiveDashboard.activePresentation = val;
- }
- }
constructor(id?: FieldId, forceSave?: boolean) {
super(id);
+ makeObservable(this);
const docProxy = new Proxy<this>(this, {
set: setter,
get: getter,
@@ -302,7 +188,36 @@ export class Doc extends RefField {
has: (target, key) => GetEffectiveAcl(target) !== AclPrivate && key in target.__fieldTuples,
ownKeys: target => {
const keys = GetEffectiveAcl(target) !== AclPrivate ? Object.keys(target[FieldKeys]) : [];
- return [...keys, '__LAYOUT__'];
+ return [
+ ...keys,
+ AclAdmin,
+ AclAugment,
+ AclEdit,
+ AclPrivate,
+ AclReadonly,
+ Animation,
+ AudioPlay,
+ Brushed,
+ CachedUpdates,
+ DirectLinks,
+ DocAcl,
+ DocCss,
+ DocData,
+ DocFields,
+ DocLayout,
+ DocViews,
+ FieldKeys,
+ FieldTuples,
+ ForceServerWrite,
+ Height,
+ Highlight,
+ Initializing,
+ Self,
+ SelfProxy,
+ UpdatingFromServer,
+ Width,
+ '__LAYOUT__',
+ ];
},
getOwnPropertyDescriptor: (target, prop) => {
if (prop.toString() === '__LAYOUT__' || !(prop in target[FieldKeys])) {
@@ -351,20 +266,19 @@ export class Doc extends RefField {
@observable public [DocAcl]: { [key: string]: symbol } = {};
@observable public [DocCss]: number = 0; // incrementer denoting a change to CSS layout
@observable public [DirectLinks] = new ObservableSet<Doc>();
- @observable public [AudioPlay]: any; // meant to store sound object from Howl
- @observable public [Animation]: Opt<Doc>;
+ @observable public [AudioPlay]: any = undefined; // meant to store sound object from Howl
+ @observable public [Animation]: Opt<Doc> = undefined;
@observable public [Highlight]: boolean = false;
- static __Anim(Doc: Doc) {
- // for debugging to print AnimationSym field easily.
- return Doc[Animation];
- }
+ @observable public [Brushed]: boolean = false;
+ @observable public [DocViews] = new ObservableSet<DocumentView>();
+ private [Self] = this;
+ private [SelfProxy]: any;
private [UpdatingFromServer]: boolean = false;
private [ForceServerWrite]: boolean = false;
- public [Initializing]: boolean = false;
+ private [CachedUpdates]: { [key: string]: () => void | Promise<any> } = {};
- private [Self] = this;
- private [SelfProxy]: any;
+ public [Initializing]: boolean = false;
public [FieldChanged] = (diff: undefined | { op: '$addToSet' | '$remFromSet' | '$set'; items: Field[] | undefined; length: number | undefined; hint?: any }, serverOp: any) => {
if (!this[UpdatingFromServer] || this[ForceServerWrite]) {
DocServer.UpdateField(this[Id], serverOp);
@@ -375,9 +289,7 @@ export class Doc extends RefField {
public [Height] = () => NumCast(this[SelfProxy]._height);
public [ToScriptString] = () => `idToDoc("${this[Self][Id]}")`;
public [ToString] = () => `Doc(${GetEffectiveAcl(this[SelfProxy]) === AclPrivate ? '-inaccessible-' : this[SelfProxy].title})`;
- public get [DocLayout]() {
- return this[SelfProxy].__LAYOUT__;
- }
+ public get [DocLayout]() { return this[SelfProxy].__LAYOUT__; } // prettier-ignore
public get [DocData](): Doc {
const self = this[SelfProxy];
return self.resolvedDataDoc && !self.isTemplateForField ? self : Doc.GetProto(Cast(Doc.Layout(self).resolvedDataDoc, Doc, null) || self);
@@ -398,29 +310,6 @@ export class Doc extends RefField {
return undefined;
}
- private [CachedUpdates]: { [key: string]: () => void | Promise<any> } = {};
- public static get noviceMode() {
- return Doc.UserDoc().noviceMode as boolean;
- }
- public static set noviceMode(val) {
- Doc.UserDoc().noviceMode = val;
- }
- public static get IsSharingEnabled() {
- return Doc.UserDoc().isSharingEnabled as boolean;
- }
- public static set IsSharingEnabled(val) {
- Doc.UserDoc().isSharingEnabled = val;
- }
- public static get defaultAclPrivate() {
- return Doc.UserDoc().defaultAclPrivate;
- }
- public static set defaultAclPrivate(val) {
- Doc.UserDoc().defaultAclPrivate = val;
- }
- public static CurrentUserEmail: string = '';
- public static get CurrentUserEmailNormalized() {
- return normalizeEmail(Doc.CurrentUserEmail);
- }
public async [HandleUpdate](diff: any) {
const set = diff.$set;
const sameAuthor = this.author === Doc.CurrentUserEmail;
@@ -477,17 +366,6 @@ export class Doc extends RefField {
}
export namespace Doc {
- // export function GetAsync(doc: Doc, key: string, ignoreProto: boolean = false): Promise<Field | undefined> {
- // const self = doc[Self];
- // return new Promise(res => getField(self, key, ignoreProto, res));
- // }
- // export function GetTAsync<T extends Field>(doc: Doc, key: string, ctor: ToConstructor<T>, ignoreProto: boolean = false): Promise<T | undefined> {
- // return new Promise(async res => {
- // const field = await GetAsync(doc, key, ignoreProto);
- // return Cast(field, ctor);
- // });
- // }
-
export function SetContainer(doc: Doc, container: Doc) {
doc.embedContainer = container;
}
@@ -546,7 +424,7 @@ export namespace Doc {
//
export async function SetInPlace(doc: Doc, key: string, value: Field | undefined, defaultProto: boolean) {
if (key.startsWith('_')) key = key.substring(1);
- const hasProto = Doc.GetProto(doc) !== doc ? Doc.GetProto(doc) : undefined;
+ const hasProto = doc[DocData] !== doc ? doc[DocData] : undefined;
const onDeleg = Object.getOwnPropertyNames(doc).indexOf(key) !== -1;
const onProto = hasProto && Object.getOwnPropertyNames(hasProto).indexOf(key) !== -1;
if (onDeleg || !hasProto || (!onProto && !defaultProto)) {
@@ -621,10 +499,9 @@ export namespace Doc {
/**
* @returns the index of doc toFind in list of docs, -1 otherwise
*/
- export function IndexOf(toFind: Doc, list: Doc[], allowProtos: boolean = true) {
- let index = list.reduce((p, v, i) => (v instanceof Doc && v === toFind ? i : p), -1);
- index = allowProtos && index !== -1 ? index : list.reduce((p, v, i) => (v instanceof Doc && Doc.AreProtosEqual(v, toFind) ? i : p), -1);
- return index; // list.findIndex(doc => doc === toFind || Doc.AreProtosEqual(doc, toFind));
+ export function IndexOf(toFind: Doc, list: Doc[]) {
+ const index = list.indexOf(toFind);
+ return index !== -1 ? index : list.findIndex(doc => Doc.AreProtosEqual(doc, toFind));
}
/**
@@ -634,7 +511,7 @@ export namespace Doc {
export function RemoveDocFromList(listDoc: Doc, fieldKey: string | undefined, doc: Doc) {
const key = fieldKey ? fieldKey : Doc.LayoutFieldKey(listDoc);
if (listDoc[key] === undefined) {
- Doc.GetProto(listDoc)[key] = new List<Doc>();
+ listDoc[DocData][key] = new List<Doc>();
}
const list = Cast(listDoc[key], listSpec(Doc));
if (list) {
@@ -654,15 +531,14 @@ export namespace Doc {
export function AddDocToList(listDoc: Doc, fieldKey: string | undefined, doc: Doc, relativeTo?: Doc, before?: boolean, first?: boolean, allowDuplicates?: boolean, reversed?: boolean) {
const key = fieldKey ? fieldKey : Doc.LayoutFieldKey(listDoc);
if (listDoc[key] === undefined) {
- Doc.GetProto(listDoc)[key] = new List<Doc>();
+ listDoc[DocData][key] = new List<Doc>();
}
const list = Cast(listDoc[key], listSpec(Doc));
if (list) {
- if (allowDuplicates !== true) {
- const pind = list.reduce((l, d, i) => (d instanceof Doc && d[Id] === doc[Id] ? i : l), -1);
+ if (!allowDuplicates) {
+ const pind = list.findIndex(d => d instanceof Doc && d[Id] === doc[Id]);
if (pind !== -1) {
return true;
- //list.splice(pind, 1); // bcz: this causes schemaView docs in the Catalog to move to the bottom of the schema view when they are dragged even though they haven't left the collection
}
}
if (first) {
@@ -682,41 +558,27 @@ export namespace Doc {
return false;
}
- /**
- * Computes the bounds of the contents of a set of documents.
- */
- export function ComputeContentBounds(docList: Doc[]) {
- const bounds = docList.reduce(
- (bounds, doc) => ({
- x: Math.min(NumCast(doc.x), bounds.x),
- y: Math.min(NumCast(doc.y), bounds.y),
- r: Math.max(NumCast(doc.x) + doc[Width](), bounds.r),
- b: Math.max(NumCast(doc.y) + doc[Height](), bounds.b),
- }),
- { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: -Number.MAX_VALUE, b: -Number.MAX_VALUE }
- );
- return bounds;
- }
-
export function MakeEmbedding(doc: Doc, id?: string) {
- const embedding = !GetT(doc, 'isDataDoc', 'boolean', true) && doc.proto ? Doc.MakeCopy(doc, undefined, id) : Doc.MakeDelegate(doc, id);
+ const embedding = (!GetT(doc, 'isDataDoc', 'boolean', true) && doc.proto) || doc.type === DocumentType.CONFIG ? Doc.MakeCopy(doc, undefined, id) : Doc.MakeDelegate(doc, id);
const layout = Doc.LayoutField(embedding);
if (layout instanceof Doc && layout !== embedding && layout === Doc.Layout(embedding)) {
Doc.SetLayout(embedding, Doc.MakeEmbedding(layout));
}
embedding.createdFrom = doc;
- embedding.proto_embeddingId = Doc.GetProto(doc).proto_embeddingId = DocListCast(Doc.GetProto(doc).proto_embeddings).length - 1;
- embedding.title = ComputedField.MakeFunction(`renameEmbedding(this)`);
+ embedding.proto_embeddingId = doc[DocData].proto_embeddingId = DocListCast(doc[DocData].proto_embeddings).length - 1;
+ !Doc.GetT(embedding, 'title', 'string', true) && (embedding.title = ComputedField.MakeFunction(`renameEmbedding(this)`));
embedding.author = Doc.CurrentUserEmail;
- Doc.AddDocToList(Doc.GetProto(doc)[DocData], 'proto_embeddings', embedding);
+ Doc.AddDocToList(doc[DocData], 'proto_embeddings', embedding);
return embedding;
}
export function BestEmbedding(doc: Doc) {
- const bestEmbedding = Doc.GetProto(doc) ? [doc, ...DocListCast(doc.proto_embeddings)].find(doc => !doc.embedContainer && doc.author === Doc.CurrentUserEmail) : doc;
- bestEmbedding && Doc.AddDocToList(Doc.GetProto(doc), 'protoEmbeddings', doc);
+ const dataDoc = doc[DocData];
+ const availableEmbeddings = DocListCast(dataDoc.proto_embeddings);
+ const bestEmbedding = [...(dataDoc !== doc ? [doc] : []), ...availableEmbeddings].find(doc => !doc.embedContainer && doc.author === Doc.CurrentUserEmail);
+ bestEmbedding && Doc.AddDocToList(dataDoc, 'protoEmbeddings', doc);
return bestEmbedding ?? Doc.MakeEmbedding(doc);
}
@@ -774,7 +636,7 @@ export namespace Doc {
} else if (field instanceof RefField) {
assignKey(field);
} else if (cfield instanceof ComputedField) {
- assignKey(cfield[Copy]()); // ComputedField.MakeFunction(cfield.script.originalScript));
+ assignKey(cfield[Copy]());
} else if (field instanceof ObjectField) {
await copyObjectField(field);
} else if (field instanceof Promise) {
@@ -808,9 +670,7 @@ export namespace Doc {
const docAtKey = DocCast(clone[key]);
if (docAtKey && !Doc.IsSystem(docAtKey)) {
if (!Array.from(cloneMap.values()).includes(docAtKey)) {
- if (cloneMap.has(docAtKey[Id])) {
- clone[key] = cloneMap.get(docAtKey[Id]);
- } else clone[key] = undefined;
+ clone[key] = cloneMap.get(docAtKey[Id]);
} else {
repairClone(docAtKey, cloneMap, visited);
}
@@ -925,7 +785,7 @@ export namespace Doc {
});
}
- const _pendingMap: Map<string, boolean> = new Map();
+ const _pendingMap = new Set<string>();
//
// Returns an expanded template layout for a target data document if there is a template relationship
// between the two. If so, the layoutDoc is expanded into a new document that inherits the properties
@@ -947,23 +807,25 @@ export namespace Doc {
if (templateLayoutDoc.resolvedDataDoc instanceof Promise) {
expandedTemplateLayout = undefined;
- _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey, true);
- } else if (expandedTemplateLayout === undefined && !_pendingMap.get(targetDoc[Id] + expandedLayoutFieldKey)) {
- if (templateLayoutDoc.resolvedDataDoc === (targetDoc.rootDocument || Doc.GetProto(targetDoc))) {
+ _pendingMap.add(targetDoc[Id] + expandedLayoutFieldKey);
+ } else if (expandedTemplateLayout === undefined && !_pendingMap.has(targetDoc[Id] + expandedLayoutFieldKey)) {
+ if (templateLayoutDoc.resolvedDataDoc === (targetDoc.rootDocument ?? Doc.GetProto(targetDoc))) {
expandedTemplateLayout = templateLayoutDoc; // reuse an existing template layout if its for the same document with the same params
} else {
templateLayoutDoc.resolvedDataDoc && (templateLayoutDoc = DocCast(templateLayoutDoc.proto, templateLayoutDoc)); // if the template has already been applied (ie, a nested template), then use the template's prototype
if (!targetDoc[expandedLayoutFieldKey]) {
- _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey, true);
+ _pendingMap.add(targetDoc[Id] + expandedLayoutFieldKey);
setTimeout(
action(() => {
const newLayoutDoc = Doc.MakeDelegate(templateLayoutDoc, undefined, '[' + templateLayoutDoc.title + ']');
- newLayoutDoc.rootDocument = targetDoc;
const dataDoc = Doc.GetProto(targetDoc);
+ newLayoutDoc.rootDocument = targetDoc;
+ newLayoutDoc.embedContainer = targetDoc;
newLayoutDoc.resolvedDataDoc = dataDoc;
newLayoutDoc['acl-Guest'] = SharingPermissions.Edit;
- if (dataDoc[templateField] === undefined && templateLayoutDoc[templateField] instanceof List && (templateLayoutDoc[templateField] as any).length) {
- dataDoc[templateField] = ComputedField.MakeFunction(`ObjectField.MakeCopy(templateLayoutDoc["${templateField}"] as List)`, { templateLayoutDoc: Doc.name }, { templateLayoutDoc });
+ if (dataDoc[templateField] === undefined && (templateLayoutDoc[templateField] as any)?.length) {
+ dataDoc[templateField] = ObjectField.MakeCopy(templateLayoutDoc[templateField] as List<Doc>);
+ // ComputedField.MakeFunction(`ObjectField.MakeCopy(templateLayoutDoc["${templateField}"])`, { templateLayoutDoc: Doc.name }, { templateLayoutDoc });
}
targetDoc[expandedLayoutFieldKey] = newLayoutDoc;
@@ -987,31 +849,9 @@ export namespace Doc {
return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc), data: resolvedDataDoc };
}
- export function Overwrite(doc: Doc, overwrite: Doc, copyProto: boolean = false): Doc {
- Object.keys(doc).forEach(key => {
- const field = ProxyField.WithoutProxy(() => doc[key]);
- if (key === 'proto' && copyProto) {
- if (doc.proto instanceof Doc && overwrite.proto instanceof Doc) {
- overwrite[key] = Doc.Overwrite(doc.proto, overwrite.proto);
- }
- } else {
- if (field instanceof RefField) {
- overwrite[key] = field;
- } else if (field instanceof ObjectField) {
- overwrite[key] = ObjectField.MakeCopy(field);
- } else if (field instanceof Promise) {
- debugger; //This shouldn't happend...
- } else {
- overwrite[key] = field;
- }
- }
- });
-
- return overwrite;
- }
-
export function FindReferences(infield: Doc | List<any>, references: Set<Doc>, system: boolean | undefined) {
- if (infield instanceof List<any>) {
+ if (infield instanceof Promise) return;
+ if (!(infield instanceof Doc)) {
infield.forEach(val => (val instanceof Doc || val instanceof List) && FindReferences(val, references, system));
return;
}
@@ -1020,7 +860,7 @@ export namespace Doc {
references.add(doc);
return;
}
- const excludeLists = ['My Recently Closed', 'My Header Bar', 'My Dashboards'].includes(StrCast(doc.title));
+ const excludeLists = [Doc.MyRecentlyClosed, Doc.MyHeaderBar, Doc.MyDashboards].includes(doc);
if (system !== undefined && ((system && !Doc.IsSystem(doc)) || (!system && Doc.IsSystem(doc)))) return;
references.add(doc);
Object.keys(doc).forEach(key => {
@@ -1064,7 +904,7 @@ export namespace Doc {
}
export function MakeCopy(doc: Doc, copyProto: boolean = false, copyProtoId?: string, retitle = false): Doc {
- const copy = new Doc(copyProtoId, true);
+ const copy = runInAction(() => new Doc(copyProtoId, true));
updateCachedAcls(copy);
const exclude = [...StrListCast(doc.cloneFieldFilter), 'dragFactory_count', 'cloneFieldFilter'];
Object.keys(doc)
@@ -1097,7 +937,7 @@ export namespace Doc {
Doc.GetProto(copy).embedContainer = undefined;
Doc.GetProto(copy).proto_embeddings = new List<Doc>([copy]);
} else {
- Doc.AddDocToList(Doc.GetProto(copy)[DocData], 'proto_embeddings', copy);
+ Doc.AddDocToList(copy[DocData], 'proto_embeddings', copy);
}
copy.embedContainer = undefined;
if (retitle) {
@@ -1202,9 +1042,6 @@ export namespace Doc {
// change it to render the target metadata field instead of what it was rendering before and assign it to the template field layout document.
Doc.Layout(templateField).layout = templateFieldLayoutString.replace(/fieldKey={'[^']*'}/, `fieldKey={'${metadataFieldKey}'}`);
- // assign the template field doc a delegate of any extension document that was previously used to render the template field (since extension doc's carry rendering informatino)
- Doc.Layout(templateField)[metadataFieldKey + '_ext'] = Doc.MakeDelegate(templateField[templateFieldLayoutString?.split("'")[1] + '_ext'] as Doc);
-
return true;
}
@@ -1217,30 +1054,16 @@ export namespace Doc {
return '/doc/' + (doc ? doc[Id] : '');
}
- export function overlapping(doc1: Doc, doc2: Doc, clusterDistance: number) {
- const doc2Layout = Doc.Layout(doc2);
- const doc1Layout = Doc.Layout(doc1);
- const x2 = NumCast(doc2.x) - clusterDistance;
- const y2 = NumCast(doc2.y) - clusterDistance;
- const w2 = NumCast(doc2Layout._width) + clusterDistance;
- const h2 = NumCast(doc2Layout._height) + clusterDistance;
- const x = NumCast(doc1.x) - clusterDistance;
- const y = NumCast(doc1.y) - clusterDistance;
- const w = NumCast(doc1Layout._width) + clusterDistance;
- const h = NumCast(doc1Layout._height) + clusterDistance;
- return doc1.z === doc2.z && intersectRect({ left: x, top: y, width: w, height: h }, { left: x2, top: y2, width: w2, height: h2 });
- }
-
- export function isBrushedHighlightedDegree(doc: Doc) {
- return Doc.IsHighlighted(doc) ? DocBrushStatus.highlighted : Doc.IsBrushedDegree(doc);
- }
- export function isBrushedHighlightedDegreeUnmemoized(doc: Doc) {
- return Doc.IsHighlighted(doc) ? DocBrushStatus.highlighted : Doc.IsBrushedDegreeUnmemoized(doc);
+ export function GetBrushHighlightStatus(doc: Doc) {
+ return Doc.IsHighlighted(doc) ? DocBrushStatus.highlighted : Doc.GetBrushStatus(doc);
}
-
export class DocBrush {
- BrushedDoc: ObservableMap<Doc, boolean> = new ObservableMap();
+ BrushedDoc = new Set<Doc>();
SearchMatchDoc: ObservableMap<Doc, { searchMatch: number }> = new ObservableMap();
+ brushDoc = action((doc: Doc, unbrush: boolean) => {
+ unbrush ? this.BrushedDoc.delete(doc) : this.BrushedDoc.add(doc);
+ doc[Brushed] = !unbrush;
+ });
}
export const brushManager = new DocBrush();
@@ -1262,26 +1085,26 @@ export namespace Doc {
export function LayoutField(doc: Doc) {
return doc[StrCast(doc.layout_fieldKey, 'layout')];
}
- export function LayoutFieldKey(doc: Doc): string {
- return StrCast(Doc.Layout(doc).layout).split("'")[1]; // bcz: TODO check on this . used to always reference 'layout', now it uses the layout speicfied by the current layout_fieldKey
+ export function LayoutFieldKey(doc: Doc, templateLayoutString?: string): string {
+ return StrCast(templateLayoutString || Doc.Layout(doc).layout).split("'")[1]; // bcz: TODO check on this . used to always reference 'layout', now it uses the layout speicfied by the current layout_fieldKey
}
export function NativeAspect(doc: Doc, dataDoc?: Doc, useDim?: boolean) {
return Doc.NativeWidth(doc, dataDoc, useDim) / (Doc.NativeHeight(doc, dataDoc, useDim) || 1);
}
export function NativeWidth(doc?: Doc, dataDoc?: Doc, useWidth?: boolean) {
- return !doc ? 0 : NumCast(doc._nativeWidth, NumCast((dataDoc || doc)[Doc.LayoutFieldKey(doc) + '_nativeWidth'], useWidth ? doc[Width]() : 0));
+ return !doc ? 0 : NumCast(doc._nativeWidth, NumCast((dataDoc || doc)[Doc.LayoutFieldKey(doc) + '_nativeWidth'], useWidth ? NumCast(doc._width) : 0));
}
export function NativeHeight(doc?: Doc, dataDoc?: Doc, useHeight?: boolean) {
if (!doc) return 0;
- const nheight = (Doc.NativeWidth(doc, dataDoc, useHeight) * doc[Height]()) / doc[Width]();
- const dheight = NumCast((dataDoc || doc)[Doc.LayoutFieldKey(doc) + '_nativeHeight'], useHeight ? doc[Height]() : 0);
+ const nheight = (Doc.NativeWidth(doc, dataDoc, useHeight) / NumCast(doc._width)) * NumCast(doc._height); // divide before multiply to avoid floating point errrorin case nativewidth = width
+ const dheight = NumCast((dataDoc || doc)[Doc.LayoutFieldKey(doc) + '_nativeHeight'], useHeight ? NumCast(doc._height) : 0);
return NumCast(doc._nativeHeight, nheight || dheight);
}
export function SetNativeWidth(doc: Doc, width: number | undefined, fieldKey?: string) {
- doc[(fieldKey ?? Doc.LayoutFieldKey(doc)) + '_nativeWidth'] = width;
+ doc[(fieldKey || Doc.LayoutFieldKey(doc)) + '_nativeWidth'] = width;
}
export function SetNativeHeight(doc: Doc, height: number | undefined, fieldKey?: string) {
- doc[(fieldKey ?? Doc.LayoutFieldKey(doc)) + '_nativeHeight'] = height;
+ doc[(fieldKey || Doc.LayoutFieldKey(doc)) + '_nativeHeight'] = height;
}
const manager = new UserDocData();
@@ -1305,22 +1128,22 @@ export namespace Doc {
}
const isSearchMatchCache = computedFn(function IsSearchMatch(doc: Doc) {
- return brushManager.SearchMatchDoc.has(doc) ? brushManager.SearchMatchDoc.get(doc) : brushManager.SearchMatchDoc.has(Doc.GetProto(doc)) ? brushManager.SearchMatchDoc.get(Doc.GetProto(doc)) : undefined;
+ return brushManager.SearchMatchDoc.has(doc) ? brushManager.SearchMatchDoc.get(doc) : brushManager.SearchMatchDoc.has(doc[DocData]) ? brushManager.SearchMatchDoc.get(doc[DocData]) : undefined;
});
export function IsSearchMatch(doc: Doc) {
return isSearchMatchCache(doc);
}
export function IsSearchMatchUnmemoized(doc: Doc) {
- return brushManager.SearchMatchDoc.has(doc) ? brushManager.SearchMatchDoc.get(doc) : brushManager.SearchMatchDoc.has(Doc.GetProto(doc)) ? brushManager.SearchMatchDoc.get(Doc.GetProto(doc)) : undefined;
+ return brushManager.SearchMatchDoc.has(doc) ? brushManager.SearchMatchDoc.get(doc) : brushManager.SearchMatchDoc.has(doc[DocData]) ? brushManager.SearchMatchDoc.get(doc[DocData]) : undefined;
}
export function SetSearchMatch(doc: Doc, results: { searchMatch: number }) {
- if (doc && GetEffectiveAcl(doc) !== AclPrivate && GetEffectiveAcl(Doc.GetProto(doc)) !== AclPrivate) {
+ if (doc && GetEffectiveAcl(doc) !== AclPrivate && GetEffectiveAcl(doc[DocData]) !== AclPrivate) {
brushManager.SearchMatchDoc.set(doc, results);
}
return doc;
}
export function SearchMatchNext(doc: Doc, backward: boolean) {
- if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc;
+ if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(doc[DocData]) === AclPrivate) return doc;
const result = brushManager.SearchMatchDoc.get(doc);
const num = Math.abs(result?.searchMatch || 0) + 1;
runInAction(() => result && brushManager.SearchMatchDoc.set(doc, { searchMatch: backward ? -num : num }));
@@ -1330,63 +1153,29 @@ export namespace Doc {
brushManager.SearchMatchDoc.clear();
}
- const isBrushedCache = computedFn(function IsBrushed(doc: Doc) {
- return brushManager.BrushedDoc.has(doc) || brushManager.BrushedDoc.has(Doc.GetProto(doc));
- });
- export function IsBrushed(doc: Doc) {
- return isBrushedCache(doc);
- }
-
export enum DocBrushStatus {
unbrushed = 0,
protoBrushed = 1,
selfBrushed = 2,
highlighted = 3,
}
- // don't bother memoizing (caching) the result if called from a non-reactive context. (plus this avoids a warning message)
- export function IsBrushedDegreeUnmemoized(doc: Doc) {
- if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate || doc.opacity === 0) return DocBrushStatus.unbrushed;
- const status = brushManager.BrushedDoc.has(doc) ? DocBrushStatus.selfBrushed : brushManager.BrushedDoc.has(Doc.GetProto(doc)) ? DocBrushStatus.protoBrushed : DocBrushStatus.unbrushed;
- return status;
- }
- export function IsBrushedDegree(doc: Doc) {
- return computedFn(function IsBrushDegree(doc: Doc) {
- return Doc.IsBrushedDegreeUnmemoized(doc);
- })(doc);
+ // returns 'how' a Doc has been brushed over - whether the document itself was brushed, it's prototype, or neither
+ export function GetBrushStatus(doc: Doc) {
+ if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(doc[DocData]) === AclPrivate || doc.opacity === 0) return DocBrushStatus.unbrushed;
+ return doc[Brushed] ? DocBrushStatus.selfBrushed : doc[DocData][Brushed] ? DocBrushStatus.protoBrushed : DocBrushStatus.unbrushed;
}
- export function BrushDoc(doc: Doc) {
- if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc;
- runInAction(() => {
- brushManager.BrushedDoc.set(doc, true);
- brushManager.BrushedDoc.set(Doc.GetProto(doc), true);
- });
+ export function BrushDoc(doc: Doc, unbrush = false) {
+ if (doc && GetEffectiveAcl(doc) !== AclPrivate && GetEffectiveAcl(doc[DocData]) !== AclPrivate) {
+ brushManager.brushDoc(doc, unbrush);
+ brushManager.brushDoc(doc[DocData], unbrush);
+ }
return doc;
}
export function UnBrushDoc(doc: Doc) {
- if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc;
- runInAction(() => {
- brushManager.BrushedDoc.delete(doc);
- brushManager.BrushedDoc.delete(Doc.GetProto(doc));
- });
- return doc;
+ return BrushDoc(doc, true);
}
-
- export function LinkEndpoint(linkDoc: Doc, anchorDoc: Doc) {
- const linkAnchor2 = DocCast(linkDoc.link_anchor_2);
- const linkAnchor1 = DocCast(linkDoc.link_anchor_1);
- if (linkDoc.link_matchEmbeddings) {
- return [linkAnchor2, linkAnchor2.annotationOn].includes(anchorDoc) ? '2' : '1';
- }
- if (Doc.AreProtosEqual(linkAnchor2, anchorDoc) || Doc.AreProtosEqual(linkAnchor2.annotationOn as Doc, anchorDoc)) return '2';
- return Doc.AreProtosEqual(linkAnchor1, anchorDoc) || Doc.AreProtosEqual(linkAnchor1.annotationOn as Doc, anchorDoc) ? '1' : '2';
- }
-
- export function linkFollowUnhighlight() {
- clearTimeout(UnhighlightTimer);
- UnhighlightWatchers.forEach(watcher => watcher());
- UnhighlightWatchers.length = 0;
- highlightedDocs.forEach(doc => Doc.UnHighlightDoc(doc));
- document.removeEventListener('pointerdown', linkFollowUnhighlight);
+ export function UnBrushAllDocs() {
+ Array.from(brushManager.BrushedDoc).forEach(action(doc => (doc[Brushed] = false)));
}
let UnhighlightWatchers: (() => void)[] = [];
@@ -1396,6 +1185,14 @@ export namespace Doc {
UnhighlightWatchers.push(watcher);
} else watcher();
}
+ export function linkFollowUnhighlight() {
+ clearTimeout(UnhighlightTimer);
+ UnhighlightTimer = 0;
+ UnhighlightWatchers.forEach(watcher => watcher());
+ UnhighlightWatchers.length = 0;
+ highlightedDocs.forEach(doc => Doc.UnHighlightDoc(doc));
+ document.removeEventListener('pointerdown', linkFollowUnhighlight);
+ }
export function linkFollowHighlight(destDoc: Doc | Doc[], dataAndDisplayDocs = true, presentation_effect?: Doc) {
linkFollowUnhighlight();
(destDoc instanceof Doc ? [destDoc] : destDoc).forEach(doc => Doc.HighlightDoc(doc, dataAndDisplayDocs, presentation_effect));
@@ -1410,8 +1207,8 @@ export namespace Doc {
export var highlightedDocs = new ObservableSet<Doc>();
export function IsHighlighted(doc: Doc) {
- if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate || doc.opacity === 0) return false;
- return doc[Highlight] || Doc.GetProto(doc)[Highlight];
+ if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(doc[DocData]) === AclPrivate || doc.opacity === 0) return false;
+ return doc[Highlight] || doc[DocData][Highlight];
}
export function HighlightDoc(doc: Doc, dataAndDisplayDocs = true, presentation_effect?: Doc) {
runInAction(() => {
@@ -1419,8 +1216,8 @@ export namespace Doc {
doc[Highlight] = true;
doc[Animation] = presentation_effect;
if (dataAndDisplayDocs) {
- highlightedDocs.add(Doc.GetProto(doc));
- Doc.GetProto(doc)[Highlight] = true;
+ highlightedDocs.add(doc[DocData]);
+ doc[DocData][Highlight] = true;
}
});
}
@@ -1429,65 +1226,30 @@ export namespace Doc {
runInAction(() => {
(doc ? [doc] : Array.from(highlightedDocs)).forEach(doc => {
highlightedDocs.delete(doc);
- highlightedDocs.delete(Doc.GetProto(doc));
- doc[Highlight] = Doc.GetProto(doc)[Highlight] = false;
+ highlightedDocs.delete(doc[DocData]);
+ doc[Highlight] = doc[DocData][Highlight] = false;
doc[Animation] = undefined;
});
});
}
- export function UnBrushAllDocs() {
- runInAction(() => brushManager.BrushedDoc.clear());
- }
export function getDocTemplate(doc?: Doc) {
return !doc
? undefined
: doc.isTemplateDoc
- ? doc
- : Cast(doc.dragFactory, Doc, null)?.isTemplateDoc
- ? doc.dragFactory
- : Cast(Doc.Layout(doc), Doc, null)?.isTemplateDoc
- ? Cast(Doc.Layout(doc), Doc, null).resolvedDataDoc
- ? Doc.Layout(doc).proto
- : Doc.Layout(doc)
- : undefined;
- }
-
- export function matchFieldValue(doc: Doc, key: string, value: any): boolean {
- if (Utils.HasTransparencyFilter(value)) {
- const isTransparent = (color: string) => color !== '' && DashColor(color).alpha() !== 1;
- return isTransparent(StrCast(doc[key]));
- }
- if (key === LinkedTo) {
- // links are not a field value, so handled here. value is an expression of form ([field=]idToDoc("..."))
- const allLinks = LinkManager.Instance.getAllRelatedLinks(doc);
- const matchLink = (value: string, anchor: Doc) => {
- const linkedToExp = value?.split('=');
- if (linkedToExp.length === 1) return Field.toScriptString(anchor) === value;
- return Field.toScriptString(DocCast(anchor[linkedToExp[0]])) === linkedToExp[1];
- };
- // prettier-ignore
- return (value === Doc.FilterNone && !allLinks.length) ||
- (value === Doc.FilterAny && !!allLinks.length) ||
- (allLinks.some(link => matchLink(value,DocCast(link.link_anchor_1)) ||
- matchLink(value,DocCast(link.link_anchor_2)) ));
- }
- if (typeof value === 'string') {
- value = value.replace(`,${Utils.noRecursionHack}`, '');
- }
- const fieldVal = doc[key];
- // prettier-ignore
- if ((value === Doc.FilterAny && fieldVal !== undefined) ||
- (value === Doc.FilterNone && fieldVal === undefined)) {
- return true;
- }
- if (Cast(fieldVal, listSpec('string'), []).length) {
- const vals = StrListCast(fieldVal);
- const docs = vals.some(v => (v as any) instanceof Doc);
- if (docs) return value === Field.toString(fieldVal as Field);
- return vals.some(v => v.includes(value)); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring
- }
- return Field.toString(fieldVal as Field).includes(value); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring
+ ? doc
+ : Cast(doc.dragFactory, Doc, null)?.isTemplateDoc
+ ? doc.dragFactory
+ : Cast(Doc.Layout(doc), Doc, null)?.isTemplateDoc
+ ? Cast(Doc.Layout(doc), Doc, null).resolvedDataDoc
+ ? Doc.Layout(doc).proto
+ : Doc.Layout(doc)
+ : undefined;
+ }
+
+ export function toggleLockedPosition(doc: Doc) {
+ doc._lockedPosition = !doc._lockedPosition;
+ doc._pointerEvents = doc._lockedPosition ? 'none' : undefined;
}
export function deiconifyView(doc: Doc) {
@@ -1501,34 +1263,27 @@ export namespace Doc {
doc.layout_fieldKey = deiconify || 'layout';
}
export function setDocRangeFilter(container: Opt<Doc>, key: string, range?: readonly number[], modifiers?: 'remove') {
- //, modifiers: 'remove' | 'set'
if (!container) return;
const childFiltersByRanges = Cast(container._childFiltersByRanges, listSpec('string'), []);
for (let i = 0; i < childFiltersByRanges.length; i += 3) {
if (childFiltersByRanges[i] === key) {
- console.log('this is key inside childfilters by range ' + key);
childFiltersByRanges.splice(i, 3);
- console.log('this is child filters by range ' + childFiltersByRanges);
break;
}
}
if (range !== undefined) {
- console.log('in doc.ts in set range filter');
childFiltersByRanges.push(key);
childFiltersByRanges.push(range[0].toString());
childFiltersByRanges.push(range[1].toString());
container._childFiltersByRanges = new List<string>(childFiltersByRanges);
- console.log('this is child filters by range ' + childFiltersByRanges[0] + ',' + childFiltersByRanges[1] + ',' + childFiltersByRanges[2]);
- console.log('this is new list ' + container._childFiltersByRange);
}
if (modifiers) {
childFiltersByRanges.splice(0, 3);
container._childFiltersByRanges = new List<string>(childFiltersByRanges);
}
- console.log('this is child filters by range END' + childFiltersByRanges[0] + ',' + childFiltersByRanges[1] + ',' + childFiltersByRanges[2]);
}
export const FilterSep = '::';
@@ -1583,37 +1338,25 @@ export namespace Doc {
layoutDoc._freeform_scale = NumCast(layoutDoc._freeform_scale, 1) * contentScale;
layoutDoc._nativeWidth = undefined;
layoutDoc._nativeHeight = undefined;
- layoutDoc._layout_forceReflow = undefined;
- layoutDoc._nativeHeightUnfrozen = undefined;
- layoutDoc._nativeDimModifiable = undefined;
} else {
layoutDoc._layout_autoHeight = false;
if (!Doc.NativeWidth(layoutDoc)) {
layoutDoc._nativeWidth = NumCast(layoutDoc._width, panelWidth);
layoutDoc._nativeHeight = NumCast(layoutDoc._height, panelHeight);
- layoutDoc._layout_forceReflow = true;
- layoutDoc._nativeHeightUnfrozen = true;
- layoutDoc._nativeDimModifiable = true;
}
}
});
}
- export function isDocPinned(doc: Doc) {
- //add this new doc to props.Document
- const curPres = Doc.ActivePresentation;
- return !curPres ? false : DocListCast(curPres.data).findIndex(val => Doc.AreProtosEqual(val, doc)) !== -1;
- }
-
- export function styleFromLayoutString(rootDoc: Doc, layoutDoc: Doc, props: any, scale: number) {
+ export function styleFromLayoutString(doc: Doc, props: FieldViewProps, scale: number) {
const style: { [key: string]: any } = {};
const divKeys = ['width', 'height', 'fontSize', 'transform', 'left', 'backgroundColor', 'left', 'right', 'top', 'bottom', 'pointerEvents', 'position'];
const replacer = (match: any, expr: string, offset: any, string: any) => {
// bcz: this executes a script to convert a property expression string: { script } into a value
- return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name, scale: 'number' })?.script.run({ self: rootDoc, this: layoutDoc, scale }).result?.toString() ?? '';
+ return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name, scale: 'number' })?.script.run({ this: doc, self: doc, scale }).result?.toString() ?? '';
};
divKeys.map((prop: string) => {
- const p = props[prop];
+ const p = (props as any)[prop];
typeof p === 'string' && (style[prop] = p?.replace(/{([^.'][^}']+)}/g, replacer));
});
return style;
@@ -1628,7 +1371,7 @@ export namespace Doc {
if (ptx !== undefined && pty !== undefined && newPoint !== undefined) {
const firstx = list.length ? NumCast(list[0].x) + ptx - newPoint[0] : 0;
const firsty = list.length ? NumCast(list[0].y) + pty - newPoint[1] : 0;
- docs.map(doc => {
+ docs.forEach(doc => {
doc.x = NumCast(doc.x) - firstx;
doc.y = NumCast(doc.y) - firsty;
});
@@ -1638,15 +1381,25 @@ export namespace Doc {
}
// prettier-ignore
- export function toIcon(doc?: Doc, isOpen?: boolean) {
- switch (isOpen !== undefined ? DocumentType.COL: StrCast(doc?.type)) {
+ export function toIcon(doc?: Doc, isOpen?: Opt<boolean>) {
+ if (isOpen) return doc?.isFolder ? 'chevron-down' : 'folder-open';
+ switch (StrCast(doc?.type)) {
case DocumentType.IMG: return 'image';
case DocumentType.COMPARISON: return 'columns';
case DocumentType.RTF: return 'sticky-note';
case DocumentType.COL:
- const folder: IconProp = isOpen === true ? 'folder-open' : isOpen === false ? 'folder' : doc?.title==='Untitled Collection'? 'object-group': 'chalkboard';
- const chevron: IconProp = isOpen === true ? 'chevron-down' : isOpen === false ? 'chevron-right' : 'question';
- return !doc?.isFolder ? folder : chevron;
+ if (doc?.isFolder) {
+ switch (doc.type_collection) {
+ default: return isOpen === false ? 'chevron-right' : 'question';
+ } // prettier-ignore
+ }
+ switch (doc?.type_collection) {
+ case CollectionViewType.Freeform : return 'object-group';
+ case CollectionViewType.NoteTaking : return 'chalkboard';
+ case CollectionViewType.Schema : return 'table-cells';
+ case CollectionViewType.Docking: return 'solar-panel';
+ default: return 'folder';
+ } // prettier-ignore
case DocumentType.WEB: return 'globe-asia';
case DocumentType.SCREENSHOT: return 'photo-video';
case DocumentType.WEBCAM: return 'video';
@@ -1663,9 +1416,9 @@ export namespace Doc {
case DocumentType.DATAVIZ: return 'chart-bar';
case DocumentType.EQUATION: return 'calculator';
case DocumentType.SIMULATION: return 'rocket';
- case DocumentType.CONFIG: return 'question-circle';
- default: return 'question';
+ case DocumentType.CONFIG: return 'folder-closed';
}
+ return 'question';
}
///
@@ -1842,7 +1595,7 @@ ScriptingGlobals.add(function idToDoc(id: string): any {
return IdToDoc(id);
});
ScriptingGlobals.add(function renameEmbedding(doc: any) {
- return StrCast(Doc.GetProto(doc).title).replace(/\([0-9]*\)/, '') + `(${doc.proto_embeddingId})`;
+ return StrCast(doc[DocData].title).replace(/\([0-9]*\)/, '') + `(${doc.proto_embeddingId})`;
});
ScriptingGlobals.add(function getProto(doc: any) {
return Doc.GetProto(doc);
@@ -1871,21 +1624,16 @@ ScriptingGlobals.add(function setInPlace(doc: any, field: any, value: any) {
ScriptingGlobals.add(function sameDocs(doc1: any, doc2: any) {
return Doc.AreProtosEqual(doc1, doc2);
});
-ScriptingGlobals.add(function DOC(id: string) {
- console.log("Can't parse a document id in a script");
- return 'invalid';
-});
ScriptingGlobals.add(function assignDoc(doc: Doc, field: string, id: string) {
return Doc.assignDocToField(doc, field, id);
});
-ScriptingGlobals.add(function docCast(doc: FieldResult): any {
- return DocCastAsync(doc);
+ScriptingGlobals.add(function docCastAsync(doc: FieldResult): any {
+ return Cast(doc, Doc);
});
ScriptingGlobals.add(function activePresentationItem() {
const curPres = Doc.ActivePresentation;
return curPres && DocListCast(curPres[Doc.LayoutFieldKey(curPres)])[NumCast(curPres._itemIndex)];
});
-
ScriptingGlobals.add(function setDocFilter(container: Doc, key: string, value: any, modifiers: 'match' | 'check' | 'x' | 'remove') {
Doc.setDocFilter(container, key, value, modifiers);
});