aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-03-06 09:44:38 -0500
committerbobzel <zzzman@gmail.com>2024-03-06 09:44:38 -0500
commit43770615603c9d0f0aa19a3a676822737157c161 (patch)
tree0ec0a991884e28a1f453872c256c5f4548dc7ad5 /src
parent11b6cb8344f26e5895bebc3dedef491675717e30 (diff)
enabled copy and paste to work with template docs (and not copy template). Fixed tempaltes of collections to allow new nodes to be added/removed.
Diffstat (limited to 'src')
-rw-r--r--src/client/views/DocComponent.tsx8
-rw-r--r--src/client/views/TemplateMenu.tsx9
-rw-r--r--src/client/views/nodes/ScriptingBox.tsx32
-rw-r--r--src/fields/Doc.ts52
4 files changed, 60 insertions, 41 deletions
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 2a527eca1..a25a8f77a 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -182,7 +182,7 @@ export function ViewBoxAnnotatableComponent<P extends FieldViewProps>() {
const docs = indocs.filter(doc => [AclEdit, AclAdmin].includes(effectiveAcl) || GetEffectiveAcl(doc) === AclAdmin);
// docs.forEach(doc => doc.annotationOn === this.Document && Doc.SetInPlace(doc, 'annotationOn', undefined, true));
- const targetDataDoc = this.dataDoc;
+ const targetDataDoc = this.Document[DocData]; // this.dataDoc; // we want to write to the template, not the actual data doc
const value = DocListCast(targetDataDoc[annotationKey ?? this.annotationKey]);
const toRemove = value.filter(v => docs.includes(v));
@@ -228,7 +228,7 @@ export function ViewBoxAnnotatableComponent<P extends FieldViewProps>() {
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.dataDoc;
+ const targetDataDoc = this.Document[DocData]; // this.dataDoc; // we want to write to the template, not the actual data doc
const effectiveAcl = GetEffectiveAcl(targetDataDoc);
if (effectiveAcl === AclPrivate || effectiveAcl === AclReadonly) {
@@ -245,9 +245,9 @@ export function ViewBoxAnnotatableComponent<P extends FieldViewProps>() {
inheritParentAcls(targetDataDoc, doc, true);
});
- const annoDocs = Doc.Get(targetDataDoc, annotationKey ?? this.annotationKey, true) as List<Doc>; // get the dataDoc directly ... when using templates there may be some default items already there, but we can't change them. maybe we should copy them over, though...
+ const annoDocs = Doc.Get(targetDataDoc, annotationKey ?? this.annotationKey, true) as List<Doc>; // get the dataDoc directly ... when using templates there may be some default items already there, but we can't change them, so we copy them below (should really be some kind of inheritance since the template contents could change)
if (annoDocs instanceof List) annoDocs.push(...added.filter(add => !annoDocs.includes(add)));
- else targetDataDoc[annotationKey ?? this.annotationKey] = new List<Doc>(added);
+ else targetDataDoc[annotationKey ?? this.annotationKey] = new List<Doc>([...added, ...(annoDocs === undefined ? DocListCast(targetDataDoc[annotationKey ?? this.annotationKey]) : [])]);
targetDataDoc[(annotationKey ?? this.annotationKey) + '_modificationDate'] = new DateField();
}
}
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index f7729dbc7..5d9abb460 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -3,7 +3,7 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, DocListCast } from '../../fields/Doc';
import { ScriptField } from '../../fields/ScriptField';
-import { Cast, StrCast } from '../../fields/Types';
+import { Cast, DocCast, StrCast } from '../../fields/Types';
import { TraceMobx } from '../../fields/util';
import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../Utils';
import { Docs, DocUtils } from '../documents/Documents';
@@ -81,8 +81,11 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
componentDidMount() {
!this._addedKeys && (this._addedKeys = new ObservableSet());
[...Array.from(Object.keys(this.props.docViews[0].Document[DocData])), ...Array.from(Object.keys(this.props.docViews[0].Document))]
- .filter(key => key.startsWith('layout_') && key !== 'layout_fieldKey')
- .map(key => runInAction(() => this._addedKeys.add(key.replace('layout_', ''))));
+ .filter(key => key.startsWith('layout_') && (
+ StrCast(this.props.docViews[0].Document[key]).startsWith("<") ||
+ DocCast(this.props.docViews[0].Document[key])?.isTemplateDoc
+ ))
+ .map(key => runInAction(() => this._addedKeys.add(key.replace('layout_', '')))); // prettier-ignore
}
return100 = () => 300;
diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx
index 89650889d..d9d0dbe3e 100644
--- a/src/client/views/nodes/ScriptingBox.tsx
+++ b/src/client/views/nodes/ScriptingBox.tsx
@@ -130,7 +130,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
}
})
);
- observer.observe(document.getElementsByClassName('scriptingBox')[0]);
+ observer.observe(document.getElementsByClassName('scriptingBox-outerDiv')[0]);
}
@action
@@ -811,22 +811,20 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
render() {
TraceMobx();
return (
- <div className={`scriptingBox`} onContextMenu={this.specificContextMenu} onPointerUp={!this._function ? this.suggestionPos : undefined}>
- <div className="scriptingBox-outerDiv" onWheel={e => this._props.isSelected() && e.stopPropagation()}>
- {this._paramSuggestion ? (
- <div className="boxed" ref={this._suggestionRef} style={{ left: this._suggestionBoxX + 20, top: this._suggestionBoxY - 15, display: 'inline' }}>
- {' '}
- {this._scriptSuggestedParams}{' '}
- </div>
- ) : null}
- {!this._applied && !this._function ? this.renderScriptingInputs : null}
- {this._applied && !this._function ? this.renderParamsInputs() : null}
- {!this._applied && this._function ? this.renderFunctionInputs() : null}
-
- {!this._applied && !this._function ? this.renderScriptingTools() : null}
- {this._applied && !this._function ? this.renderTools('Run', () => this.onRun()) : null}
- {!this._applied && this._function ? this.renderTools('Create Function', () => this.onCreate()) : null}
- </div>
+ <div className="scriptingBox-outerDiv" onContextMenu={this.specificContextMenu} onPointerUp={!this._function ? this.suggestionPos : undefined} onWheel={e => this._props.isSelected() && e.stopPropagation()}>
+ {this._paramSuggestion ? (
+ <div className="boxed" ref={this._suggestionRef} style={{ left: this._suggestionBoxX + 20, top: this._suggestionBoxY - 15, display: 'inline' }}>
+ {' '}
+ {this._scriptSuggestedParams}{' '}
+ </div>
+ ) : null}
+ {!this._applied && !this._function ? this.renderScriptingInputs : null}
+ {this._applied && !this._function ? this.renderParamsInputs() : null}
+ {!this._applied && this._function ? this.renderFunctionInputs() : null}
+
+ {!this._applied && !this._function ? this.renderScriptingTools() : null}
+ {this._applied && !this._function ? this.renderTools('Run', () => this.onRun()) : null}
+ {!this._applied && this._function ? this.renderTools('Create Function', () => this.onCreate()) : null}
</div>
);
}
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index b1bdd50a7..1df9d80a1 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -614,8 +614,19 @@ export namespace Doc {
// this lists out all the tag ids that can be in a RichTextField that might contain document ids.
// if a document is cloned, we need to make sure to clone all of these referenced documents as well;
export const DocsInTextFieldIds = ['audioId', 'textId', 'anchorId', 'docId'];
- export async function makeClone(doc: Doc, cloneMap: Map<string, Doc>, linkMap: Map<string, Doc>, rtfs: { copy: Doc; key: string; field: RichTextField }[], exclusions: string[], pruneDocs: Doc[], cloneLinks: boolean): Promise<Doc> {
- if (Doc.IsBaseProto(doc)) return doc;
+ export async function makeClone(
+ doc: Doc,
+ cloneMap: Map<string, Doc>,
+ linkMap: Map<string, Doc>,
+ rtfs: { copy: Doc; key: string; field: RichTextField }[],
+ exclusions: string[],
+ pruneDocs: Doc[],
+ cloneLinks: boolean,
+ cloneTemplates: boolean
+ ): Promise<Doc> {
+ if (Doc.IsBaseProto(doc) || ((Doc.Get(doc, 'isTemplateDoc', true) || Doc.Get(doc, 'isTemplateForField', true)) && !cloneTemplates)) {
+ return doc;
+ }
if (cloneMap.get(doc[Id])) return cloneMap.get(doc[Id])!;
const copy = new Doc(undefined, true);
cloneMap.set(doc[Id], copy);
@@ -630,7 +641,7 @@ export namespace Doc {
const list = await Cast(doc[key], listSpec(Doc));
const docs = list && (await DocListCastAsync(list))?.filter(d => d instanceof Doc);
if (docs !== undefined && docs.length) {
- const clones = await Promise.all(docs.map(async d => Doc.makeClone(d, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks)));
+ const clones = await Promise.all(docs.map(async d => Doc.makeClone(d, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks, cloneTemplates)));
assignKey(new List<Doc>(clones));
} else {
assignKey(ObjectField.MakeCopy(field));
@@ -645,7 +656,7 @@ export namespace Doc {
);
const results = docids && (await DocServer.GetRefFields(docids));
const docs = results && Array.from(Object.keys(results)).map(key => DocCast(results[key]));
- docs?.map(doc => doc && Doc.makeClone(doc, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks));
+ docs?.map(doc => doc && Doc.makeClone(doc, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks, cloneTemplates));
rtfs.push({ copy, key, field });
}
}
@@ -657,8 +668,14 @@ export namespace Doc {
} else if (docAtKey instanceof Doc) {
if (pruneDocs.includes(docAtKey)) {
// prune doc and do nothing
- } else if (!Doc.IsSystem(docAtKey) && (key.startsWith('layout') || ['embedContainer', 'annotationOn', 'proto'].includes(key) || ((key === 'link_anchor_1' || key === 'link_anchor_2') && doc.author === Doc.CurrentUserEmail))) {
- assignKey(await Doc.makeClone(docAtKey, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks));
+ } else if (
+ !Doc.IsSystem(docAtKey) &&
+ (key.includes('layout[') ||
+ key.startsWith('layout') || //
+ ['embedContainer', 'annotationOn', 'proto'].includes(key) ||
+ (['link_anchor_1', 'link_anchor_2'].includes(key) && doc.author === Doc.CurrentUserEmail))
+ ) {
+ assignKey(await Doc.makeClone(docAtKey, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks, cloneTemplates));
} else {
assignKey(docAtKey);
}
@@ -681,16 +698,17 @@ export namespace Doc {
((cloneMap.has(DocCast(link.link_anchor_1)?.[Id]) || cloneMap.has(DocCast(DocCast(link.link_anchor_1)?.annotationOn)?.[Id])) &&
(cloneMap.has(DocCast(link.link_anchor_2)?.[Id]) || cloneMap.has(DocCast(DocCast(link.link_anchor_2)?.annotationOn)?.[Id])))
) {
- linkMap.set(link[Id], await Doc.makeClone(link, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks));
+ linkMap.set(link[Id], await Doc.makeClone(link, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks, cloneTemplates));
}
});
- Doc.SetInPlace(copy, 'title', '>:' + doc.title, true);
+ if (Doc.Get(copy, 'title', true)) copy.title = '>:' + doc.title;
+ // Doc.SetInPlace(copy, 'title', '>:' + doc.title, true);
copy.cloneOf = doc;
cloneMap.set(doc[Id], copy);
return copy;
}
- export function repairClone(clone: Doc, cloneMap: Map<string, Doc>, visited: Set<Doc>) {
+ export function repairClone(clone: Doc, cloneMap: Map<string, Doc>, cloneTemplates: boolean, visited: Set<Doc>) {
if (visited.has(clone)) return;
visited.add(clone);
Object.keys(clone)
@@ -699,22 +717,22 @@ export namespace Doc {
const docAtKey = DocCast(clone[key]);
if (docAtKey && !Doc.IsSystem(docAtKey)) {
if (!Array.from(cloneMap.values()).includes(docAtKey)) {
- clone[key] = cloneMap.get(docAtKey[Id]);
+ clone[key] = !cloneTemplates && (Doc.Get(docAtKey, 'isTemplateDoc', true) || Doc.Get(docAtKey, 'isTemplateForField', true)) ? docAtKey : cloneMap.get(docAtKey[Id]);
} else {
- repairClone(docAtKey, cloneMap, visited);
+ repairClone(docAtKey, cloneMap, cloneTemplates, visited);
}
}
});
}
- export function MakeClones(docs: Doc[], cloneLinks: boolean) {
+ export function MakeClones(docs: Doc[], cloneLinks: boolean, cloneTemplates: boolean) {
const cloneMap = new Map<string, Doc>();
- return docs.map(doc => Doc.MakeClone(doc, cloneLinks, cloneMap));
+ return docs.map(doc => Doc.MakeClone(doc, cloneLinks, cloneTemplates, cloneMap));
}
- export async function MakeClone(doc: Doc, cloneLinks = true, cloneMap: Map<string, Doc> = new Map()) {
+ export async function MakeClone(doc: Doc, cloneLinks = true, cloneTemplates = true, cloneMap: Map<string, Doc> = new Map()) {
const linkMap = new Map<string, Doc>();
const rtfMap: { copy: Doc; key: string; field: RichTextField }[] = [];
- const copy = await Doc.makeClone(doc, cloneMap, linkMap, rtfMap, ['cloneOf'], doc.embedContainer ? [DocCast(doc.embedContainer)] : [], cloneLinks);
+ const copy = await Doc.makeClone(doc, cloneMap, linkMap, rtfMap, ['cloneOf'], doc.embedContainer ? [DocCast(doc.embedContainer)] : [], cloneLinks, cloneTemplates);
const repaired = new Set<Doc>();
const linkedDocs = Array.from(linkMap.values());
linkedDocs.map((link: Doc) => LinkManager.Instance.addLink(link, true));
@@ -732,7 +750,7 @@ export namespace Doc {
copy[key] = new RichTextField(field.Data.replace(docidsearch, replacer).replace(re, replacer2), field.Text);
});
const clonedDocs = [...Array.from(cloneMap.values()), ...linkedDocs];
- clonedDocs.map(clone => Doc.repairClone(clone, cloneMap, repaired));
+ clonedDocs.map(clone => Doc.repairClone(clone, cloneMap, cloneTemplates, repaired));
return { clone: copy, map: cloneMap, linkMap };
}
@@ -1395,7 +1413,7 @@ export namespace Doc {
const list = Array.from(Object.values(fieldlist))
.map(d => DocCast(d))
.filter(d => d);
- const docs = clone ? (await Promise.all(Doc.MakeClones(list, false))).map(res => res.clone) : list;
+ const docs = clone ? (await Promise.all(Doc.MakeClones(list, false, false))).map(res => res.clone) : list;
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;