aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/DocComponent.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/DocComponent.tsx')
-rw-r--r--src/client/views/DocComponent.tsx97
1 files changed, 48 insertions, 49 deletions
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 9ff27d9a0..235b0dc68 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -1,44 +1,42 @@
-import { action, computed, observable } from 'mobx';
+import { action, computed, makeObservable, observable } from 'mobx';
+import * as React from 'react';
+import { returnFalse } from '../../Utils';
import { DateField } from '../../fields/DateField';
import { Doc, DocListCast, Opt } from '../../fields/Doc';
import { AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, DocData } from '../../fields/DocSymbols';
import { List } from '../../fields/List';
-import { Cast } from '../../fields/Types';
import { GetEffectiveAcl, inheritParentAcls } from '../../fields/util';
-import { returnFalse } from '../../Utils';
-import { DocUtils } from '../documents/Documents';
import { DocumentType } from '../documents/DocumentTypes';
+import { DocUtils } from '../documents/Documents';
+import { DocumentManager } from '../util/DocumentManager';
+import { ObservableReactComponent } from './ObservableReactComponent';
+import { CollectionFreeFormView } from './collections/collectionFreeForm';
import { DocumentView } from './nodes/DocumentView';
-import * as React from 'react';
/// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView)
export interface DocComponentProps {
Document: Doc;
- fieldKey?: string;
LayoutTemplate?: () => Opt<Doc>;
LayoutTemplateString?: string;
}
export function DocComponent<P extends DocComponentProps>() {
- class Component extends React.Component<React.PropsWithChildren<P>> {
- //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then
- @computed get Document() {
- return this.props.Document;
+ class Component extends ObservableReactComponent<React.PropsWithChildren<P>> {
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
}
- // This is the "The Document" -- it encapsulates, data, layout, and any templates
- @computed get rootDoc() {
- return Cast(this.props.Document.rootDocument, Doc, null) || this.props.Document;
+
+ //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then
+ get Document() {
+ return this._props.Document;
}
// This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info
@computed get layoutDoc() {
- return this.props.LayoutTemplateString ? this.props.Document : Doc.Layout(this.props.Document, this.props.LayoutTemplate?.());
+ return this._props.LayoutTemplateString ? this.Document : Doc.Layout(this.Document, this._props.LayoutTemplate?.());
}
// This is the data part of a document -- ie, the data that is constant across all views of the document
@computed get dataDoc() {
- return this.props.Document[DocData] as Doc;
- }
- // key where data is stored
- @computed get fieldKey() {
- return this.props.fieldKey;
+ return this._props.Document[DocData] as Doc;
}
}
return Component;
@@ -47,34 +45,31 @@ export function DocComponent<P extends DocComponentProps>() {
/// FieldViewBoxProps - a generic base class for field views that are not annotatable (e.g. InkingStroke, ColorBox)
interface ViewBoxBaseProps {
Document: Doc;
- DataDoc?: Doc;
+ TemplateDataDocument?: Doc;
DocumentView?: () => DocumentView;
fieldKey: string;
isSelected: () => boolean;
isContentActive: () => boolean | undefined;
renderDepth: number;
- rootSelected: () => boolean;
}
export function ViewBoxBaseComponent<P extends ViewBoxBaseProps>() {
- class Component extends React.Component<React.PropsWithChildren<P>> {
+ class Component extends ObservableReactComponent<React.PropsWithChildren<P>> {
//TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then
//@computed get Document(): T { return schemaCtor(this.props.Document); }
-
- // This is the "The Document" -- it encapsulates, data, layout, and any templates
- @computed get rootDoc() {
- return Cast(this.props.Document.rootDocument, Doc, null) || this.props.Document;
+ get Document() {
+ return this._props.Document;
}
// This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info
@computed get layoutDoc() {
- return Doc.Layout(this.props.Document);
+ return Doc.Layout(this.Document);
}
// This is the data part of a document -- ie, the data that is constant across all views of the document
@computed get dataDoc() {
- return this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : this.props.Document[DocData];
+ return this.Document.isTemplateForField || this.Document.isTemplateDoc ? this._props.TemplateDataDocument ?? this.Document[DocData] : this.Document[DocData];
}
// key where data is stored
- @computed get fieldKey() {
- return this.props.fieldKey;
+ get fieldKey() {
+ return this._props.fieldKey;
}
}
return Component;
@@ -83,41 +78,41 @@ export function ViewBoxBaseComponent<P extends ViewBoxBaseProps>() {
/// DocAnnotatbleComponent -return a base class for React views of document fields that are annotatable *and* interactive when selected (e.g., pdf, image)
export interface ViewBoxAnnotatableProps {
Document: Doc;
- DataDoc?: Doc;
+ TemplateDataDocument?: Doc;
fieldKey: string;
filterAddDocument?: (doc: Doc[]) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example)
isContentActive: () => boolean | undefined;
select: (isCtrlPressed: boolean) => void;
whenChildContentsActiveChanged: (isActive: boolean) => void;
isSelected: () => boolean;
- rootSelected: () => boolean;
renderDepth: number;
isAnnotationOverlay?: boolean;
}
export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>() {
- class Component extends React.Component<React.PropsWithChildren<P>> {
+ class Component extends ObservableReactComponent<React.PropsWithChildren<P>> {
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ }
+
@observable _annotationKeySuffix = () => 'annotations';
@observable _isAnyChildContentActive = false;
//TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then
@computed get Document() {
- return this.props.Document;
- }
- // This is the "The Document" -- it encapsulates, data, layout, and any templates
- @computed get rootDoc() {
- return Cast(this.props.Document.rootDocument, Doc, null) || this.props.Document;
+ return this._props.Document;
}
// This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info
@computed get layoutDoc() {
- return Doc.Layout(this.props.Document);
+ return Doc.Layout(this.Document);
}
// This is the data part of a document -- ie, the data that is constant across all views of the document
@computed get dataDoc() {
- return this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : this.props.Document[DocData];
+ return this.Document.isTemplateForField || this.Document.isTemplateDoc ? this._props.TemplateDataDocument ?? this.Document[DocData] : this.Document[DocData];
}
// key where data is stored
@computed get fieldKey() {
- return this.props.fieldKey;
+ return this._props.fieldKey;
}
isAnyChildContentActive = () => this._isAnyChildContentActive;
@@ -138,7 +133,7 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>()
const toRemove = value.filter(v => docs.includes(v));
if (toRemove.length !== 0) {
- const recent = this.rootDoc !== Doc.MyRecentlyClosed ? Doc.MyRecentlyClosed : undefined;
+ const recent = this.Document !== Doc.MyRecentlyClosed ? Doc.MyRecentlyClosed : undefined;
toRemove.forEach(doc => {
leavePushpin && DocUtils.LeavePushpin(doc, annotationKey ?? this.annotationKey);
Doc.RemoveDocFromList(targetDataDoc, annotationKey ?? this.annotationKey, doc);
@@ -148,7 +143,11 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>()
doc.type !== DocumentType.LOADING && Doc.AddDocToList(recent, 'data', doc, undefined, true, true);
}
});
- this.isAnyChildContentActive() && this.props.select(false);
+ if (targetDataDoc.isGroup && DocListCast(targetDataDoc[annotationKey ?? this.annotationKey]).length < 2) {
+ (DocumentManager.Instance.getFirstDocumentView(targetDataDoc)?.ComponentView as CollectionFreeFormView)?.promoteCollection();
+ } else {
+ this.isAnyChildContentActive() && this._props.select(false);
+ }
return true;
}
@@ -160,7 +159,7 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>()
// moving it into the target.
@action.bound
moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[], annotationKey?: string) => boolean, annotationKey?: string): boolean => {
- if (Doc.AreProtosEqual(this.props.Document, targetCollection)) {
+ if (Doc.AreProtosEqual(this._props.Document, targetCollection)) {
return true;
}
const first = doc instanceof Doc ? doc : doc[0];
@@ -172,10 +171,10 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>()
@action.bound
addDocument = (doc: Doc | Doc[], annotationKey?: string): boolean => {
const docs = doc instanceof Doc ? [doc] : doc;
- if (this.props.filterAddDocument?.(docs) === false || docs.find(doc => Doc.AreProtosEqual(doc, this.props.Document) && Doc.LayoutField(doc) === Doc.LayoutField(this.props.Document))) {
+ if (this._props.filterAddDocument?.(docs) === false || docs.find(doc => Doc.AreProtosEqual(doc, this.Document) && Doc.LayoutField(doc) === Doc.LayoutField(this.Document))) {
return false;
}
- const targetDataDoc = this.rootDoc[DocData];
+ const targetDataDoc = this.dataDoc;
const effectiveAcl = GetEffectiveAcl(targetDataDoc);
if (effectiveAcl === AclPrivate || effectiveAcl === AclReadonly) {
@@ -186,9 +185,9 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>()
if ([AclAugment, AclEdit, AclAdmin].includes(effectiveAcl)) {
added.forEach(doc => {
doc._dragOnlyWithinContainer = undefined;
- if (annotationKey ?? this._annotationKeySuffix()) Doc.GetProto(doc).annotationOn = this.rootDoc;
+ if (annotationKey ?? this._annotationKeySuffix()) Doc.GetProto(doc).annotationOn = this.Document;
else Doc.GetProto(doc).annotationOn = undefined;
- Doc.SetContainer(doc, this.rootDoc);
+ Doc.SetContainer(doc, this.Document);
inheritParentAcls(targetDataDoc, doc, true);
});
@@ -201,7 +200,7 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>()
return true;
};
- whenChildContentsActiveChanged = action((isActive: boolean) => this.props.whenChildContentsActiveChanged((this._isAnyChildContentActive = isActive)));
+ whenChildContentsActiveChanged = action((isActive: boolean) => this._props.whenChildContentsActiveChanged((this._isAnyChildContentActive = isActive)));
}
return Component;
}