diff options
Diffstat (limited to 'src/client/documents/Documents.ts')
-rw-r--r-- | src/client/documents/Documents.ts | 131 |
1 files changed, 99 insertions, 32 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 4086ede20..029653204 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -2,7 +2,7 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { action, reaction, runInAction } from 'mobx'; import { basename } from 'path'; import { DateField } from '../../fields/DateField'; -import { Doc, DocListCast, Field, LinkedTo, Opt, updateCachedAcls } from '../../fields/Doc'; +import { Doc, DocListCast, Field, LinkedTo, Opt, StrListCast, updateCachedAcls } from '../../fields/Doc'; import { Initializing } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; import { HtmlField } from '../../fields/HtmlField'; @@ -186,8 +186,6 @@ export class DocumentOptions { linearBtnWidth?: NUMt = new NumInfo('unexpanded width of a linear menu button (button "width" changes when it expands)', false); _nativeWidth?: NUMt = new NumInfo('native width of document contents (e.g., the pixel width of an image)', false); _nativeHeight?: NUMt = new NumInfo('native height of document contents (e.g., the pixel height of an image)', false); - _nativeDimModifiable?: BOOLt = new BoolInfo('native dimensions can be modified using document decoration reizers', false); - _nativeHeightUnfrozen?: BOOLt = new BoolInfo('native height can be changed independent of width by dragging decoration resizers'); 'acl-Guest'?: STRt = new StrInfo("permissions granted to users logged in as 'guest' (either view, or private)"); // public permissions '_acl-Guest'?: string; // public permissions @@ -229,12 +227,16 @@ export class DocumentOptions { layout_hideLinkButton?: BOOLt = new BoolInfo('whether the blue link counter button should be hidden'); layout_hideDecorationTitle?: BOOLt = new BoolInfo('whether to suppress the document decortations title when selected'); layout_borderRounding?: string; + _layout_nativeDimEditable?: BOOLt = new BoolInfo('native dimensions can be modified using document decoration reizers', false); + _layout_reflowVertical?: BOOLt = new BoolInfo('native height can be changed independent of width by dragging decoration resizers'); + _layout_reflowHorizontal?: BOOLt = new BoolInfo('whether a doc with a native size can be horizonally resized, causing some form of reflow'); layout_boxShadow?: string; // box-shadow css string OR "standard" to use dash standard box shadow layout_maxAutoHeight?: NUMt = new NumInfo('maximum height for newly created (eg, from pasting) text documents', false); _layout_autoHeight?: BOOLt = new BoolInfo('whether document automatically resizes vertically to display contents'); _layout_curPage?: NUMt = new NumInfo('current page of a PDF or other? paginated document', false); _layout_currentTimecode?: NUMt = new NumInfo('the current timecode of a time-based document (e.g., current time of a video) value is in seconds', false); _layout_hideContextMenu?: BOOLt = new BoolInfo('whether the context menu can be shown'); + _layout_centered?: BOOLt = new BoolInfo('whether text should be vertically centered in Doc'); _layout_fitWidth?: BOOLt = new BoolInfo('whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)'); _layout_fitContentsToBox?: BOOLt = new BoolInfo('whether a freeformview should zoom/scale to create a shrinkwrapped view of its content'); _layout_fieldKey?: STRt = new StrInfo('the field key containing the current layout definition', false); @@ -472,9 +474,9 @@ export namespace Docs { _height: 35, _xMargin: 10, _yMargin: 10, - nativeDimModifiable: true, - nativeHeightUnfrozen: true, - layout_forceReflow: true, + layout_nativeDimEditable: true, + layout_reflowVertical: true, + layout_reflowHorizontal: true, defaultDoubleClick: 'ignore', systemIcon: 'BsFileEarmarkTextFill', }, @@ -505,14 +507,24 @@ export namespace Docs { DocumentType.WEB, { layout: { view: WebBox, dataField: defaultDataKey }, - options: { _height: 300, _layout_fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true, waitForDoubleClickToClick: 'always', systemIcon: 'BsGlobe' }, + options: { _height: 300, _layout_fitWidth: true, layout_nativeDimEditable: true, layout_reflowVertical: true, waitForDoubleClickToClick: 'always', systemIcon: 'BsGlobe' }, }, ], [ DocumentType.COL, { layout: { view: CollectionView, dataField: defaultDataKey }, - options: { _layout_fitWidth: true, freeform: '', _freeform_panX: 0, _freeform_panY: 0, _freeform_scale: 1, systemIcon: 'BsFillCollectionFill' }, + options: { + _layout_fitWidth: true, + freeform: '', + _freeform_panX: 0, + _freeform_panY: 0, + _freeform_scale: 1, + layout_nativeDimEditable: true, + layout_reflowHorizontal: true, + layout_reflowVertical: true, + systemIcon: 'BsFillCollectionFill', + }, }, ], [ @@ -533,7 +545,7 @@ export namespace Docs { DocumentType.AUDIO, { layout: { view: AudioBox, dataField: defaultDataKey }, - options: { _height: 100, layout_fitWidth: true, layout_forceReflow: true, nativeDimModifiable: true, systemIcon: 'BsFillVolumeUpFill' }, + options: { _height: 100, layout_fitWidth: true, layout_reflowHorizontal: true, layout_reflowVertical: true, layout_nativeDimEditable: true, systemIcon: 'BsFillVolumeUpFill' }, }, ], [ @@ -547,14 +559,14 @@ export namespace Docs { DocumentType.PDF, { layout: { view: PDFBox, dataField: defaultDataKey }, - options: { _layout_curPage: 1, _layout_fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true, systemIcon: 'BsFileEarmarkPdfFill' }, + options: { _layout_curPage: 1, _layout_fitWidth: true, layout_nativeDimEditable: true, layout_reflowVertical: true, systemIcon: 'BsFileEarmarkPdfFill' }, }, ], [ DocumentType.MAP, { layout: { view: MapBox, dataField: defaultDataKey }, - options: { map: '', _height: 600, _width: 800, nativeDimModifiable: true, systemIcon: 'BsFillPinMapFill' }, + options: { map: '', _height: 600, _width: 800, layout_reflowHorizontal: true, layout_reflowVertical: true, layout_nativeDimEditable: true, systemIcon: 'BsFillPinMapFill' }, }, ], [ @@ -613,14 +625,25 @@ export namespace Docs { DocumentType.EQUATION, { layout: { view: EquationBox, dataField: 'text' }, - options: { nativeDimModifiable: true, fontSize: '14px', layout_hideResizeHandles: true, layout_hideDecorationTitle: true, systemIcon: 'BsCalculatorFill' }, ///systemIcon: 'BsSuperscript' + BsSubscript + options: { + fontSize: '14px', + layout_reflowHorizontal: true, + layout_reflowVertical: true, + layout_nativeDimEditable: true, + layout_hideDecorationTitle: true, + systemIcon: 'BsCalculatorFill', + }, ///systemIcon: 'BsSuperscript' + BsSubscript }, ], [ DocumentType.FUNCPLOT, { layout: { view: FunctionPlotBox, dataField: defaultDataKey }, - options: { nativeDimModifiable: true }, + options: { + layout_reflowHorizontal: true, + layout_reflowVertical: true, + layout_nativeDimEditable: true, + }, }, ], [ @@ -672,12 +695,12 @@ export namespace Docs { layout: { view: InkingStroke, dataField: 'stroke' }, options: { systemIcon: 'BsFillPencilFill', // - nativeDimModifiable: true, - nativeHeightUnfrozen: true, + layout_nativeDimEditable: true, + layout_reflowVertical: true, + layout_reflowHorizontal: true, layout_hideDecorationTitle: true, // don't show title when selected fitWidth: false, layout_isSvg: true, - layout_forceReflow: true, }, }, ], @@ -685,7 +708,7 @@ export namespace Docs { DocumentType.SCREENSHOT, { layout: { view: ScreenshotBox, dataField: defaultDataKey }, - options: { nativeDimModifiable: true, nativeHeightUnfrozen: true, systemIcon: 'BsCameraFill' }, + options: { layout_nativeDimEditable: true, systemIcon: 'BsCameraFill' }, }, ], [ @@ -693,7 +716,7 @@ export namespace Docs { { data: '', layout: { view: ComparisonBox, dataField: defaultDataKey }, - options: { backgroundColor: 'gray', dropAction: 'move', waitForDoubleClickToClick: 'always', systemIcon: 'BsLayoutSplit' }, + options: { backgroundColor: 'gray', dropAction: 'move', waitForDoubleClickToClick: 'always', layout_reflowHorizontal: true, layout_reflowVertical: true, layout_nativeDimEditable: true, systemIcon: 'BsLayoutSplit' }, }, ], [ @@ -714,14 +737,14 @@ export namespace Docs { DocumentType.DATAVIZ, { layout: { view: DataVizBox, dataField: defaultDataKey }, - options: { dataViz_title: '', dataViz_line: '', dataViz_pie: '', dataViz_histogram: '', dataViz: 'table', _layout_fitWidth: true, nativeDimModifiable: true }, + options: { dataViz_title: '', dataViz_line: '', dataViz_pie: '', dataViz_histogram: '', dataViz: 'table', _layout_fitWidth: true, layout_reflowHorizontal: true, layout_reflowVertical: true, layout_nativeDimEditable: true }, }, ], [ DocumentType.LOADING, { layout: { view: LoadingBox, dataField: '' }, - options: { _layout_fitWidth: true, _fitHeight: true, nativeDimModifiable: true }, + options: { _layout_fitWidth: true, _fitHeight: true, layout_nativeDimEditable: true }, }, ], [ @@ -731,11 +754,9 @@ export namespace Docs { layout: { view: PhysicsSimulationBox, dataField: defaultDataKey, _width: 1000, _height: 800 }, options: { _height: 100, - layout_forceReflow: true, - nativeHeightUnfrozen: true, mass1: '', mass2: '', - nativeDimModifiable: true, + layout_nativeDimEditable: true, position: '', acceleration: '', pendulum: '', @@ -948,7 +969,7 @@ export namespace Docs { export function ImageDocument(url: string | ImageField, options: DocumentOptions = {}, overwriteDoc?: Doc) { const imgField = url instanceof ImageField ? url : new ImageField(url); - return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { _nativeDimModifiable: false, _nativeHeightUnfrozen: false, title: basename(imgField.url.href), ...options }, undefined, undefined, undefined, overwriteDoc); + return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: basename(imgField.url.href), ...options }, undefined, undefined, undefined, overwriteDoc); } export function PresDocument(options: DocumentOptions = {}) { @@ -1042,7 +1063,18 @@ export namespace Docs { return linkDoc; } - export function InkDocument(color: string, strokeWidth: number, stroke_bezier: string, fillColor: string, arrowStart: string, arrowEnd: string, dash: string, points: PointData[], isInkMask: boolean, options: DocumentOptions = {}) { + export function InkDocument( + points: PointData[], + options: DocumentOptions = {}, + strokeWidth = ActiveInkWidth(), + color = ActiveInkColor(), + stroke_bezier = ActiveInkBezierApprox(), + fillColor = ActiveFillColor(), + arrowStart = ActiveArrowStart(), + arrowEnd = ActiveArrowEnd(), + dash = ActiveDash(), + isInkMask = ActiveIsInkMask() + ) { const ink = InstanceFromProto(Prototypes.get(DocumentType.INK), '', { title: 'ink', ...options }); const I = Doc.GetProto(ink); // I.layout_hideOpenButton = true; // don't show open full screen button when selected @@ -1253,6 +1285,40 @@ export namespace Docs { } export namespace DocUtils { + function matchFieldValue(doc: Doc, key: string, value: any): boolean { + const hasFunctionFilter = Utils.HasFunctionFilter(value); + if (hasFunctionFilter) { + return hasFunctionFilter(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; + } + const vals = StrListCast(fieldVal); // list typing is very imperfect. casting to a string list doesn't mean that the entries will actually be strings + if (vals.length) { + return vals.some(v => typeof v === 'string' && 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 + } /** * @param docs * @param childFilters @@ -1284,7 +1350,7 @@ export namespace DocUtils { if (d.cookies && (!filterFacets.cookies || !Object.keys(filterFacets.cookies).some(key => d.cookies === key))) { return false; } - for (const facetKey of Object.keys(filterFacets).filter(fkey => fkey !== 'cookies' && fkey !== Utils.noDragsDocFilter.split(Doc.FilterSep)[0])) { + for (const facetKey of Object.keys(filterFacets).filter(fkey => fkey !== 'cookies' && fkey !== Utils.noDragDocsFilter.split(Doc.FilterSep)[0])) { const facet = filterFacets[facetKey]; // facets that match some value in the field of the document (e.g. some text field) @@ -1303,8 +1369,8 @@ export namespace DocUtils { const xs = Object.keys(facet).filter(value => facet[value] === 'x'); if (!unsets.length && !exists.length && !xs.length && !checks.length && !matches.length) return true; - const failsNotEqualFacets = !xs.length ? false : xs.some(value => Doc.matchFieldValue(d, facetKey, value)); - const satisfiesCheckFacets = !checks.length ? true : checks.some(value => Doc.matchFieldValue(d, facetKey, value)); + const failsNotEqualFacets = !xs.length ? false : xs.some(value => matchFieldValue(d, facetKey, value)); + const satisfiesCheckFacets = !checks.length ? true : checks.some(value => matchFieldValue(d, facetKey, value)); const satisfiesExistsFacets = !exists.length ? true : exists.some(value => (facetKey !== LinkedTo ? d[facetKey] !== undefined : LinkManager.Instance.getAllRelatedLinks(d).length)); const satisfiesUnsetsFacets = !unsets.length ? true : unsets.some(value => d[facetKey] === undefined); const satisfiesMatchFacets = !matches.length @@ -1492,7 +1558,7 @@ export namespace DocUtils { created = Docs.Create.AudioDocument(field.url.href, resolved); created.layout = AudioBox.LayoutString(fieldKey); } else if (field instanceof InkField) { - created = Docs.Create.InkDocument(ActiveInkColor(), ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), field.inkData, ActiveIsInkMask(), resolved); + created = Docs.Create.InkDocument(field.inkData, resolved); created.layout = InkingStroke.LayoutString(fieldKey); } else if (field instanceof List && field[0] instanceof Doc) { created = Docs.Create.StackingDocument(DocListCast(field), resolved); @@ -1802,7 +1868,7 @@ export namespace DocUtils { proto.data_duration = result.duration; } if (overwriteDoc) { - Doc.removeCurrentlyLoading(overwriteDoc); + LoadingBox.removeCurrentlyLoading(overwriteDoc); } generatedDocuments.push(doc); } @@ -1819,6 +1885,7 @@ export namespace DocUtils { _height: 35, x: x, y: y, + _layout_centered: BoolCast(Doc.UserDoc().layout_centered), _layout_fitWidth: true, _layout_autoHeight: true, _layout_enableAltContentUI: BoolCast(Doc.UserDoc().defaultToFlashcards), @@ -1844,7 +1911,7 @@ export namespace DocUtils { if (overwriteDoc) { overwriteDoc.isLoading = false; overwriteDoc.loadingError = (result as any).message; - Doc.removeCurrentlyLoading(overwriteDoc); + LoadingBox.removeCurrentlyLoading(overwriteDoc); } } else name && processFileupload(generatedDocuments, name, type, result, options, overwriteDoc); }); @@ -1885,7 +1952,7 @@ export namespace DocUtils { if ((result as any).message) { if (overwriteDoc) { overwriteDoc.loadingError = (result as any).message; - Doc.removeCurrentlyLoading(overwriteDoc); + LoadingBox.removeCurrentlyLoading(overwriteDoc); } } else name && type && processFileupload(generatedDocuments, name, type, result, options, overwriteDoc); }); |