aboutsummaryrefslogtreecommitdiff
path: root/src/client/documents/Documents.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/documents/Documents.ts')
-rw-r--r--src/client/documents/Documents.ts144
1 files changed, 100 insertions, 44 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index a1ffddb98..da5c8efa9 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -39,7 +39,7 @@ import { DocFocusOptions } from "../views/nodes/DocumentView";
import { EquationBox } from "../views/nodes/EquationBox";
import { FieldViewProps } from "../views/nodes/FieldView";
import { FilterBox } from "../views/nodes/FilterBox";
-import { FontIconBox } from "../views/nodes/FontIconBox";
+import { FontIconBox } from "../views/nodes/button/FontIconBox";
import { FormattedTextBox } from "../views/nodes/formattedText/FormattedTextBox";
import { FunctionPlotBox } from "../views/nodes/FunctionPlotBox";
import { ImageBox } from "../views/nodes/ImageBox";
@@ -59,6 +59,7 @@ import { WebBox } from "../views/nodes/WebBox";
import { SearchBox } from "../views/search/SearchBox";
import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo";
import { DocumentType } from "./DocumentTypes";
+import { IconProp } from "@fortawesome/fontawesome-svg-core";
const path = require('path');
const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", ""));
@@ -140,8 +141,8 @@ export class DocumentOptions {
_columnWidth?: number;
_columnsHideIfEmpty?: boolean; // whether stacking view column headings should be hidden
_fontSize?: string;
- _fontWeight?: number;
_fontFamily?: string;
+ _fontWeight?: string;
_pivotField?: string; // field key used to determine headings for sections in stacking, masonry, pivot views
_curPage?: number; // current page of a PDF or other? paginated document
_currentTimecode?: number; // the current timecode of a time-based document (e.g., current time of a video) value is in seconds
@@ -156,6 +157,7 @@ export class DocumentOptions {
z?: number; // whether document is in overlay (1) or not (0 or undefined)
author?: string;
_layoutKey?: string;
+ unrendered?: boolean; // denotes an annotation that is not rendered with a DocumentView (e.g, rtf/pdf text selections and links to scroll locations in web/pdf)
type?: string;
title?: string;
"acl-Public"?: string; // public permissions
@@ -163,6 +165,7 @@ export class DocumentOptions {
version?: string; // version identifier for a document
label?: string;
hidden?: boolean;
+ _hidden?: boolean;
mediaState?: string; // status of media document: "pendingRecording", "recording", "paused", "playing"
autoPlayAnchors?: boolean; // whether to play audio/video when an anchor is clicked in a stackedTimeline.
dontPlayLinkOnSelect?: boolean; // whether an audio/video should start playing when a link is followed to it.
@@ -188,6 +191,7 @@ export class DocumentOptions {
opacity?: number;
defaultBackgroundColor?: string;
_isLinkButton?: boolean; // marks a document as a button that will follow its primary link when clicked
+ _linkAutoMove?: boolean; // whether link endpoint should move around the edges of a document to make shortest path to other link endpoint
isFolder?: boolean;
lastFrame?: number; // the last frame of a frame-based collection (e.g., progressive slide)
activeFrame?: number; // the active frame of a document in a frame base collection
@@ -214,7 +218,33 @@ export class DocumentOptions {
annotationOn?: Doc;
isPushpin?: boolean;
_removeDropProperties?: List<string>; // list of properties that should be removed from a document when it is dropped. e.g., a creator button may be forceActive to allow it be dragged, but the forceActive property can be removed from the dropped document
+
+ // BACKGROUND GRID
+ _backgroundGridShow?: boolean;
+
+ //BUTTONS
+ buttonText?: string;
iconShape?: string; // shapes of the fonticon border
+ btnType?: string;
+ btnList?: List<string>;
+ docColorBtn?: string;
+ userColorBtn?: string;
+ canClick?: string;
+ script?: string;
+ numBtnType?: string;
+ numBtnMax?: number;
+ numBtnMin?: number;
+ switchToggle?: boolean;
+
+ //LINEAR VIEW
+ linearViewIsExpanded?: boolean; // is linear view expanded
+ linearViewExpandable?: boolean; // can linear view be expanded
+ linearViewToggleButton?: string; // button to open close linear view group
+ linearViewSubMenu?: boolean;
+ linearViewFloating?: boolean;
+ flexGap?: number; // Linear view flex gap
+ flexDirection?: "unset" | "row" | "column" | "row-reverse" | "column-reverse";
+
layout_linkView?: Doc; // view template for a link document
layout_keyValue?: string; // view tempalte for key value docs
linkRelationship?: string; // type of relatinoship a link represents
@@ -246,7 +276,12 @@ export class DocumentOptions {
treeViewHideTitle?: boolean; // whether to hide the top document title of a tree view
treeViewHideHeader?: boolean; // whether to hide the header for a document in a tree view
treeViewHideHeaderFields?: boolean; // whether to hide the drop down options for tree view items.
- treeViewShowClearButton?: boolean; // whether a clear button should be displayed
+
+ // Action Button
+ buttonMenu?: boolean; // whether a action button should be displayed
+ buttonMenuDoc?: Doc;
+ explainer?: string;
+
treeViewOpenIsTransient?: boolean; // ignores the treeViewOpen Doc flag, allowing a treeViewItem's expand/collapse state to be independent of other views of the same document in the same or any other tree view
_treeViewOpen?: boolean; // whether this document is expanded in a tree view (note: need _ and regular versions since this can be specified for both proto and layout docs)
treeViewOpen?: boolean; // whether this document is expanded in a tree view
@@ -261,15 +296,14 @@ export class DocumentOptions {
text?: string;
textTransform?: string; // is linear view expanded
letterSpacing?: string; // is linear view expanded
- flexDirection?: "unset" | "row" | "column" | "row-reverse" | "column-reverse";
selectedIndex?: number; // which item in a linear view has been selected using the "thumb doc" ui
clipboard?: Doc;
searchQuery?: string; // for quersyBox
- linearViewIsExpanded?: boolean; // is linear view expanded
useLinkSmallAnchor?: boolean; // whether links to this document should use a miniature linkAnchorBox
border?: string; //for searchbox
hoverBackgroundColor?: string; // background color of a label when hovered
linkRelationshipList?: List<string>; // for storing different link relationships (when set by user in the link editor)
+ linkRelationshipSizes?: List<number>; //stores number of links contained in each relationship
linkColorList?: List<string>; // colors of links corresponding to specific link relationships
}
export namespace Docs {
@@ -321,7 +355,7 @@ export namespace Docs {
const TemplateMap: TemplateMap = new Map([
[DocumentType.RTF, {
layout: { view: FormattedTextBox, dataField: "text" },
- options: { _height: 150, _xMargin: 10, _yMargin: 10, links: ComputedField.MakeFunction("links(self)") as any }
+ options: { _height: 150, _xMargin: 10, _yMargin: 10, nativeDimModifiable: true, nativeHeightUnfrozen: true, links: ComputedField.MakeFunction("links(self)") as any }
}],
[DocumentType.SEARCH, {
layout: { view: SearchBox, dataField: defaultDataKey },
@@ -341,7 +375,7 @@ export namespace Docs {
}],
[DocumentType.WEB, {
layout: { view: WebBox, dataField: defaultDataKey },
- options: { _height: 300, _fitWidth: true, links: ComputedField.MakeFunction("links(self)") as any }
+ options: { _height: 300, _fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true, links: ComputedField.MakeFunction("links(self)") as any }
}],
[DocumentType.COL, {
layout: { view: CollectionView, dataField: defaultDataKey },
@@ -357,11 +391,11 @@ export namespace Docs {
}],
[DocumentType.AUDIO, {
layout: { view: AudioBox, dataField: defaultDataKey },
- options: { _height: 35, backgroundColor: "lightGray", links: ComputedField.MakeFunction("links(self)") as any }
+ options: { _height: 100, backgroundColor: "lightGray", links: ComputedField.MakeFunction("links(self)") as any }
}],
[DocumentType.PDF, {
layout: { view: PDFBox, dataField: defaultDataKey },
- options: { _curPage: 1, _fitWidth: true, links: ComputedField.MakeFunction("links(self)") as any }
+ options: { _curPage: 1, _fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true, links: ComputedField.MakeFunction("links(self)") as any }
}],
[DocumentType.IMPORT, {
layout: { view: DirectoryImportBox, dataField: defaultDataKey },
@@ -370,7 +404,7 @@ export namespace Docs {
[DocumentType.LINK, {
layout: { view: LinkBox, dataField: defaultDataKey },
options: {
- childDontRegisterViews: true, _isLinkButton: true, _height: 150, description: "",
+ childDontRegisterViews: true, _isLinkButton: true, _height: 150, description: "", showCaption: "description",
backgroundColor: "lightblue", // lightblue is default color for linking dot and link documents text comment area
links: ComputedField.MakeFunction("links(self)") as any,
_removeDropProperties: new List(["_layerTags", "isLinkButton"]),
@@ -399,7 +433,7 @@ export namespace Docs {
}],
[DocumentType.EQUATION, {
layout: { view: EquationBox, dataField: defaultDataKey },
- options: { links: ComputedField.MakeFunction("links(self)") as any }
+ options: { links: ComputedField.MakeFunction("links(self)") as any, hideResizeHandles: true, hideDecorationTitle: true }
}],
[DocumentType.FUNCPLOT, {
layout: { view: FunctionPlotBox, dataField: defaultDataKey },
@@ -432,9 +466,9 @@ export namespace Docs {
layout: { view: CollectionView, dataField: defaultDataKey },
options: { links: ComputedField.MakeFunction("links(self)") as any, hideLinkButton: true }
}],
- [DocumentType.INK, {
+ [DocumentType.INK, { // NOTE: this is unused!! ink fields are filled in directly within the InkDocument() method
layout: { view: InkingStroke, dataField: defaultDataKey },
- options: { _fontFamily: "cursive", backgroundColor: "transparent", links: ComputedField.MakeFunction("links(self)") as any }
+ options: { links: ComputedField.MakeFunction("links(self)") as any }
}],
[DocumentType.SCREENSHOT, {
layout: { view: ScreenshotBox, dataField: defaultDataKey },
@@ -475,6 +509,14 @@ export namespace Docs {
const prototypeIds = Object.values(DocumentType).filter(type => type !== DocumentType.NONE).map(type => type + suffix);
// fetch the actual prototype documents from the server
const actualProtos = Docs.newAccount ? {} : await DocServer.GetRefFields(prototypeIds);
+ if (!Docs.newAccount) {
+ Cast(actualProtos[DocumentType.WEB + suffix], Doc, null).nativeHeightUnfrozen = true; // to avoid having to recreate the DB
+ Cast(actualProtos[DocumentType.PDF + suffix], Doc, null).nativeHeightUnfrozen = true;
+ Cast(actualProtos[DocumentType.RTF + suffix], Doc, null).nativeHeightUnfrozen = true;
+ Cast(actualProtos[DocumentType.WEB + suffix], Doc, null).nativeDimModifiable = true; // to avoid having to recreate the DB
+ Cast(actualProtos[DocumentType.PDF + suffix], Doc, null).nativeDimModifiable = true;
+ Cast(actualProtos[DocumentType.RTF + suffix], Doc, null).nativeDimModifiable = true;
+ }
// update this object to include any default values: DocumentOptions for all prototypes
prototypeIds.map(id => {
@@ -679,14 +721,16 @@ export namespace Docs {
return linkDoc;
}
- export function InkDocument(color: string, tool: string, strokeWidth: string, strokeBezier: string, fillColor: string, arrowStart: string, arrowEnd: string, dash: string, points: { X: number, Y: number }[], options: DocumentOptions = {}) {
+ export function InkDocument(color: string, tool: string, strokeWidth: number, strokeBezier: string, fillColor: string, arrowStart: string, arrowEnd: string, dash: string, points: { X: number, Y: number }[], options: DocumentOptions = {}) {
const I = new Doc();
I[Initializing] = true;
I.type = DocumentType.INK;
I.layout = InkingStroke.LayoutString("data");
I.color = color;
+ I.hideDecorationTitle = true; // don't show title when selected
+ I.hideOpenButton = true; // don't show open full screen button when selected
I.fillColor = fillColor;
- I.strokeWidth = Number(strokeWidth);
+ I.strokeWidth = strokeWidth;
I.strokeBezier = strokeBezier;
I.strokeStartMarker = arrowStart;
I.strokeEndMarker = arrowEnd;
@@ -829,7 +873,7 @@ export namespace Docs {
export function DockDocument(documents: Array<Doc>, config: string, options: DocumentOptions, id?: string) {
const tabs = TreeDocument(documents, { title: "On-Screen Tabs", childDontRegisterViews: true, freezeChildren: "remove|add", treeViewExpandedViewLock: true, treeViewExpandedView: "data", _fitWidth: true, system: true, isFolder: true });
const all = TreeDocument([], { title: "Off-Screen Tabs", childDontRegisterViews: true, freezeChildren: "add", treeViewExpandedViewLock: true, treeViewExpandedView: "data", system: true, isFolder: true });
- return InstanceFromProto(Prototypes.get(DocumentType.COL), new List([tabs, all]), { freezeChildren: "remove|add", treeViewExpandedViewLock: true, treeViewExpandedView: "data", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id);
+ return InstanceFromProto(Prototypes.get(DocumentType.COL), new List([tabs, all]), { freezeChildren: "remove|add", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id);
}
export function DirectoryImportDocument(options: DocumentOptions = {}) {
@@ -928,12 +972,20 @@ export namespace DocUtils {
// facets that have a check next to them
const checks = Object.keys(facet).filter(value => facet[value] === "check");
+ // metadata facets that exist
+ const exists = Object.keys(facet).filter(value => facet[value] === "exists");
+
+ // metadata facets that exist
+ const unsets = Object.keys(facet).filter(value => facet[value] === "unset");
+
// facets that have an x next to them
const xs = Object.keys(facet).filter(value => facet[value] === "x");
- if (!xs.length && !checks.length && !matches.length) return true;
+ 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 satisfiesExistsFacets = !exists.length ? true : exists.some(value => d[facetKey] !== undefined);
+ const satisfiesUnsetsFacets = !unsets.length ? true : unsets.some(value => d[facetKey] === undefined);
const satisfiesMatchFacets = !matches.length ? true : matches.some(value => {
if (facetKey.startsWith("*")) { // fields starting with a '*' are used to match families of related fields. ie, *lastModified will match text-lastModified, data-lastModified, etc
const allKeys = Array.from(Object.keys(d));
@@ -945,11 +997,11 @@ export namespace DocUtils {
});
// if we're ORing them together, the default return is false, and we return true for a doc if it satisfies any one set of criteria
if ((parentCollection?.currentFilter as Doc)?.filterBoolean === "OR") {
- if (satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true;
+ if (satisfiesUnsetsFacets && satisfiesExistsFacets && satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true;
}
// if we're ANDing them together, the default return is true, and we return false for a doc if it doesn't satisfy any set of criteria
else {
- if (!satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false;
+ if (!satisfiesUnsetsFacets || !satisfiesExistsFacets || !satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false;
}
}
@@ -1053,10 +1105,12 @@ export namespace DocUtils {
"anchor2-useLinkSmallAnchor": target.doc.useLinkSmallAnchor ? true : undefined,
"acl-Public": SharingPermissions.Augment,
"_acl-Public": SharingPermissions.Augment,
- layout_linkView: Cast(Cast(Doc.UserDoc()["template-button-link"], Doc, null).dragFactory, Doc, null),
- linkDisplay: true, hidden: true,
+ linkDisplay: true,
+ _hidden: true,
+ _linkAutoMove: true,
linkRelationship,
- _layoutKey: "layout_linkView",
+ _showCaption: "description",
+ _showTitle: "linkRelationship",
description
}, id), showPopup);
}
@@ -1141,7 +1195,7 @@ export namespace DocUtils {
export function addDocumentCreatorMenuItems(docTextAdder: (d: Doc) => void, docAdder: (d: Doc) => void, x: number, y: number, simpleMenu: boolean = false): void {
!simpleMenu && ContextMenu.Instance.addItem({
- description: "Add Note ...",
+ description: "Quick Notes",
subitems: DocListCast((Doc.UserDoc()["template-notes"] as Doc).data).map((note, i) => ({
description: ":" + StrCast(note.title),
event: undoBatch((args: { x: number, y: number }) => {
@@ -1153,12 +1207,12 @@ export namespace DocUtils {
textDoc[textDoc.layoutKey] = note;
docTextAdder(textDoc);
}),
- icon: "eye"
+ icon: StrCast(note.icon) as IconProp
})) as ContextMenuProps[],
- icon: "eye"
+ icon: "sticky-note"
});
- ContextMenu.Instance.addItem({
- description: ":=math", event: () => {
+ const math: ContextMenuProps = ({
+ description: ":Math", event: () => {
const created = Docs.Create.EquationDocument();
if (created) {
created.author = Doc.CurrentUserEmail;
@@ -1169,25 +1223,27 @@ export namespace DocUtils {
EquationBox.SelectOnLoad = created[Id];
docAdder?.(created);
}
- }, icon: "compress-arrows-alt"
+ }, icon: "calculator"
});
+ const documentList: ContextMenuProps[] = DocListCast(Cast(Doc.UserDoc().myItemCreators, Doc, null)?.data).filter(btnDoc => !btnDoc.hidden).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc && doc !== Doc.UserDoc().emptyPresentation).map((dragDoc, i) => ({
+ description: ":" + StrCast(dragDoc.title),
+ event: undoBatch((args: { x: number, y: number }) => {
+ const newDoc = Doc.copyDragFactory(dragDoc);
+ if (newDoc) {
+ newDoc.author = Doc.CurrentUserEmail;
+ newDoc.x = x;
+ newDoc.y = y;
+ if (newDoc.type === DocumentType.RTF) FormattedTextBox.SelectOnLoad = newDoc[Id];
+ docAdder?.(newDoc);
+ }
+ }),
+ icon: Doc.toIcon(dragDoc),
+ })) as ContextMenuProps[];
+ documentList.push(math);
ContextMenu.Instance.addItem({
- description: "Add Template Doc ...",
- subitems: DocListCast(Cast(Doc.UserDoc().myItemCreators, Doc, null)?.data).filter(btnDoc => !btnDoc.hidden).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc && doc !== Doc.UserDoc().emptyPresentation).map((dragDoc, i) => ({
- description: ":" + StrCast(dragDoc.title),
- event: undoBatch((args: { x: number, y: number }) => {
- const newDoc = Doc.copyDragFactory(dragDoc);
- if (newDoc) {
- newDoc.author = Doc.CurrentUserEmail;
- newDoc.x = x;
- newDoc.y = y;
- if (newDoc.type === DocumentType.RTF) FormattedTextBox.SelectOnLoad = newDoc[Id];
- docAdder?.(newDoc);
- }
- }),
- icon: "eye"
- })) as ContextMenuProps[],
- icon: "eye"
+ description: "Create document",
+ subitems: documentList,
+ icon: "file"
});
}// applies a custom template to a document. the template is identified by it's short name (e.g, slideView not layout_slideView)
export function makeCustomViewClicked(doc: Doc, creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = "custom", docLayoutTemplate?: Doc) {