diff options
Diffstat (limited to 'src/client/documents/DocUtils.ts')
-rw-r--r-- | src/client/documents/DocUtils.ts | 88 |
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; |