aboutsummaryrefslogtreecommitdiff
path: root/src/client/documents/DocUtils.ts
diff options
context:
space:
mode:
authorA.J. Shulman <Shulman.aj@gmail.com>2025-05-11 10:46:15 -0400
committerA.J. Shulman <Shulman.aj@gmail.com>2025-05-11 10:46:15 -0400
commitb87b2105e966928518c96c7702b68c12344ffdd7 (patch)
tree84fd5ecede3af9d773c10d02908cdde27da1a759 /src/client/documents/DocUtils.ts
parent0db4583914e43e6efdba3e86a614a19956e73b5e (diff)
parent0c3f86d57225a2991920adef3a337bc13e408ac0 (diff)
Merge branch 'master' into agent-web-working
Diffstat (limited to 'src/client/documents/DocUtils.ts')
-rw-r--r--src/client/documents/DocUtils.ts88
1 files changed, 42 insertions, 46 deletions
diff --git a/src/client/documents/DocUtils.ts b/src/client/documents/DocUtils.ts
index 1c7ccadd1..36e03daed 100644
--- a/src/client/documents/DocUtils.ts
+++ b/src/client/documents/DocUtils.ts
@@ -8,7 +8,6 @@ import * as JSZipUtils from '../../JSZipUtils';
import { decycle } from '../../decycler/decycler';
import { DateField } from '../../fields/DateField';
import { Doc, DocListCast, Field, FieldResult, FieldType, LinkedTo, Opt, StrListCast } from '../../fields/Doc';
-import { DocData } from '../../fields/DocSymbols';
import { Id } from '../../fields/FieldSymbols';
import { InkData, InkDataFieldName, InkField } from '../../fields/InkField';
import { List, ListFieldName } from '../../fields/List';
@@ -56,13 +55,13 @@ export namespace DocUtils {
const matchLink = (val: string, anchor: Doc) => {
const linkedToExp = (val ?? '').split('=');
if (linkedToExp.length === 1) return Field.toScriptString(anchor) === val;
- return Field.toScriptString(DocCast(anchor[linkedToExp[0]])) === linkedToExp[1];
+ return DocCast(anchor[linkedToExp[0]]) && 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 as string, DocCast(link.link_anchor_1)) ||
- matchLink(value as string, DocCast(link.link_anchor_2)) ));
+ (allLinks.some(link => (DocCast(link.link_anchor_1) && matchLink(value as string, DocCast(link.link_anchor_1)!)) ||
+ (DocCast(link.link_anchor_2) && matchLink(value as string, DocCast(link.link_anchor_2)!)) ));
}
if (typeof value === 'string') {
value = value.replace(`,${ClientUtils.noRecursionHack}`, '');
@@ -267,7 +266,7 @@ export namespace DocUtils {
Object.keys(funcs)
.filter(key => !key.endsWith('-setter'))
.forEach(key => {
- const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key]));
+ const cfield = ComputedField.DisableCompute(() => FieldValue(doc[key]));
const func = funcs[key];
if (ScriptCast(cfield)?.script.originalScript !== func) {
const setFunc = Cast(funcs[key + '-setter'], 'string', null);
@@ -284,10 +283,10 @@ export namespace DocUtils {
}
return val1 === val2;
};
- Object.entries(reqdOpts).forEach(pair => {
- const targetDoc = pair[0].startsWith('_') ? doc : Doc.GetProto(doc as Doc);
- if (!Object.getOwnPropertyNames(targetDoc).includes(pair[0].replace(/^_/, '')) || !compareValues(pair[1], targetDoc[pair[0]])) {
- targetDoc[pair[0]] = pair[1];
+ Object.entries(reqdOpts).forEach(([key, val]) => {
+ const targetDoc = key.startsWith('_') ? doc : Doc.GetProto(doc as Doc);
+ if (!Object.getOwnPropertyNames(targetDoc).includes(key.replace(/^_/, '')) || !compareValues(val, targetDoc[key])) {
+ targetDoc[key] = val as FieldType;
}
});
items?.forEach(item => !DocListCast(doc.data).includes(item) && Doc.AddDocToList(Doc.GetProto(doc), 'data', item));
@@ -309,6 +308,7 @@ export namespace DocUtils {
*/
export async function DocumentFromType(type: string, path: string, options: DocumentOptions, overwriteDoc?: Doc): Promise<Opt<Doc>> {
let ctor: ((path: string, options: DocumentOptions, overwriteDoc?: Doc) => Doc | Promise<Doc | undefined>) | undefined;
+
if (type.indexOf('image') !== -1) {
ctor = Docs.Create.ImageDocument;
if (!options._width) options._width = 300;
@@ -376,17 +376,18 @@ export namespace DocUtils {
const documentList: ContextMenuProps[] = foo
.filter(btnDoc => !btnDoc.hidden)
- .map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null))
+ .map(btnDoc => DocCast(btnDoc?.dragFactory))
.filter(doc => doc && doc !== Doc.UserDoc().emptyTrail && doc.title)
+ .map(doc => doc!)
.map(dragDoc => ({
description: ':' + StrCast(dragDoc.title).replace('Untitled ', ''),
event: undoable(() => {
- const newDoc = DocUtils.copyDragFactory(dragDoc);
+ const newDoc = (dragDoc.isTemplateDoc ? DocUtils.delegateDragFactory : DocUtils.copyDragFactory)(dragDoc);
if (newDoc) {
- newDoc.author = ClientUtils.CurrentUserEmail();
+ newDoc._author = ClientUtils.CurrentUserEmail();
newDoc.x = x;
newDoc.y = y;
- newDoc[DocData].backgroundColor = Doc.UserDoc().textBackgroundColor;
+ newDoc.$backgroundColor = Doc.UserDoc().textBackgroundColor;
DocumentView.SetSelectOnLoad(newDoc);
if (pivotField) {
newDoc[pivotField] = pivotValue;
@@ -438,6 +439,7 @@ export namespace DocUtils {
.filter(btnDoc => !btnDoc.hidden)
.map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null))
.filter(doc => doc && doc !== Doc.UserDoc().emptyTrail && doc !== Doc.UserDoc().emptyNote && doc.title)
+ .map(doc => doc!)
.map(dragDoc => ({
description: ':' + StrCast(dragDoc.title).replace('Untitled ', ''),
event: undoable(() => {
@@ -495,11 +497,11 @@ export namespace DocUtils {
.map(btnDoc => (btnDoc.dragFactory as Doc) || btnDoc)
.filter(d => d.isTemplateDoc);
// bcz: this is hacky -- want to have different templates be applied depending on the "type" of a document. but type is not reliable and there could be other types of template searches so this should be generalized
- // first try to find a template that matches the specific document type (<typeName>_<templateName>). otherwise, fallback to a general match on <templateName>
+ // first try to find a template that matches the specific document type (<typeName><TemplateName>). otherwise, fallback to a general match on <templateName>
!docLayoutTemplate &&
allTemplates.forEach(tempDoc => {
const templateType = StrCast(doc[templateName + '_fieldKey'] || doc.type);
- StrCast(tempDoc.title) === templateName + '_' + templateType && (docLayoutTemplate = tempDoc);
+ StrCast(tempDoc.title) === templateName + (templateType[0].toUpperCase() + templateType.slice(1)) && (docLayoutTemplate = tempDoc);
});
!docLayoutTemplate &&
allTemplates.forEach(tempDoc => {
@@ -523,18 +525,13 @@ export namespace DocUtils {
Doc.ApplyTemplateTo(docLayoutTemplate, doc, customName, undefined);
}
} else {
- let fieldTemplate: Opt<Doc>;
- if (doc.data instanceof RichTextField || typeof doc.data === 'string') {
- fieldTemplate = Docs.Create.TextDocument('', options);
- } else if (doc.data instanceof PdfField) {
- fieldTemplate = Docs.Create.PdfDocument('http://www.msn.com', options);
- } else if (doc.data instanceof VideoField) {
- fieldTemplate = Docs.Create.VideoDocument('http://www.cs.brown.edu', options);
- } else if (doc.data instanceof AudioField) {
- fieldTemplate = Docs.Create.AudioDocument('http://www.cs.brown.edu', options);
- } else if (doc.data instanceof ImageField) {
- fieldTemplate = Docs.Create.ImageDocument('http://www.cs.brown.edu', options);
- }
+ const fieldTemplate = (() => {
+ if (doc.data instanceof RichTextField || typeof doc.data === 'string') return Docs.Create.TextDocument('', options);
+ if (doc.data instanceof PdfField) return Docs.Create.PdfDocument('http://www.msn.com', options);
+ if (doc.data instanceof VideoField) return Docs.Create.VideoDocument('http://www.cs.brown.edu', options);
+ if (doc.data instanceof AudioField) return Docs.Create.AudioDocument('http://www.cs.brown.edu', options);
+ if (doc.data instanceof ImageField) return Docs.Create.ImageDocument('http://www.cs.brown.edu', options);
+ })();
const docTemplate = creator?.(fieldTemplate ? [fieldTemplate] : [], { title: customName + '(' + doc.title + ')', isTemplateDoc: true, _width: _width + 20, _height: Math.max(100, _height + 45) });
fieldTemplate && Doc.MakeMetadataFieldTemplate(fieldTemplate, docTemplate ? Doc.GetProto(docTemplate) : docTemplate);
docTemplate && Doc.ApplyTemplateTo(docTemplate, doc, customName, undefined);
@@ -579,7 +576,7 @@ export namespace DocUtils {
Docs.Create.FreeformDocument([], {
_width: NumCast(layoutDoc._width) + 10,
_height: Math.max(NumCast(layoutDoc._height), NumCast(layoutDoc._width) + 10),
- _isLightbox: true,
+ isLightbox: true,
_layout_fitWidth: true,
title: StrCast(doc.title) + ' [Portal]',
}),
@@ -606,7 +603,7 @@ export namespace DocUtils {
layout_hideAllLinks: true,
_width: 15,
_height: 15,
- _xPadding: 0,
+ _xMargin: 0,
onClick: FollowLinkScript(),
_timecodeToShow: Cast(doc._timecodeToShow, 'number', null),
});
@@ -645,8 +642,15 @@ export namespace DocUtils {
return dd;
}
- export function assignImageInfo(result: Upload.FileInformation, protoIn: Doc) {
+ export function assignUploadInfo(result: Upload.FileInformation, protoIn: Doc) {
const proto = protoIn;
+
+ if (Upload.isTextInformation(result)) {
+ proto.text = result.rawText;
+ }
+ if (Upload.isVideoInformation(result)) {
+ proto.data_duration = result.duration;
+ }
if (Upload.isImageInformation(result)) {
const maxNativeDim = Math.max(result.nativeHeight, result.nativeWidth);
const exifRotation = StrCast(result.exifData?.data?.Orientation).toLowerCase();
@@ -680,15 +684,8 @@ export namespace DocUtils {
const pathname = result.accessPaths.agnostic.client;
const doc = await DocUtils.DocumentFromType(type, pathname, full, overwriteDoc);
if (doc) {
- const proto = Doc.GetProto(doc);
- proto.text = result.rawText;
- !(result instanceof Error) && DocUtils.assignImageInfo(result, proto);
- if (Upload.isVideoInformation(result)) {
- proto.data_duration = result.duration;
- }
- if (overwriteDoc) {
- Doc.removeCurrentlyLoading(overwriteDoc);
- }
+ DocUtils.assignUploadInfo(result, Doc.GetProto(doc));
+ overwriteDoc && Doc.removeCurrentlyLoading(overwriteDoc);
generatedDocuments.push(doc);
}
return doc;
@@ -715,7 +712,7 @@ export namespace DocUtils {
nativeWidth: 40,
nativeHeight: 40,
})
- : Docs.Create.TextDocument('', {
+ : (defaultTextTemplate?.type === DocumentType.JOURNAL ? Docs.Create.DailyJournalDocument : Docs.Create.TextDocument)('', {
annotationOn,
backgroundColor,
x,
@@ -726,12 +723,11 @@ export namespace DocUtils {
: {
_width: width || BoolCast(Doc.UserDoc().fitBox) ? Number(StrCast(Doc.UserDoc().fontSize).replace('px', '')) * 1.5 * 6 : 200,
_height: BoolCast(Doc.UserDoc().fitBox) ? Number(StrCast(Doc.UserDoc().fontSize).replace('px', '')) * 1.5 : 35,
- _layout_centered: BoolCast(Doc.UserDoc()._layout_centered),
- _layout_fitWidth: true,
_layout_autoHeight: true,
backgroundColor: StrCast(Doc.UserDoc().textBackgroundColor),
borderColor: Doc.UserDoc().borderColor as string,
borderWidth: Doc.UserDoc().borderWidth as number,
+ text_centered: BoolCast(Doc.UserDoc().textCentered),
text_fitBox: BoolCast(Doc.UserDoc().fitBox),
text_align: StrCast(Doc.UserDoc().textAlign),
text_fontColor: StrCast(Doc.UserDoc().fontColor),
@@ -745,7 +741,7 @@ export namespace DocUtils {
if (defaultTextTemplate) {
tbox.layout_fieldKey = 'layout_' + StrCast(defaultTextTemplate.title);
Doc.GetProto(tbox)[StrCast(tbox.layout_fieldKey)] = defaultTextTemplate; // set the text doc's layout to render with the text template
- tbox[DocData].proto = defaultTextTemplate; // and also set the text doc to inherit from the template (this allows the template to specify default field values)
+ tbox.$proto = defaultTextTemplate; // and also set the text doc to inherit from the template (this allows the template to specify default field values)
}
return tbox;
}
@@ -873,13 +869,13 @@ export namespace DocUtils {
const ndoc = Doc.MakeDelegateWithProto(dragFactory);
if (ndoc && dragFactory.dragFactory_count !== undefined) {
dragFactory.dragFactory_count = NumCast(dragFactory.dragFactory_count) + 1;
- Doc.GetProto(ndoc).title = ndoc.title + ' ' + NumCast(dragFactory.dragFactory_count).toString();
+ Doc.GetProto(ndoc).title = ndoc.title;
}
return ndoc;
}
- export async function Zip(doc: Doc, zipFilename = 'dashExport.zip') {
- const { clone, map, linkMap } = await Doc.MakeClone(doc);
+ export function Zip(doc: Doc, zipFilename = 'dashExport.zip') {
+ const { clone, map, linkMap } = Doc.MakeClone(doc);
const proms = new Set<string>();
function replacer(key: string, value: { url: string; [key: string]: unknown }) {
if (key && ['branchOf', 'cloneOf', 'cursors'].includes(key)) return undefined;