From ab1688962875073fa59a4a97303d0e0f0398ba5d Mon Sep 17 00:00:00 2001 From: geireann Date: Thu, 30 Nov 2023 15:23:08 -0500 Subject: fixed not fitting width for carousel views. --- src/client/views/collections/CollectionCarousel3DView.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/client/views/collections/CollectionCarousel3DView.tsx') diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index a8d080953..b3d8874d0 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -2,16 +2,16 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { computed } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { Utils, returnFalse, returnZero } from '../../../Utils'; import { Doc, DocListCast } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; -import { returnFalse, returnZero, Utils } from '../../../Utils'; import { DocumentType } from '../../documents/DocumentTypes'; import { DragManager } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; +import { StyleProp } from '../StyleProvider'; import { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } from '../global/globalCssVariables.scss'; import { DocFocusOptions, DocumentView } from '../nodes/DocumentView'; -import { StyleProp } from '../StyleProvider'; import './CollectionCarousel3DView.scss'; import { CollectionSubView } from './CollectionSubView'; @@ -61,9 +61,11 @@ export class CollectionCarousel3DView extends CollectionSubView() { return ( Date: Fri, 1 Dec 2023 02:33:04 -0500 Subject: converted props.DataDoc to props.TemplateDataDocument and fixed so that it's always undefined unless it's a template. converted references from rootDocument to props.TemplateDataDocument. --- src/client/documents/Documents.ts | 2 +- src/client/views/DocComponent.tsx | 13 +++---- src/client/views/GestureOverlay.tsx | 1 - src/client/views/LightboxView.tsx | 1 - src/client/views/MainView.tsx | 6 ---- src/client/views/MarqueeAnnotator.tsx | 2 +- src/client/views/PropertiesButtons.tsx | 2 +- src/client/views/PropertiesView.tsx | 2 +- src/client/views/SidebarAnnos.tsx | 2 +- src/client/views/StyleProvider.tsx | 21 ++++++----- .../views/collections/CollectionCarousel3DView.tsx | 4 +-- .../views/collections/CollectionCarouselView.tsx | 4 +-- .../collections/CollectionMasonryViewFieldRow.tsx | 2 +- src/client/views/collections/CollectionMenu.tsx | 1 - .../views/collections/CollectionNoteTakingView.tsx | 10 +++--- .../collections/CollectionNoteTakingViewColumn.tsx | 8 ++--- .../collections/CollectionStackedTimeline.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 10 +++--- .../CollectionStackingViewFieldColumn.tsx | 8 ++--- src/client/views/collections/CollectionSubView.tsx | 24 +++++++------ .../views/collections/CollectionTreeView.tsx | 8 ++--- src/client/views/collections/TabDocView.tsx | 2 +- src/client/views/collections/TreeView.tsx | 4 +-- .../collectionFreeForm/CollectionFreeFormView.tsx | 12 +++---- .../collectionGrid/CollectionGridView.tsx | 4 +-- .../CollectionMulticolumnView.tsx | 2 +- .../CollectionMultirowView.tsx | 2 +- .../collectionSchema/CollectionSchemaView.tsx | 2 -- .../collectionSchema/SchemaTableCell.tsx | 2 +- src/client/views/linking/LinkPopup.tsx | 1 - src/client/views/newlightbox/NewLightboxView.tsx | 1 - .../views/nodes/CollectionFreeFormDocumentView.tsx | 4 +-- src/client/views/nodes/ComparisonBox.tsx | 2 +- src/client/views/nodes/DocumentContentsView.tsx | 41 ++++++++++++---------- src/client/views/nodes/DocumentView.tsx | 20 +++++------ src/client/views/nodes/FieldView.tsx | 1 - src/client/views/nodes/FontIconBox/FontIconBox.tsx | 30 ++++++++-------- src/client/views/nodes/KeyValuePair.tsx | 1 - src/client/views/nodes/LoadingBox.tsx | 2 +- src/client/views/nodes/MapBox/MapBox.tsx | 4 +-- src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx | 14 ++++---- src/client/views/nodes/ScreenshotBox.tsx | 8 ++--- .../views/nodes/formattedText/FormattedTextBox.tsx | 13 ++++--- .../formattedText/ProsemirrorExampleTransfer.ts | 4 +-- .../views/nodes/importBox/ImportElementBox.tsx | 1 - src/client/views/nodes/trails/PresElementBox.tsx | 3 +- src/client/views/topbar/TopBar.tsx | 1 - src/fields/Doc.ts | 12 +++---- src/mobile/MobileInterface.tsx | 1 - 49 files changed, 158 insertions(+), 169 deletions(-) (limited to 'src/client/views/collections/CollectionCarousel3DView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index dfb9f4327..929660ff4 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1678,7 +1678,7 @@ export namespace DocUtils { newDoc.x = x; newDoc.y = y; EquationBox.SelectOnLoad = newDoc[Id]; - if (newDoc.type === DocumentType.RTF) FormattedTextBox.SelectOnLoad = newDoc[Id]; + if (newDoc.type === DocumentType.RTF) FormattedTextBox.SetSelectOnLoad(newDoc); if (pivotField) { newDoc[pivotField] = pivotValue; } diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 04956d974..d104eb90c 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -16,7 +16,6 @@ import { CollectionFreeFormView } from './collections/collectionFreeForm'; /// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView) export interface DocComponentProps { Document: Doc; - fieldKey?: string; LayoutTemplate?: () => Opt; LayoutTemplateString?: string; } @@ -34,10 +33,6 @@ export function DocComponent

() { @computed get dataDoc() { return this.props.Document[DocData] as Doc; } - // key where data is stored - @computed get fieldKey() { - return this.props.fieldKey; - } } return Component; } @@ -45,7 +40,7 @@ export function DocComponent

() { /// FieldViewBoxProps - a generic base class for field views that are not annotatable (e.g. InkingStroke, ColorBox) interface ViewBoxBaseProps { Document: Doc; - DataDoc?: Doc; + TemplateDataDocument?: Doc; DocumentView?: () => DocumentView; fieldKey: string; isSelected: () => boolean; @@ -65,7 +60,7 @@ export function ViewBoxBaseComponent

() { } // This is the data part of a document -- ie, the data that is constant across all views of the document @computed get dataDoc() { - return this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : this.props.Document[DocData]; + return this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc ? this.props.TemplateDataDocument ?? this.props.Document[DocData] : this.props.Document[DocData]; } // key where data is stored @computed get fieldKey() { @@ -78,7 +73,7 @@ export function ViewBoxBaseComponent

() { /// DocAnnotatbleComponent -return a base class for React views of document fields that are annotatable *and* interactive when selected (e.g., pdf, image) export interface ViewBoxAnnotatableProps { Document: Doc; - DataDoc?: Doc; + TemplateDataDocument?: Doc; fieldKey: string; filterAddDocument?: (doc: Doc[]) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example) isContentActive: () => boolean | undefined; @@ -102,7 +97,7 @@ export function ViewBoxAnnotatableComponent

() } // This is the data part of a document -- ie, the data that is constant across all views of the document @computed get dataDoc() { - return this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : this.props.Document[DocData]; + return this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc ? this.props.TemplateDataDocument ?? this.props.Document[DocData] : this.props.Document[DocData]; } // key where data is stored diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 508339efc..559f245d9 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -466,7 +466,6 @@ export class GestureOverlay extends React.Component { (this._docView = r !== null ? r : undefined))} Document={this._doc} - DataDoc={undefined} PanelWidth={this.lightboxWidth} PanelHeight={this.lightboxHeight} LayoutTemplate={this.lightboxDocTemplate} diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 3b3b43469..2e3817cb6 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -599,7 +599,6 @@ export class MainView extends React.Component { { const targetCreator = (annotationOn: Doc | undefined) => { const target = DocUtils.GetNewTextDoc('Note linked to ' + this.props.Document.title, 0, 0, 100, 100, undefined, annotationOn, undefined, 'yellow'); - FormattedTextBox.SelectOnLoad = target[Id]; + FormattedTextBox.SetSelectOnLoad(target); return target; }; DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.docView(), sourceAnchorCreator, targetCreator), e.pageX, e.pageY, { diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 7a8a0bfb9..6635aabf9 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -91,7 +91,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { //containerDoc._freeform_fitContentsToBox = containerDoc._isLightbox = !containerDoc._isLightbox; //containerDoc._xPadding = containerDoc._yPadding = containerDoc._isLightbox ? 10 : undefined; - const containerContents = DocListCast(dv.dataDoc[dv.props.fieldKey ?? Doc.LayoutFieldKey(containerDoc)]); + const containerContents = DocListCast(dv.dataDoc[Doc.LayoutFieldKey(containerDoc)]); //dv.Docuemnt.onClick = ScriptField.MakeScript('{self.data = undefined; documentView.select(false)}', { documentView: 'any' }); containerContents.forEach(doc => LinkManager.Links(doc).forEach(link => (link.link_displayLine = false))); }); diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index cde7eeb08..c5b0528af 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -293,7 +293,7 @@ export class PropertiesView extends React.Component {

{ _text_fontSize: StrCast(Doc.UserDoc().fontSize), _text_fontFamily: StrCast(Doc.UserDoc().fontFamily), }); - FormattedTextBox.SelectOnLoad = target[Id]; + FormattedTextBox.SetSelectOnLoad(target); FormattedTextBox.DontSelectInitialText = true; const link = DocUtils.MakeLink(anchor, target, { link_relationship: 'inline comment:comment on' }); link && (link.link_displayLine = false); diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index fa2768d79..2dd58fa80 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -64,6 +64,9 @@ function toggleLockedPosition(doc: Doc) { export function testDocProps(toBeDetermined: any): toBeDetermined is DocumentViewProps { return toBeDetermined?.isContentActive ? toBeDetermined : undefined; } +export function testFieldProps(toBeDetermined: any): toBeDetermined is FieldViewProps { + return toBeDetermined?.isContentActive ? toBeDetermined : undefined; +} export function wavyBorderPath(pw: number, ph: number, inset: number = 0.05) { return `M ${pw * 0.5} ${ph * inset} C ${pw * 0.6} ${ph * inset} ${pw * (1 - 2 * inset)} 0 ${pw * (1 - inset)} ${ph * inset} C ${pw} ${ph * (2 * inset)} ${pw * (1 - inset)} ${ph * 0.25} ${pw * (1 - inset)} ${ph * 0.3} C ${ @@ -77,19 +80,20 @@ export function wavyBorderPath(pw: number, ph: number, inset: number = 0.05) { // a preliminary implementation of a dash style sheet for setting rendering properties of documents nested within a Tab // -export function DefaultStyleProvider(doc: Opt, props: Opt, property: string): any { +export function DefaultStyleProvider(doc: Opt, props: Opt, property: string): any { const remoteDocHeader = 'author;author_date;noMargin'; const docProps = testDocProps(props) ? props : undefined; + const fieldProps = testFieldProps(props) ? props : undefined; const selected = property.includes(':selected'); const isCaption = property.includes(':caption'); const isAnchor = property.includes(':anchor'); const isContent = property.includes(':content'); const isAnnotated = property.includes(':annotated'); - const isInk = () => doc?._layout_isSvg && !props?.LayoutTemplateString; + const isInk = () => doc?._layout_isSvg && !docProps?.LayoutTemplateString; const isOpen = property.includes(':open'); const isEmpty = property.includes(':empty'); const boxBackground = property.includes(':box'); - const fieldKey = props?.fieldKey ? props.fieldKey + '_' : isCaption ? 'caption_' : ''; + const fieldKey = fieldProps?.fieldKey ? fieldProps.fieldKey + '_' : isCaption ? 'caption_' : ''; const lockedPosition = () => doc && BoolCast(doc._lockedPosition); const titleHeight = () => props?.styleProvider?.(doc, props, StyleProp.TitleHeight); const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor); @@ -132,20 +136,21 @@ export function DefaultStyleProvider(doc: Opt, props: Opt, props: Opt @@ -87,7 +87,7 @@ export class CollectionCarouselView extends CollectionSubView() { marginLeft: this.marginX, width: `calc(100% - ${this.marginX * 2}px)`, }}> - +
); diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index 06522b85e..a9b5f401d 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -155,7 +155,7 @@ export class CollectionMasonryViewFieldRow extends React.Component {
(this.docsDraggedRowCol.length ? 'none' : undefined); // getDisplayDoc returns the rules for displaying a document in this view (ie. DocumentView) getDisplayDoc(doc: Doc, width: () => number) { - const dataDoc = !doc.isTemplateDoc && !doc.isTemplateForField ? undefined : this.props.DataDoc; + const dataDoc = !doc.isTemplateDoc && !doc.isTemplateForField ? undefined : this.props.TemplateDataDocument; const height = () => this.getDocHeight(doc); let dref: Opt; const noteTakingDocTransform = () => this.getDocTransform(doc, dref); @@ -229,7 +229,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { (dref = r || undefined)} Document={doc} - DataDoc={dataDoc ?? (!Doc.AreProtosEqual(doc[DocData], doc) ? doc[DocData] : undefined)} + TemplateDataDocument={dataDoc ?? (!Doc.AreProtosEqual(doc[DocData], doc) ? doc[DocData] : undefined)} pointerEvents={this.blockPointerEventsWhenDragging} renderDepth={this.props.renderDepth + 1} PanelWidth={width} @@ -297,7 +297,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { getDocHeight(d?: Doc) { if (!d || d.hidden) return 0; const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); - const childDataDoc = !d.isTemplateDoc && !d.isTemplateForField ? undefined : this.props.DataDoc; + const childDataDoc = !d.isTemplateDoc && !d.isTemplateForField ? undefined : this.props.TemplateDataDocument; const maxHeight = (lim => (lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim))(NumCast(this.layoutDoc.childLimitHeight, -1)); const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d)) ? NumCast(d._width) : 0); const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d)) ? NumCast(d._height) : 0); @@ -411,7 +411,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { e.stopPropagation?.(); const newDoc = Doc.MakeCopy(docView.Document, true); Doc.GetProto(newDoc).text = undefined; - FormattedTextBox.SelectOnLoad = newDoc[Id]; + FormattedTextBox.SetSelectOnLoad(newDoc); return this.addDocument?.(newDoc); } }; @@ -526,7 +526,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { chromeHidden={this.chromeHidden} colHeaderData={this.colHeaderData} Document={this.props.Document} - DataDoc={this.props.DataDoc} + TemplateDataDocument={this.props.TemplateDataDocument} resizeColumns={this.resizeColumns} renderChildren={this.children} numGroupColumns={this.numGroupColumns} diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx index 52cc21903..9e5f09479 100644 --- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx +++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx @@ -25,7 +25,7 @@ import './CollectionNoteTakingView.scss'; interface CSVFieldColumnProps { Document: Doc; - DataDoc: Opt; + TemplateDataDocument: Opt; docList: Doc[]; heading: string; pivotField: string; @@ -134,7 +134,7 @@ export class CollectionNoteTakingViewColumn extends React.Component { const key = this.props.pivotField; doc[key] = this.getValue(this.props.heading); - FormattedTextBox.SelectOnLoad = doc[Id]; + FormattedTextBox.SetSelectOnLoad(doc); return this.props.addDocument?.(doc); }, this.props.addDocument, diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index d4daf2baf..57ea777e4 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -799,7 +799,7 @@ class StackedTimelineAnchor extends React.Component NativeHeight={returnZero} ref={action((r: DocumentView | null) => (anchor.view = r))} Document={mark} - DataDoc={undefined} + TemplateDataDocument={undefined} docViewPath={returnEmptyDoclist} pointerEvents={this.noEvents ? returnNone : undefined} styleProvider={this.props.styleProvider} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index c1333c90e..10ee01e0b 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -292,7 +292,7 @@ export class CollectionStackingView extends CollectionSubView number, count: number) { - const dataDoc = !doc.isTemplateDoc && !doc.isTemplateForField ? undefined : this.props.DataDoc; + const dataDoc = doc.isTemplateDoc || doc.isTemplateForField ? this.props.TemplateDataDocument : undefined; const height = () => this.getDocHeight(doc); const panelHeight = () => (this.isStackingView ? height() : Math.min(height(), this.props.PanelHeight())); const panelWidth = () => (this.isStackingView ? width() : this.columnWidth); @@ -323,7 +323,7 @@ export class CollectionStackingView extends CollectionSubView r?.ContentDiv && this.docRefs.set(doc, r))} Document={doc} - DataDoc={dataDoc ?? (!Doc.AreProtosEqual(doc[DocData], doc) ? doc[DocData] : undefined)} + TemplateDataDocument={dataDoc ?? (Doc.AreProtosEqual(doc[DocData], doc) ? undefined : doc[DocData])} renderDepth={this.props.renderDepth + 1} PanelWidth={panelWidth} PanelHeight={panelHeight} @@ -387,7 +387,7 @@ export class CollectionStackingView extends CollectionSubView (lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim))(NumCast(this.layoutDoc.childLimitHeight, -1)); const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!this.childFitWidth(childLayoutDoc) ? NumCast(d._width) : 0); const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!this.childFitWidth(childLayoutDoc) ? NumCast(d._height) : 0); @@ -558,7 +558,7 @@ export class CollectionStackingView extends CollectionSubView; + TemplateDataDocument: Opt; docList: Doc[]; heading: string; pivotField: string; @@ -137,7 +137,7 @@ export class CollectionStackingViewFieldColumn extends React.Component (NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading), 0); const heading = maxHeading === 0 || this.props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3; newDoc.heading = heading; - FormattedTextBox.SelectOnLoad = newDoc[Id]; + FormattedTextBox.SetSelectOnLoad(newDoc); FormattedTextBox.SelectOnLoadChar = forceEmptyNote ? '' : ' '; return this.props.addDocument?.(newDoc) || false; }; @@ -211,12 +211,12 @@ export class CollectionStackingViewFieldColumn extends React.Component { - FormattedTextBox.SelectOnLoad = doc[Id]; + FormattedTextBox.SetSelectOnLoad(doc); return this.props.addDocument?.(doc); }, this.props.addDocument, diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 43653ed75..f082ca0da 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -20,7 +20,7 @@ import { ImageUtils } from '../../util/Import & Export/ImageUtils'; import { SelectionManager } from '../../util/SelectionManager'; import { SnappingManager } from '../../util/SnappingManager'; import { undoBatch, UndoManager } from '../../util/UndoManager'; -import { DocComponent } from '../DocComponent'; +import { ViewBoxBaseComponent } from '../DocComponent'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { LoadingBox } from '../nodes/LoadingBox'; import { CollectionView, CollectionViewProps } from './CollectionView'; @@ -31,7 +31,7 @@ export interface SubCollectionViewProps extends CollectionViewProps { } export function CollectionSubView(moreProps?: X) { - class CollectionSubView extends DocComponent() { + class CollectionSubView extends ViewBoxBaseComponent() { private dropDisposer?: DragManager.DragDropDisposer; private gestureDisposer?: GestureUtils.GestureEventDisposer; protected _mainCont?: HTMLDivElement; @@ -56,14 +56,18 @@ export function CollectionSubView(moreProps?: X) { } @computed get dataDoc() { - return this.props.DataDoc instanceof Doc && this.props.Document.isTemplateForField ? Doc.GetProto(this.props.DataDoc) : this.props.Document.resolvedDataDoc ? this.props.Document : Doc.GetProto(this.props.Document); // if the layout document has a resolvedDataDoc, then we don't want to get its parent which would be the unexpanded template + return this.props.TemplateDataDocument instanceof Doc && this.props.Document.isTemplateForField + ? Doc.GetProto(this.props.TemplateDataDocument) + : this.props.Document.resolvedDataDoc + ? this.props.Document + : Doc.GetProto(this.props.Document); // if the layout document has a resolvedDataDoc, then we don't want to get its parent which would be the unexpanded template } // this returns whether either the collection is selected, or the template that it is part of is selected - rootSelected = () => this.props.isSelected() || BoolCast(this.Document.rootDocument && this.props.rootSelected?.()); + rootSelected = () => this.props.isSelected() || BoolCast(this.props.TemplateDataDocument && this.props.rootSelected?.()); - // The data field for rendering this collection will be on the this.props.Document unless we're rendering a template in which case we try to use props.DataDoc. - // When a document has a DataDoc but it's not a template, then it contains its own rendering data, but needs to pass the DataDoc through + // The data field for rendering this collection will be on the this.props.Document unless we're rendering a template in which case we try to use props.TemplateDataDocument. + // When a document has a TemplateDataDoc but it's not a template, then it contains its own rendering data, but needs to pass the TemplateDataDoc through // to its children which may be templates. // If 'annotationField' is specified, then all children exist on that field of the extension document, otherwise, they exist directly on the data document under 'fieldKey' @computed get dataField() { @@ -71,9 +75,9 @@ export function CollectionSubView(moreProps?: X) { } @computed get childLayoutPairs(): { layout: Doc; data: Doc }[] { - const { Document, DataDoc } = this.props; + const { Document, TemplateDataDocument } = this.props; const validPairs = this.childDocs - .map(doc => Doc.GetLayoutDataDocPair(Document, !this.props.isAnnotationOverlay ? DataDoc : undefined, doc)) + .map(doc => Doc.GetLayoutDataDocPair(Document, !this.props.isAnnotationOverlay ? TemplateDataDocument : undefined, doc)) .filter(pair => { // filter out any documents that have a proto that we don't have permissions to return !pair.layout?.hidden && pair.layout && (!pair.layout.proto || (pair.layout.proto instanceof Doc && GetEffectiveAcl(pair.layout.proto) !== AclPrivate)); @@ -104,8 +108,8 @@ export function CollectionSubView(moreProps?: X) { // Finally, if it's not a doc or a list and the document is a template, we try to render the root doc. // For example, if an image doc is rendered with a slide template, the template will try to render the data field as a collection. // Since the data field is actually an image, we set the list of documents to the singleton of root document's proto which will be an image. - const rootDocument = Cast(this.props.Document.rootDocument, Doc, null); - rawdocs = rootDocument && !this.props.isAnnotationOverlay ? [Doc.GetProto(rootDocument)] : []; + const templateRoot = this.props.TemplateDataDocument; + rawdocs = templateRoot && !this.props.isAnnotationOverlay ? [Doc.GetProto(templateRoot)] : []; } const childDocs = rawdocs.filter(d => !(d instanceof Promise) && GetEffectiveAcl(Doc.GetProto(d)) !== AclPrivate && (this.props.ignoreUnrendered || !d.layout_unrendered)).map(d => d as Doc); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 36ea14d92..1315decb2 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -63,7 +63,7 @@ export class CollectionTreeView extends CollectionSubView 0 && prev) { - FormattedTextBox.SelectOnLoad = prev[Id]; + FormattedTextBox.SetSelectOnLoad(prev); DocumentManager.Instance.getDocumentView(prev, this.props.DocumentView?.())?.select(false); } return true; @@ -271,7 +271,7 @@ export class CollectionTreeView extends CollectionSubView { LayoutTemplateString={this.props.keyValue ? KeyValueBox.LayoutString() : undefined} hideTitle={this.props.keyValue} Document={this._document} - DataDoc={!Doc.AreProtosEqual(this._document[DocData], this._document) ? this._document[DocData] : undefined} + TemplateDataDocument={!Doc.AreProtosEqual(this._document[DocData], this._document) ? this._document[DocData] : undefined} onBrowseClick={DocumentView.exploreMode} waitForDoubleClickToClick={this.waitForDoubleClick} isContentActive={this.isContentActive} diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 6cd111ac4..a756007f8 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -964,7 +964,6 @@ export class TreeView extends React.Component { } })} Document={this.doc} - DataDoc={undefined} // or this.dataDoc? layout_fitWidth={returnTrue} scriptContext={this} hideDecorationTitle={this.props.treeView.outlineMode} @@ -1059,7 +1058,6 @@ export class TreeView extends React.Component { key={this.doc[Id]} ref={action((r: DocumentView | null) => (this._dref = r))} Document={this.doc} - DataDoc={undefined} layout_fitWidth={this.fitWidthFilter} PanelWidth={this.embeddedPanelWidth} PanelHeight={this.embeddedPanelHeight} @@ -1249,7 +1247,7 @@ export class TreeView extends React.Component { const fieldKey = Doc.LayoutFieldKey(newParent); if (remove && fieldKey && Cast(newParent[fieldKey], listSpec(Doc)) !== undefined) { remove(child); - FormattedTextBox.SelectOnLoad = child[Id]; + FormattedTextBox.SetSelectOnLoad(child); TreeView._editTitleOnLoad = editTitle ? { id: child[Id], parent } : undefined; Doc.AddDocToList(newParent, fieldKey, child, addAfter, false); newParent.treeView_Open = true; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index fb29fb0d3..ab718c351 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -239,9 +239,9 @@ export class CollectionFreeFormView extends CollectionSubView this.screenToLocalXf.copy(); getActiveDocuments = () => this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => pair.layout); isAnyChildContentActive = () => this.props.isAnyChildContentActive(); - addLiveTextBox = (newBox: Doc) => { - FormattedTextBox.SelectOnLoad = newBox[Id]; // track the new text box so we can give it a prop that tells it to focus itself when it's displayed - this.addDocument(newBox); + addLiveTextBox = (newDoc: Doc) => { + FormattedTextBox.SetSelectOnLoad(newDoc); // track the new text box so we can give it a prop that tells it to focus itself when it's displayed + this.addDocument(newDoc); }; selectDocuments = (docs: Doc[]) => { SelectionManager.DeselectAll(); @@ -1177,7 +1177,7 @@ export class CollectionFreeFormView extends CollectionSubView { const text = Docs.Create.TextDocument('', { _width: 150, _height: 50 }); - FormattedTextBox.SelectOnLoad = text[Id]; // track the new text box so we can give it a prop that tells it to focus itself when it's displayed + FormattedTextBox.SetSelectOnLoad(text); // track the new text box so we can give it a prop that tells it to focus itself when it's displayed Doc.AddDocToList(this.props.Document, this.props.fieldKey, text); this.setLayoutList(this.addLayoutItem(this.savedLayoutList, this.makeLayoutItem(text, this.screenToCell(e.clientX, e.clientY)))); }) diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index 05ec0448b..043914985 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -253,7 +253,7 @@ export class CollectionMulticolumnView extends CollectionSubView() { return ( { fieldProps.isContentActive = this.selectedFunc; return (
- {this.selected ? : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))} + {this.selected ? : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))}
); } diff --git a/src/client/views/linking/LinkPopup.tsx b/src/client/views/linking/LinkPopup.tsx index f02a284da..a36c8d778 100644 --- a/src/client/views/linking/LinkPopup.tsx +++ b/src/client/views/linking/LinkPopup.tsx @@ -61,7 +61,6 @@ export class LinkPopup extends React.Component { { (NewLightboxView._docView = r !== null ? r : undefined))} Document={LightboxView.LightboxDoc} - DataDoc={undefined} PanelWidth={this.newLightboxWidth} PanelHeight={this.newLightboxHeight} LayoutTemplate={NewLightboxView.LightboxDocTemplate} diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index b7cd306ae..6195a155d 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -36,7 +36,7 @@ export interface CollectionFreeFormDocumentViewWrapperProps extends DocumentView CollectionFreeFormView: CollectionFreeFormView; } @observer -export class CollectionFreeFormDocumentViewWrapper extends DocComponent() implements CollectionFreeFormDocumentViewProps { +export class CollectionFreeFormDocumentViewWrapper extends DocComponent() implements CollectionFreeFormDocumentViewProps { @observable X = this.props.x; @observable Y = this.props.y; @observable Z = this.props.z; @@ -115,7 +115,7 @@ export interface CollectionFreeFormDocumentViewProps { } @observer -export class CollectionFreeFormDocumentView extends DocComponent() { +export class CollectionFreeFormDocumentView extends DocComponent() { get displayName() { // this makes mobx trace() statements more descriptive return 'CollectionFreeFormDocumentView(' + this.Document.title + ')'; } // prettier-ignore diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index b050e3252..9fd4fbcaa 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -173,7 +173,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent { @observer export class DocumentContentsView extends React.Component< - DocumentViewProps & { - setHeight?: (height: number) => void; - layout_fieldKey: string; - } + DocumentViewProps & + FieldViewProps & { + setHeight?: (height: number) => void; + layout_fieldKey: string; + } > { @computed get layout(): string { TraceMobx(); @@ -137,10 +139,6 @@ export class DocumentContentsView extends React.Component< Object.keys(prevProps).forEach(pkey => (prevProps as any)[pkey] !== (this.props as any)[pkey] && console.log(pkey + ' ' + (prevProps as any)[pkey] + ' ' + (this.props as any)[pkey])); } - get dataDoc() { - const proto = this.props.DataDoc || Doc.GetProto(this.props.Document); - return proto instanceof Promise ? undefined : proto; - } get layoutDoc() { // bcz: replaced this with below : is it correct? change was made to accommodate passing fieldKey's from a layout script // const template: Doc = this.props.LayoutTemplate?.() || Doc.Layout(this.props.Document, this.props.layout_fieldKey ? Cast(this.props.Document[this.props.layout_fieldKey], Doc, null) : undefined); @@ -163,19 +161,24 @@ export class DocumentContentsView extends React.Component< 'LayoutTemplate', 'dontCenter', 'contextMenuItems', - 'onClick', + //'onClick', // don't need to omit this since it will be set 'onDoubleClick', 'onPointerDown', 'onPointerUp', ]; - const list = { - ...OmitKeys(this.props, [...docOnlyProps], '').omit, - Document: this.layoutDoc, - DataDoc: this.dataDoc, - onClick: onClick, - onInput: onInput, + const templateDataDoc = this.props.TemplateDataDocument ?? (this.layoutDoc !== this.props.Document ? this.props.Document[DocData] : undefined); + const list: BindingProps & React.DetailedHTMLProps, HTMLDivElement> = { + ...this.props, + Document: this.layoutDoc ?? this.props.Document, + TemplateDataDocument: templateDataDoc instanceof Promise ? undefined : templateDataDoc, + onClick: onClick as any as MouseEventHandler, // pass onClick script as if it were a real function -- it will be interpreted properly in the HTMLtag + onInput: onInput as any as React.FormEventHandler, + }; + return { + props: { + ...OmitKeys(list, [...docOnlyProps], '').omit, + }, }; - return { props: list }; } // componentWillUpdate(oldProps: any, newState: any) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index b21b22cd2..977a9bc54 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -5,7 +5,7 @@ import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import { Bounce, Fade, Flip, LightSpeed, Roll, Rotate, Zoom } from 'react-reveal'; import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../fields/Doc'; -import { AclPrivate, Animation, AudioPlay, DocData, DocViews } from '../../../fields/DocSymbols'; +import { AclPrivate, Animation, AudioPlay, DocViews } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; @@ -109,7 +109,7 @@ export interface DocFocusOptions { easeFunc?: 'linear' | 'ease'; // transition method for scrolling } export type DocFocusFunc = (doc: Doc, options: DocFocusOptions) => Opt; -export type StyleProviderFunc = (doc: Opt, props: Opt, property: string) => any; +export type StyleProviderFunc = (doc: Opt, props: Opt, property: string) => any; export interface DocComponentView { updateIcon?: () => void; // updates the icon representation of the document getAnchor?: (addAsAnnotation: boolean, pinData?: PinProps) => Doc; // returns an Anchor Doc that represents the current state of the doc's componentview (e.g., the current playhead location of a an audio/video box) @@ -150,11 +150,10 @@ export interface DocComponentView { } // These props are passed to both FieldViews and DocumentViews export interface DocumentViewSharedProps { - fieldKey?: string; // only used by FieldViews but helpful here to allow styleProviders to access fieldKey of FieldViewProps. In priniciple, passing a fieldKey to a documentView could override or be the default fieldKey for fieldViews DocumentView?: () => DocumentView; renderDepth: number; Document: Doc; - DataDoc?: Doc; + TemplateDataDocument?: Doc; fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _freeform_fitContentsToBox property on a Document isGroupActive?: () => string | undefined; // is this document part of a group that is active suppressSetHeight?: boolean; @@ -506,7 +505,7 @@ export class DocumentViewInternal extends DocComponent UndoManager.RunInBatch(func, 'click ' + this.Document.title); } else { // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTemplateForField implies we're clicking on part of a template instance and we want to select the whole template, not the part - if ((this.layoutDoc.onDragStart || this.props.Document.rootDocument) && !(e.ctrlKey || e.button > 0)) { + if ((this.layoutDoc.onDragStart || this.props.TemplateDataDocument) && !(e.ctrlKey || e.button > 0)) { stopPropagate = false; // don't stop propagation for field templates -- want the selection to propagate up to the root document of the template } preventDefault = false; @@ -548,7 +547,7 @@ export class DocumentViewInternal extends DocComponent 0))) { + if ((Doc.ActiveTool === InkTool.None || this.props.addDocTab === returnFalse) && !(this.props.TemplateDataDocument && !(e.ctrlKey || e.button > 0))) { // click events stop here if the document is active and no modes are overriding it // if this is part of a template, let the event go up to the template root unless right/ctrl clicking if ( @@ -814,7 +813,7 @@ export class DocumentViewInternal extends DocComponent Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: 'concierge-bell' }); + moreItems.push({ description: 'Make View of Metadata Field', event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.TemplateDataDocument), icon: 'concierge-bell' }); moreItems.push({ description: `${this.Document._chromeHidden ? 'Show' : 'Hide'} Chrome`, event: () => (this.Document._chromeHidden = !this.Document._chromeHidden), icon: 'project-diagram' }); if (Cast(Doc.GetProto(this.props.Document).data, listSpec(Doc))) { @@ -898,7 +897,7 @@ export class DocumentViewInternal extends DocComponent this._rootSelected; panelHeight = () => this.props.PanelHeight() - this.headerMargin; @@ -938,6 +937,7 @@ export class DocumentViewInternal extends DocComponent { return Doc.Layout(this.Document, this.props.LayoutTemplate?.()); } @computed get nativeWidth() { - return this.docView?._componentView?.ignoreNativeDimScaling?.() ? 0 : returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, !this.layout_fitWidth)); + return this.docView?._componentView?.ignoreNativeDimScaling?.() ? 0 : returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.TemplateDataDocument, !this.layout_fitWidth)); } @computed get nativeHeight() { - return this.docView?._componentView?.ignoreNativeDimScaling?.() ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, !this.layout_fitWidth)); + return this.docView?._componentView?.ignoreNativeDimScaling?.() ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.TemplateDataDocument, !this.layout_fitWidth)); } @computed get shouldNotScale() { return this.props.shouldNotScale?.() || (this.layout_fitWidth && !this.nativeWidth) || [CollectionViewType.Docking].includes(this.Document._type_collection as any); diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index f7f94c546..219e3025a 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -16,7 +16,6 @@ import { DocumentViewSharedProps } from './DocumentView'; export interface FieldViewProps extends DocumentViewSharedProps { // FieldView specific props that are not part of DocumentView props fieldKey: string; - scrollOverflow?: boolean; // bcz: would like to think this can be avoided -- need to look at further select: (isCtrlPressed: boolean) => void; isContentActive: (outsideReaction?: boolean) => boolean | undefined; diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index 0c360acf0..8f6550663 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -13,7 +13,7 @@ import { SelectionManager } from '../../../util/SelectionManager'; import { SettingsManager } from '../../../util/SettingsManager'; import { undoable, UndoManager } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; -import { DocComponent } from '../../DocComponent'; +import { ViewBoxBaseComponent } from '../../DocComponent'; import { EditableView } from '../../EditableView'; import { SelectedDocView } from '../../selectedDoc'; import { StyleProp } from '../../StyleProvider'; @@ -41,7 +41,7 @@ export interface ButtonProps extends FieldViewProps { type?: ButtonType; } @observer -export class FontIconBox extends DocComponent() { +export class FontIconBox extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FontIconBox, fieldKey); } @@ -130,7 +130,7 @@ export class FontIconBox extends DocComponent() { type = 'slider'; break; } - const numScript = (value?: number) => ScriptCast(this.Document.script).script.run({ this: this.Document, self:this.Document,value, _readOnly_: value === undefined }); + const numScript = (value?: number) => ScriptCast(this.Document.script).script.run({ this: this.Document, self: this.Document, value, _readOnly_: value === undefined }); const color = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color); // Script for checking the outcome of the toggle const checkResult = Number(Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3))); @@ -157,7 +157,7 @@ export class FontIconBox extends DocComponent() { this, e, (e: PointerEvent) => { - return ScriptCast(this.Document.onDragScript)?.script.run({ this: this.Document, self:this.Document,value: { doc: value, e } }).result; + return ScriptCast(this.Document.onDragScript)?.script.run({ this: this.Document, self: this.Document, value: { doc: value, e } }).result; }, emptyFunction, emptyFunction @@ -205,7 +205,7 @@ export class FontIconBox extends DocComponent() { } noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Carousel3D, CollectionViewType.Stacking, CollectionViewType.NoteTaking]; } else { - text = script?.script.run({ this: this.Document, self:this.Document,value: '', _readOnly_: true }).result; + text = script?.script.run({ this: this.Document, self: this.Document, value: '', _readOnly_: true }).result; // text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily); getStyle = (val: string) => ({ fontFamily: val }); } @@ -223,7 +223,7 @@ export class FontIconBox extends DocComponent() { return ( script.script.run({ this: this.Document, self:this.Document,value }), `dropdown select ${this.label}`)} + setSelectedVal={undoable(value => script.script.run({ this: this.Document, self: this.Document, value }), `dropdown select ${this.label}`)} color={SettingsManager.userColor} background={SettingsManager.userVariantColor} type={Type.TERT} @@ -247,17 +247,17 @@ export class FontIconBox extends DocComponent() { */ @computed get colorButton() { const color = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color); - const curColor = this.colorScript?.script.run({ this: this.Document, self:this.Document,value: undefined, _readOnly_: true }).result ?? 'transparent'; + const curColor = this.colorScript?.script.run({ this: this.Document, self: this.Document, value: undefined, _readOnly_: true }).result ?? 'transparent'; const tooltip: string = StrCast(this.Document.toolTip); return ( { if (!this.colorBatch) this.colorBatch = UndoManager.StartBatch(`Set ${tooltip} color`); - this.colorScript?.script.run({ this: this.Document, self:this.Document, value: value, _readOnly_: false }); + this.colorScript?.script.run({ this: this.Document, self: this.Document, value: value, _readOnly_: false }); }} setFinalColor={value => { - this.colorScript?.script.run({ this: this.Document, self:this.Document,value: value, _readOnly_: false }); + this.colorScript?.script.run({ this: this.Document, self: this.Document, value: value, _readOnly_: false }); this.colorBatch?.end(); this.colorBatch = undefined; }} @@ -277,7 +277,7 @@ export class FontIconBox extends DocComponent() { const tooltip: string = StrCast(this.Document.toolTip); const script = ScriptCast(this.Document.onClick); - const toggleStatus = script ? script.script.run({ this: this.Document, self:this.Document, value: undefined, _readOnly_: true }).result : false; + const toggleStatus = script ? script.script.run({ this: this.Document, self: this.Document, value: undefined, _readOnly_: true }).result : false; // Colors const color = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color); const items = DocListCast(this.dataDoc.data); @@ -308,7 +308,7 @@ export class FontIconBox extends DocComponent() { const tooltip = StrCast(this.Document.toolTip); const script = ScriptCast(this.Document.onClick); - const toggleStatus = script ? script.script.run({ this: this.Document, self:this.Document,value: undefined, _readOnly_: true }).result : false; + const toggleStatus = script ? script.script.run({ this: this.Document, self: this.Document, value: undefined, _readOnly_: true }).result : false; // Colors const color = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color); const backgroundColor = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor); @@ -324,7 +324,7 @@ export class FontIconBox extends DocComponent() { //background={SettingsManager.userBackgroundColor} icon={this.Icon(color)!} label={this.label} - onPointerDown={() => script.script.run({ this: this.Document, self:this.Document, value: !toggleStatus, _readOnly_: false })} + onPointerDown={() => script.script.run({ this: this.Document, self: this.Document, value: !toggleStatus, _readOnly_: false })} /> ); } @@ -344,9 +344,9 @@ export class FontIconBox extends DocComponent() { // Script for running the toggle const script = ScriptCast(this.Document.script); // Function to run the script - const checkResult = script?.script.run({ this: this.Document, self:this.Document,value: '', _readOnly_: true }).result; + const checkResult = script?.script.run({ this: this.Document, self: this.Document, value: '', _readOnly_: true }).result; - const setValue = (value: string, shiftDown?: boolean): boolean => script?.script.run({ this: this.Document, self:this.Document,value, _readOnly_: false }).result; + const setValue = (value: string, shiftDown?: boolean): boolean => script?.script.run({ this: this.Document, self: this.Document, value, _readOnly_: false }).result; return {}} />; @@ -354,7 +354,7 @@ export class FontIconBox extends DocComponent() {
- script?.script.run({ this: this.Document, self:this.Document, value: '', _readOnly_: true }).result} SetValue={setValue} oneLine={true} contents={checkResult} /> + script?.script.run({ this: this.Document, self: this.Document, value: '', _readOnly_: true }).result} SetValue={setValue} oneLine={true} contents={checkResult} />
); diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 39e0279fc..577685636 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -58,7 +58,6 @@ export class KeyValuePair extends React.Component { render() { const props: FieldViewProps = { Document: this.props.doc, - DataDoc: this.props.doc, childFilters: returnEmptyFilter, childFiltersByRanges: returnEmptyFilter, searchFilterDocs: returnEmptyDoclist, diff --git a/src/client/views/nodes/LoadingBox.tsx b/src/client/views/nodes/LoadingBox.tsx index 86c91ae3c..01dd830f8 100644 --- a/src/client/views/nodes/LoadingBox.tsx +++ b/src/client/views/nodes/LoadingBox.tsx @@ -78,7 +78,7 @@ export class LoadingBox extends ViewBoxAnnotatableComponent() {
{StrCast(this.Document.title)}

{StrCast(this.Document.loadingError, 'Loading ' + (this.progress.replace('[download]', '') || '(can take several minutes)'))}

- {this.rootDDocumentoc.loadingError ? null : ( + {this.Document.loadingError ? null : (
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 14a8a387a..398d1255e 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -228,7 +228,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, undefined, annotationOn, undefined, 'yellow'); - FormattedTextBox.SelectOnLoad = target[Id]; + FormattedTextBox.SetSelectOnLoad(target); return target; }; const docView = this.props.DocumentView?.(); @@ -774,7 +774,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { setupMoveUpEvents(this, e, returnFalse, emptyFunction, e => { - const newBox = Docs.Create.TextDocument('Note', { _layout_autoHeight: true }); - FormattedTextBox.SelectOnLoad = newBox[Id]; // track the new text box so we can give it a prop that tells it to focus itself when it's displayed - Doc.AddDocToList(this.props.place, 'data', newBox); + const newDoc = Docs.Create.TextDocument('Note', { _layout_autoHeight: true }); + FormattedTextBox.SetSelectOnLoad(newDoc); // track the new text box so we can give it a prop that tells it to focus itself when it's displayed + Doc.AddDocToList(this.props.place, 'data', newDoc); this._stack?.scrollToBottom(); e.stopPropagation(); e.preventDefault(); @@ -47,9 +47,9 @@ export class MapBoxInfoWindow extends React.Component (doc instanceof Doc ? [doc] : doc).reduce((p, d) => p && Doc.RemoveDocFromList(this.props.place, 'data', d), true as boolean); render() { return ( - +
void; // x: number; // y: number; -// rootDoc: Doc; +// doc: Doc; // color: string; // } @@ -69,8 +69,8 @@ declare class MediaRecorder { // const normals = new Float32Array(quad_normals); // const uvs = new Float32Array(quad_uvs); // Each vertex has one uv coordinate for texture mapping // const indices = new Uint32Array(quad_indices); // Use the four vertices to draw the two triangles that make up the square. -// const popOut = () => NumCast(this.props.rootDoc.popOut); -// const popOff = () => NumCast(this.props.rootDoc.popOff); +// const popOut = () => NumCast(this.props.Document.popOut); +// const popOff = () => NumCast(this.props.Document.popOff); // return ( // { // this.props.setRaised([ @@ -207,7 +207,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent numberRange(this._numScreens).forEach(y => screens.push( - // ))); + // ))); // return { // this._camera = props.camera; // props.camera.position.set(this._numScreens / 2, this._numScreens / 2, this._numScreens - 2); diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 8a927560d..42e8ace6e 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -15,7 +15,7 @@ import { EditorView } from 'prosemirror-view'; import { BsMarkdownFill } from 'react-icons/bs'; import { DateField } from '../../../../fields/DateField'; import { Doc, DocListCast, Field, Opt } from '../../../../fields/Doc'; -import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DocCss, ForceServerWrite, UpdatingFromServer } from '../../../../fields/DocSymbols'; +import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DocCss, DocData, ForceServerWrite, UpdatingFromServer } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { InkTool } from '../../../../fields/InkField'; import { List } from '../../../../fields/List'; @@ -190,7 +190,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, undefined, annotationOn); - FormattedTextBox.SelectOnLoad = target[Id]; + FormattedTextBox.SetSelectOnLoad(target); return target; }; @@ -1511,10 +1514,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent>(schema: S, props: any, mapKey } const canEdit = (state: any) => { - switch (GetEffectiveAcl(props.DataDoc)) { + switch (GetEffectiveAcl(props.TemplateDataDocument)) { case AclAugment: const prevNode = state.selection.$cursor.nodeBefore; const prevUser = !prevNode ? Doc.CurrentUserEmail : prevNode.marks[prevNode.marks.length - 1].attrs.userid; @@ -334,7 +334,7 @@ export function buildKeymap>(schema: S, props: any, mapKey //Command to create a blank space bind('Space', (state: EditorState, dispatch: (tx: Transaction) => void) => { - if (props.DataDoc && GetEffectiveAcl(props.DataDoc) != AclEdit && GetEffectiveAcl(props.DataDoc) != AclAugment && GetEffectiveAcl(props.DataDoc) != AclAdmin) return true; + if (props.TemplateDataDocument && GetEffectiveAcl(props.TemplateDataDocument) != AclEdit && GetEffectiveAcl(props.TemplateDataDocument) != AclAugment && GetEffectiveAcl(props.TemplateDataDocument) != AclAdmin) return true; const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks()); dispatch(splitMetadata(marks, state.tr)); return false; diff --git a/src/client/views/nodes/importBox/ImportElementBox.tsx b/src/client/views/nodes/importBox/ImportElementBox.tsx index 170626cd2..c4c89d8b1 100644 --- a/src/client/views/nodes/importBox/ImportElementBox.tsx +++ b/src/client/views/nodes/importBox/ImportElementBox.tsx @@ -24,7 +24,6 @@ export class ImportElementBox extends ViewBoxBaseComponent() { LayoutTemplateString={undefined} Document={this.Document} isContentActive={returnFalse} - DataDoc={undefined} addDocument={returnFalse} ScreenToLocalTransform={this.screenToLocalXf} hideResizeHandles={true} diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index b104e8b70..f8aebd021 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -56,7 +56,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { // Since this node is being rendered with a template, this method retrieves // the actual slide being rendered from the auto-generated rendering template @computed get slideDoc() { - return Cast(this.Document.rootDocument, Doc, null) || this.props.Document; + return this.props.TemplateDataDocument ?? this.props.Document; } // this is the document in the workspaces that is targeted by the slide @@ -104,7 +104,6 @@ export class PresElementBox extends ViewBoxBaseComponent() {
= new Map(); + const _pendingMap = new Set(); // // Returns an expanded template layout for a target data document if there is a template relationship // between the two. If so, the layoutDoc is expanded into a new document that inherits the properties @@ -773,19 +773,19 @@ export namespace Doc { if (templateLayoutDoc.resolvedDataDoc instanceof Promise) { expandedTemplateLayout = undefined; - _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey, true); - } else if (expandedTemplateLayout === undefined && !_pendingMap.get(targetDoc[Id] + expandedLayoutFieldKey)) { - if (templateLayoutDoc.resolvedDataDoc === (targetDoc.rootDocument || Doc.GetProto(targetDoc))) { + _pendingMap.add(targetDoc[Id] + expandedLayoutFieldKey); + } else if (expandedTemplateLayout === undefined && !_pendingMap.has(targetDoc[Id] + expandedLayoutFieldKey)) { + if (templateLayoutDoc.resolvedDataDoc === (targetDoc.rootDocument ?? Doc.GetProto(targetDoc))) { expandedTemplateLayout = templateLayoutDoc; // reuse an existing template layout if its for the same document with the same params } else { templateLayoutDoc.resolvedDataDoc && (templateLayoutDoc = DocCast(templateLayoutDoc.proto, templateLayoutDoc)); // if the template has already been applied (ie, a nested template), then use the template's prototype if (!targetDoc[expandedLayoutFieldKey]) { - _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey, true); + _pendingMap.add(targetDoc[Id] + expandedLayoutFieldKey); setTimeout( action(() => { const newLayoutDoc = Doc.MakeDelegate(templateLayoutDoc, undefined, '[' + templateLayoutDoc.title + ']'); - newLayoutDoc.rootDocument = targetDoc; const dataDoc = Doc.GetProto(targetDoc); + newLayoutDoc.rootDocument = targetDoc; newLayoutDoc.embedContainer = targetDoc; newLayoutDoc.resolvedDataDoc = dataDoc; newLayoutDoc['acl-Guest'] = SharingPermissions.Edit; diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 791ce8d8f..bdd657575 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -384,7 +384,6 @@ export class MobileInterface extends React.Component {
Date: Fri, 1 Dec 2023 12:17:10 -0500 Subject: cleaning up documentview props. got rid of special cases for keyValueBox. made fitToContents work cleanly for native scaled docs. --- src/client/views/DocumentDecorations.tsx | 3 - src/client/views/MainView.tsx | 4 +- src/client/views/SidebarAnnos.tsx | 2 +- src/client/views/StyleProvider.tsx | 2 +- .../views/collections/CollectionCarousel3DView.tsx | 1 - .../views/collections/CollectionCarouselView.tsx | 36 +++++------ .../views/collections/CollectionNoteTakingView.tsx | 5 +- .../collections/CollectionStackedTimeline.tsx | 3 +- .../views/collections/CollectionStackingView.tsx | 5 +- src/client/views/collections/CollectionView.tsx | 14 ++-- src/client/views/collections/TreeView.tsx | 7 +- .../CollectionFreeFormLinkView.tsx | 4 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 21 +++--- .../collectionGrid/CollectionGridView.tsx | 1 - .../CollectionMulticolumnView.tsx | 5 +- .../CollectionMultirowView.tsx | 5 +- src/client/views/nodes/DocumentView.tsx | 75 ++++++++-------------- src/client/views/nodes/KeyValueBox.tsx | 3 +- src/client/views/nodes/LabelBox.tsx | 4 +- src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx | 4 +- 20 files changed, 84 insertions(+), 120 deletions(-) (limited to 'src/client/views/collections/CollectionCarousel3DView.tsx') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 719055149..b9fcf5360 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -611,9 +611,6 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P get selectionTitle(): string { if (SelectionManager.Views().length === 1) { const selected = SelectionManager.Views()[0]; - if (selected.ComponentView?.getTitle?.()) { - return selected.ComponentView.getTitle(); - } if (this._titleControlString.startsWith('=')) { return ScriptField.MakeFunction(this._titleControlString.substring(1), { doc: Doc.name })!.script.run({ self: selected.Document, this: selected.layoutDoc }, console.log).result?.toString() || ''; } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 2e3817cb6..58c1570b2 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -609,7 +609,7 @@ export class MainView extends React.Component { isDocumentActive={returnTrue} // headerBar is always documentActive (ie, the docView gets pointer events) isContentActive={returnTrue} // headerBar is awlays contentActive which means its items are always documentActive ScreenToLocalTransform={this.headerBarScreenXf} - childHideResizeHandles={returnTrue} + childHideResizeHandles={true} childDragAction="move" dontRegisterView={true} hideResizeHandles={true} @@ -988,7 +988,7 @@ export class MainView extends React.Component { isDocumentActive={returnTrue} // headerBar is always documentActive (ie, the docView gets pointer events) isContentActive={returnTrue} // headerBar is awlays contentActive which means its items are always documentActive ScreenToLocalTransform={Transform.Identity} - childHideResizeHandles={returnTrue} + childHideResizeHandles={true} childDragAction="move" dontRegisterView={true} PanelWidth={this.headerBarDocWidth} diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index 8e62ed999..049ba4841 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -248,7 +248,7 @@ export class SidebarAnnos extends React.Component { isAnyChildContentActive={returnFalse} childDocumentsActive={this.props.isContentActive} whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged} - childHideDecorationTitle={returnTrue} + childHideDecorationTitle={true} removeDocument={this.removeDocument} moveDocument={this.moveDocument} addDocument={this.addDocument} diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 2dd58fa80..806c9c001 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -265,7 +265,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt
@@ -59,36 +59,36 @@ export class CollectionCarouselView extends CollectionSubView() { {...this.props} NativeWidth={returnZero} NativeHeight={returnZero} - shouldNotScale={undefined} layout_fitWidth={undefined} setContentView={undefined} onDoubleClick={this.onContentDoubleClick} onClick={this.onContentClick} isDocumentActive={this.props.childDocumentsActive?.() ? this.props.isDocumentActive : this.props.isContentActive} isContentActive={this.props.childContentsActive ?? this.props.isContentActive() === false ? returnFalse : emptyFunction} - hideCaptions={show_captions ? true : false} + hideCaptions={!!carouselShowsCaptions} // hide captions if the carousel is configured to show the captions renderDepth={this.props.renderDepth + 1} LayoutTemplate={this.props.childLayoutTemplate} LayoutTemplateString={this.props.childLayoutString} Document={curDoc.layout} - TemplateDataDocument={curDoc.layout.resolvedDataDoc as Doc} + TemplateDataDocument={DocCast(curDoc.layout.resolvedDataDoc)} PanelHeight={this.panelHeight} bringToFront={returnFalse} />
-
- -
+ {!carouselShowsCaptions ? null : ( +
+ +
+ )} ); } diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index e92cb353f..ad5431c8e 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -257,9 +257,8 @@ export class CollectionNoteTakingView extends CollectionSubView() { ScreenToLocalTransform={noteTakingDocTransform} focus={this.focusDocument} childFilters={this.childDocFilters} - hideDecorationTitle={this.props.childHideDecorationTitle?.()} - hideResizeHandles={this.props.childHideResizeHandles?.()} - hideTitle={this.props.childHideTitle?.()} + hideDecorationTitle={this.props.childHideDecorationTitle} + hideResizeHandles={this.props.childHideResizeHandles} childFiltersByRanges={this.childDocRangeFilters} searchFilterDocs={this.searchFilterDocs} addDocument={this.props.addDocument} diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 57ea777e4..7fee1cda6 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -17,7 +17,6 @@ import { DragManager } from '../../util/DragManager'; import { FollowLinkScript, IsFollowLinkScript, LinkFollower } from '../../util/LinkFollower'; import { LinkManager } from '../../util/LinkManager'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; -import { SelectionManager } from '../../util/SelectionManager'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; import { undoBatch, UndoManager } from '../../util/UndoManager'; @@ -35,6 +34,7 @@ export type CollectionStackedTimelineProps = { playLink: (linkDoc: Doc, options: DocFocusOptions) => void; playFrom: (seekTimeInSeconds: number, endTime?: number) => void; playing: () => boolean; + thumbnails?: () => string[]; setTime: (time: number) => void; startTag: string; endTag: string; @@ -43,7 +43,6 @@ export type CollectionStackedTimelineProps = { rawDuration: number; dataFieldKey: string; fieldKey: string; - thumbnails?: () => string[]; }; // trimming state: shows full clip, current trim bounds, or not trimming diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 10ee01e0b..59e0c60b9 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -349,9 +349,8 @@ export class CollectionStackingView extends CollectionSubView string; childOpacity?: () => number; childContextMenuItems?: () => { script: ScriptField; label: string }[]; - childHideTitle?: () => boolean; // whether to hide the documentdecorations title for children - childHideDecorationTitle?: () => boolean; - childHideResizeHandles?: () => boolean; childLayoutTemplate?: () => Doc | undefined; // specify a layout Doc template to use for children of the collection + childHideDecorationTitle?: boolean; + childHideResizeHandles?: boolean; childDragAction?: dropActionType; childXPadding?: number; childYPadding?: number; @@ -230,8 +228,6 @@ export class CollectionView extends ViewBoxAnnotatableComponent this.props.PanelWidth(); - childHideResizeHandles = () => this.props.childHideResizeHandles?.() ?? BoolCast(this.Document.childHideResizeHandles); - childHideDecorationTitle = () => this.props.childHideDecorationTitle?.() ?? BoolCast(this.Document.childHideDecorationTitle); childLayoutTemplate = () => this.props.childLayoutTemplate?.() || Cast(this.Document.childLayoutTemplate, Doc, null); isContentActive = (outsideReaction?: boolean) => this._isContentActive; @@ -244,14 +240,14 @@ export class CollectionView extends ViewBoxAnnotatableComponent { this._disposers.selection?.(); if (!docView) { this._editTitle = false; - } else if (docView.isSelected()) { + } else if (docView.SELECTED) { this._editTitle = true; this._disposers.selection = reaction( - () => docView.isSelected(), + () => docView.SELECTED, isSel => !isSel && this.setEditTitle(undefined) ); } else { @@ -981,9 +981,8 @@ export class TreeView extends React.Component { moveDocument={this.move} removeDocument={this.props.removeDoc} ScreenToLocalTransform={this.getTransform} - NativeHeight={return18} + NativeHeight={returnZero} NativeWidth={returnZero} - shouldNotScale={returnTrue} PanelWidth={this.titleWidth} PanelHeight={return18} contextMenuItems={this.contextMenuItems} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 5e0cf1d23..0c0d45a30 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -223,8 +223,8 @@ export class CollectionFreeFormLinkView extends React.Component this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick); elementFunc = () => this._layoutElements; fitContentOnce = () => { - if (this.props.DocumentView?.().nativeWidth) return; const vals = this.fitToContentVals; this.layoutDoc._freeform_panX = vals.bounds.cx; this.layoutDoc._freeform_panY = vals.bounds.cy; this.layoutDoc._freeform_scale = vals.scale; }; freeformData = (force?: boolean) => (!this._firstRender && (this.fitContentsToBox || force) ? this.fitToContentVals : undefined); - ignoreNativeDimScaling = () => (this.fitContentsToBox ? true : false); // freeform_panx, freeform_pany, freeform_scale all attempt to get values first from the layout controller, then from the layout/dataDoc (or template layout doc), and finally from the resolved template data document. // this search order, for example, allows icons of cropped images to find the panx/pany/zoom on the cropped image's data doc instead of the usual layout doc because the zoom/panX/panY define the cropped image panX = () => this.freeformData()?.bounds.cx ?? NumCast(this.Document[this.panXFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panX, 1)); @@ -1244,7 +1244,6 @@ export class CollectionFreeFormView extends CollectionSubView ); } diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index 82f0171eb..8daed9746 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -187,7 +187,6 @@ export class CollectionGridView extends CollectionSubView() { return ( Opt; export type StyleProviderFunc = (doc: Opt, props: Opt, property: string) => any; export interface DocComponentView { + fieldKey?: string; + annotationKey?: string; updateIcon?: () => void; // updates the icon representation of the document getAnchor?: (addAsAnnotation: boolean, pinData?: PinProps) => Doc; // returns an Anchor Doc that represents the current state of the doc's componentview (e.g., the current playhead location of a an audio/video box) restoreView?: (viewSpec: Doc) => boolean; @@ -119,10 +121,8 @@ export interface DocComponentView { getView?: (doc: Doc) => Promise>; // returns a nested DocumentView for the specified doc or undefined addDocTab?: (doc: Doc, where: OpenWhere) => boolean; // determines how to add a document - used in following links to open the target ina local lightbox addDocument?: (doc: Doc | Doc[], annotationKey?: string) => boolean; // add a document (used only by collections) - ignoreNativeDimScaling?: () => boolean; // DocumentView's setup screenToLocal based on the doc having a nativeWidth/Height. However, some content views (e.g., FreeFormView w/ fitContentsToBox set) may ignore the native dimensions so this flags the DocumentView to not do Nativre scaling. select?: (ctrlKey: boolean, shiftKey: boolean) => void; focus?: (textAnchor: Doc, options: DocFocusOptions) => Opt; - menuControls?: () => JSX.Element; // controls to display in the top menu bar when the document is selected. isAnyChildContentActive?: () => boolean; // is any child content of the document active onClickScriptDisable?: () => 'never' | 'always'; // disable click scripts : never, always, or undefined = only when selected getKeyFrameEditing?: () => boolean; // whether the document is in keyframe editing mode (if it is, then all hidden documents that are not active at the keyframe time will still be shown) @@ -136,11 +136,6 @@ export interface DocComponentView { componentUI?: (boundsLeft: number, boundsTop: number) => JSX.Element | null; dragStarting?: (snapToDraggedDoc: boolean, showGroupDragTarget: boolean, visited: Set) => void; incrementalRendering?: () => void; - layout_fitWidth?: () => boolean; // whether the component always fits width (eg, KeyValueBox) - overridePointerEvents?: () => 'all' | 'none' | undefined; // if the conmponent overrides the pointer events for the document (e.g, KeyValueBox always allows pointer events) - fieldKey?: string; - annotationKey?: string; - getTitle?: () => string; getCenter?: (xf: Transform) => { X: number; Y: number }; screenBounds?: () => Opt<{ left: number; top: number; right: number; bottom: number; center?: { X: number; Y: number } }>; ptToScreen?: (pt: { X: number; Y: number }) => { X: number; Y: number }; @@ -150,28 +145,24 @@ export interface DocComponentView { } // These props are passed to both FieldViews and DocumentViews export interface DocumentViewSharedProps { - DocumentView?: () => DocumentView; renderDepth: number; Document: Doc; TemplateDataDocument?: Doc; + scriptContext?: any; // can be assigned anything and will be passed as 'scriptContext' to any OnClick script that executes on this document + DocumentView?: () => DocumentView; + CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView; fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _freeform_fitContentsToBox property on a Document isGroupActive?: () => string | undefined; // is this document part of a group that is active - suppressSetHeight?: boolean; setContentView?: (view: DocComponentView) => any; - CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView; PanelWidth: () => number; PanelHeight: () => number; - shouldNotScale?: () => boolean; docViewPath: () => DocumentView[]; - childHideDecorationTitle?: () => boolean; - childHideResizeHandles?: () => boolean; - childDragAction?: dropActionType; // allows child documents to be dragged out of collection without holding the embedKey or dragging the doc decorations title bar. + childFilters: () => string[]; + childFiltersByRanges: () => string[]; styleProvider: Opt; setTitleFocus?: () => void; focus: DocFocusFunc; layout_fitWidth?: (doc: Doc) => boolean | undefined; - childFilters: () => string[]; - childFiltersByRanges: () => string[]; searchFilterDocs: () => Doc[]; layout_showTitle?: () => string; whenChildContentsActiveChanged: (isActive: boolean) => void; @@ -184,26 +175,27 @@ export interface DocumentViewSharedProps { pinToPres: (document: Doc, pinProps: PinProps) => void; ScreenToLocalTransform: () => Transform; bringToFront: (doc: Doc, sendToBack?: boolean) => void; - dragAction?: dropActionType; + waitForDoubleClickToClick?: () => 'never' | 'always' | undefined; + defaultDoubleClick?: () => 'default' | 'ignore' | undefined; + pointerEvents?: () => Opt; treeViewDoc?: Doc; xPadding?: number; yPadding?: number; - dropAction?: dropActionType; dontRegisterView?: boolean; + childHideDecorationTitle?: boolean; + childHideResizeHandles?: boolean; + childDragAction?: dropActionType; // allows child documents to be dragged out of collection without holding the embedKey or dragging the doc decorations title bar. + dropAction?: dropActionType; + dragAction?: dropActionType; dragWhenActive?: boolean; + dontHideOnDrag?: boolean; hideLinkButton?: boolean; hideCaptions?: boolean; ignoreAutoHeight?: boolean; forceAutoHeight?: boolean; + suppressSetHeight?: boolean; disableBrushing?: boolean; // should highlighting for this view be disabled when same document in another view is hovered over. onClickScriptDisable?: 'never' | 'always'; // undefined = only when selected - waitForDoubleClickToClick?: () => 'never' | 'always' | undefined; - defaultDoubleClick?: () => 'default' | 'ignore' | undefined; - pointerEvents?: () => Opt; - scriptContext?: any; // can be assigned anything and will be passed as 'scriptContext' to any OnClick script that executes on this document - createNewFilterDoc?: () => void; - updateFilterDoc?: (doc: Doc) => void; - dontHideOnDrag?: boolean; } // these props are specific to DocuentViews @@ -217,12 +209,11 @@ export interface DocumentViewProps extends DocumentViewSharedProps { hideOpenButton?: boolean; hideDeleteButton?: boolean; hideLinkAnchors?: boolean; - isDocumentActive?: () => boolean | undefined; // whether a document should handle pointer events - isContentActive: () => boolean | undefined; // whether document contents should handle pointer events contentPointerEvents?: 'none' | 'all' | undefined; // pointer events allowed for content of a document view. eg. set to "none" in menuSidebar for sharedDocs so that you can select a document, but not interact with its contents - radialMenu?: String[]; LayoutTemplateString?: string; dontCenter?: 'x' | 'y' | 'xy'; + isDocumentActive?: () => boolean | undefined; // whether a document should handle pointer events + isContentActive: () => boolean | undefined; // whether document contents should handle pointer events NativeWidth?: () => number; NativeHeight?: () => number; NativeDimScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal NOTE: Must also be added to FieldViewProps @@ -240,8 +231,6 @@ export interface DocumentViewProps extends DocumentViewSharedProps { // these props are only available in DocumentViewIntenral export interface DocumentViewInternalProps extends DocumentViewProps { - NativeWidth: () => number; - NativeHeight: () => number; isSelected: () => boolean; select: (ctrlPressed: boolean, shiftPress?: boolean) => void; DocumentView: () => DocumentView; @@ -325,12 +314,6 @@ export class DocumentViewInternal extends DocComponent this.props.PanelHeight() - this.headerMargin; screenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -this.headerMargin); onClickFunc: any = () => (this.disableClickScriptFunc ? undefined : this.onClickHandler); - setHeight = (height: number) => (this.layoutDoc._height = height); + setHeight = (height: number) => !this.props.suppressSetHeight && (this.layoutDoc._height = height); setContentView = action((view: { getAnchor?: (addAsAnnotation: boolean) => Doc; forward?: () => boolean; back?: () => boolean }) => (this._componentView = view)); @observable _isContentActive: boolean | undefined; @@ -943,12 +926,11 @@ export class DocumentViewInternal extends DocComponent @@ -1443,15 +1425,15 @@ export class DocumentView extends React.Component { return this.docView?.LayoutFieldKey || 'layout'; } @computed get layout_fitWidth() { - return this.docView?._componentView?.layout_fitWidth?.() ?? this.props.layout_fitWidth?.(this.layoutDoc) ?? this.layoutDoc?.layout_fitWidth; + return this.props.layout_fitWidth?.(this.layoutDoc) ?? this.layoutDoc?.layout_fitWidth; } @computed get anchorViewDoc() { return this.props.LayoutTemplateString?.includes('link_anchor_2') ? DocCast(this.Document['link_anchor_2']) : this.props.LayoutTemplateString?.includes('link_anchor_1') ? DocCast(this.Document['link_anchor_1']) : undefined; } @computed get hideLinkButton() { - return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HideLinkBtn + (this.isSelected() ? ':selected' : '')); + return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HideLinkBtn + (this.SELECTED ? ':selected' : '')); } - hideLinkCount = () => this.props.renderDepth === -1 || (this.isSelected() && this.props.renderDepth) || !this._isHovering || this.hideLinkButton; + hideLinkCount = () => this.props.renderDepth === -1 || (this.SELECTED && this.props.renderDepth) || !this._isHovering || this.hideLinkButton; @computed get linkCountView() { return ; } @@ -1462,13 +1444,13 @@ export class DocumentView extends React.Component { return Doc.Layout(this.Document, this.props.LayoutTemplate?.()); } @computed get nativeWidth() { - return this.docView?._componentView?.ignoreNativeDimScaling?.() ? 0 : returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.TemplateDataDocument, !this.layout_fitWidth)); + return this.props.LayoutTemplateString?.includes(KeyValueBox.name) ? 0 : returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.TemplateDataDocument, !this.layout_fitWidth)); } @computed get nativeHeight() { - return this.docView?._componentView?.ignoreNativeDimScaling?.() ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.TemplateDataDocument, !this.layout_fitWidth)); + return this.props.LayoutTemplateString?.includes(KeyValueBox.name) ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.TemplateDataDocument, !this.layout_fitWidth)); } @computed get shouldNotScale() { - return this.props.shouldNotScale?.() || (this.layout_fitWidth && !this.nativeWidth) || [CollectionViewType.Docking].includes(this.Document._type_collection as any); + return (this.layout_fitWidth && !this.nativeWidth) || this.props.LayoutTemplateString?.includes(KeyValueBox.name) || [CollectionViewType.Docking].includes(this.Document._type_collection as any); } @computed get effectiveNativeWidth() { return this.shouldNotScale ? 0 : this.nativeWidth || NumCast(this.layoutDoc.width); @@ -1589,7 +1571,7 @@ export class DocumentView extends React.Component { docViewPathFunc = () => this.docViewPath; isSelected = () => this.SELECTED; select = (extendSelection: boolean, focusSelection?: boolean) => { - if (this.isSelected() && SelectionManager.Views().length > 1) SelectionManager.DeselectView(this); + if (this.SELECTED && SelectionManager.Views().length > 1) SelectionManager.DeselectView(this); else { SelectionManager.SelectView(this, extendSelection); if (focusSelection) { @@ -1684,7 +1666,6 @@ export class DocumentView extends React.Component { {...this.props} DocumentView={this.selfView} viewPath={this.docViewPathFunc} - shouldNotScale={this.ShouldNotScale} PanelWidth={this.PanelWidth} PanelHeight={this.PanelHeight} NativeWidth={this.NativeWidth} diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 95d2a2667..0c6377c3a 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -41,10 +41,9 @@ export class KeyValueBox extends React.Component { componentDidMount() { this.props.setContentView?.(this); } - ignoreNativeDimScaling = returnTrue; + isKeyValueBox = returnTrue; able = returnAlways; layout_fitWidth = returnTrue; - overridePointerEvents = returnAll; onClickScriptDisable = returnAlways; @observable private rows: KeyValuePair[] = []; diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx index 0d7b2b0a4..e1421878b 100644 --- a/src/client/views/nodes/LabelBox.tsx +++ b/src/client/views/nodes/LabelBox.tsx @@ -36,7 +36,7 @@ export class LabelBox extends ViewBoxBaseComponent !this.paramsDoc[p]); params?.map(p => DocListCast(this.paramsDoc[p])); // bcz: really hacky form of prefetching ... - const label = this.getTitle(); + const label = this.Title; return (
Date: Tue, 5 Dec 2023 20:29:53 -0500 Subject: mostly working version with latest libraries --- package-lock.json | 593 ++++++----------- package.json | 10 +- src/Utils.ts | 28 +- src/client/DocServer.ts | 42 +- src/client/documents/Documents.ts | 7 +- src/client/util/CurrentUserUtils.ts | 4 +- src/client/util/DragManager.ts | 34 +- src/client/util/GroupManager.tsx | 7 +- src/client/util/Scripting.ts | 31 +- src/client/util/SharingManager.tsx | 2 +- src/client/views/InkTranscription.tsx | 700 ++++++++++----------- src/client/views/InkingStroke.tsx | 4 +- src/client/views/MainView.tsx | 6 +- .../views/collections/CollectionCarousel3DView.tsx | 6 +- src/client/views/collections/TreeView.tsx | 39 +- .../views/nodes/DataVizBox/components/TableBox.tsx | 3 +- src/client/views/nodes/LinkAnchorBox.tsx | 10 +- src/debug/Test.tsx | 18 +- src/fields/Doc.ts | 20 +- src/fields/ScriptField.ts | 8 +- src/mobile/ImageUpload.tsx | 4 +- src/server/ApiManagers/DeleteManager.ts | 36 +- src/server/ApiManagers/UserManager.ts | 5 +- src/server/DashUploadUtils.ts | 2 +- src/server/RouteManager.ts | 3 +- src/server/authentication/AuthenticationManager.ts | 117 ++-- src/server/authentication/DashUserModel.ts | 7 +- src/server/authentication/Passport.ts | 35 +- src/server/database.ts | 131 ++-- src/server/server_Initialization.ts | 34 +- src/server/websocket.ts | 35 +- src/typings/index.d.ts | 1 - 32 files changed, 910 insertions(+), 1072 deletions(-) (limited to 'src/client/views/collections/CollectionCarousel3DView.tsx') diff --git a/package-lock.json b/package-lock.json index a3c9c90d4..04e615015 100644 --- a/package-lock.json +++ b/package-lock.json @@ -79,7 +79,7 @@ "express": "^4.18.2", "express-flash": "0.0.2", "express-session": "^1.17.3", - "express-validator": "^7.0.1", + "express-validator": "^5.3.1", "expressjs": "^1.0.1", "ffmpeg": "0.0.4", "file-loader": "^6.2.0", @@ -106,7 +106,6 @@ "https": "^1.0.0", "https-browserify": "^1.0.0", "i": "^0.3.7", - "iink-js": "^2.0.2", "image-data-uri": "^2.0.1", "image-size": "^1.0.2", "image-size-stream": "^1.1.0", @@ -195,8 +194,8 @@ "sass": "^1.69.5", "serializr": "^3.0.2", "shelljs": "^0.8.5", - "socket.io": "^2.5.0", - "socket.io-client": "^2.5.0", + "socket.io": "^4.7.2", + "socket.io-client": "^4.7.2", "solr-node": "^1.2.1", "standard-http-error": "^2.0.1", "stream-browserify": "^3.0.0", @@ -213,6 +212,7 @@ "uuid": "^3.4.0", "valid-url": "^1.0.9", "web-request": "^1.0.7", + "webpack": "^5.89.0", "webpack-cli": "^5.1.4", "webpack-dev-middleware": "^6.1.1", "webrtc-adapter": "^8.2.3", @@ -287,7 +287,6 @@ "@types/rimraf": "^3.0.2", "@types/sharp": "^0.31.1", "@types/shelljs": "^0.8.15", - "@types/socket.io": "^3.0.1", "@types/socket.io-client": "^1.4.36", "@types/socket.io-parser": "^3.0.0", "@types/typescript": "^2.0.0", @@ -323,7 +322,6 @@ "tslint": "^5.20.1", "tslint-loader": "^3.6.0", "typescript": "^4.7.4", - "webpack": "^5.89.0", "webpack-dev-server": "^4.15.1", "webpack-hot-middleware": "^2.25.4" } @@ -2727,8 +2725,7 @@ "node_modules/@socket.io/component-emitter": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", - "dev": true + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "node_modules/@szmarczak/http-timer": { "version": "5.0.1", @@ -2919,6 +2916,11 @@ "@types/node": "*" } }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, "node_modules/@types/cookie-parser": { "version": "1.4.6", "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.6.tgz", @@ -3214,7 +3216,6 @@ "version": "8.21.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.0.tgz", "integrity": "sha512-35EhHNOXgxnUgh4XCJsGhE7zdlDhYDN/aMG6UbkByCFFNgQ7b3U+uVoqBpicFydR8JEfgdjCF7SJ7MiJfzuiTA==", - "dev": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -3224,7 +3225,6 @@ "version": "3.7.4", "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -4033,16 +4033,6 @@ "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", "dev": true }, - "node_modules/@types/socket.io": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-3.0.2.tgz", - "integrity": "sha512-pu0sN9m5VjCxBZVK8hW37ZcMe8rjn4HHggBN5CbaRTvFwv5jOmuIRZEuddsBPa9Th0ts0SIo3Niukq+95cMBbQ==", - "deprecated": "This is a stub types definition. socket.io provides its own type definitions, so you do not need this installed.", - "dev": true, - "dependencies": { - "socket.io": "*" - } - }, "node_modules/@types/socket.io-client": { "version": "1.4.36", "resolved": "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-1.4.36.tgz", @@ -4300,7 +4290,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", - "dev": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" @@ -4309,26 +4298,22 @@ "node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", - "dev": true + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -4338,14 +4323,12 @@ "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-buffer": "1.11.6", @@ -4357,7 +4340,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -4366,7 +4348,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -4374,14 +4355,12 @@ "node_modules/@webassemblyjs/utf8": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-buffer": "1.11.6", @@ -4397,7 +4376,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", @@ -4410,7 +4388,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-buffer": "1.11.6", @@ -4422,7 +4399,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -4436,7 +4412,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@xtuc/long": "4.2.2" @@ -4505,14 +4480,12 @@ "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "node_modules/abbrev": { "version": "1.1.1", @@ -4557,7 +4530,6 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, "peerDependencies": { "acorn": "^8" } @@ -4578,11 +4550,6 @@ "node": ">=6.0" } }, - "node_modules/after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha512-QbJ0NTQ/I9DI3uSJA4cbexiwQeRAfjPScqIbSjUDd9TOrcg6pTkdgziesOqxBMBzit8vFCTwrP27t13vFOORRA==" - }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -5190,11 +5157,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" - }, "node_modules/arrify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", @@ -5559,11 +5521,6 @@ "node": ">= 10.0.0" } }, - "node_modules/backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha512-zj6Z6M7Eq+PBZ7PQxl5NT665MvJdAkzp0f60nAJ+sLaSCBPMwVak5ZegFbgVCzFcCJTKFoMizvM5Ld7+JrRJHA==" - }, "node_modules/bail": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", @@ -5633,14 +5590,6 @@ "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz", "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg=" }, - "node_modules/base64-arraybuffer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", - "integrity": "sha512-a1eIFi4R9ySrbiMuyTGx5e92uRH5tQY6kArNcFaKBUleIoLjdjBg7Zxm3Mqm3Kmkf27HLR/1fnxX9q8GQ7Iavg==", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -5773,11 +5722,6 @@ "react": ">= 16.12.0" } }, - "node_modules/blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" - }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -9295,7 +9239,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, "engines": { "node": ">=6.0" } @@ -9381,16 +9324,6 @@ "node": ">= 10" } }, - "node_modules/clipboard": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-1.7.1.tgz", - "integrity": "sha1-Ng1taUbpmnof7zleQrqStem1oWs=", - "dependencies": { - "good-listener": "^1.2.2", - "select": "^1.1.2", - "tiny-emitter": "^2.0.0" - } - }, "node_modules/cliss": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/cliss/-/cliss-0.0.2.tgz", @@ -9616,11 +9549,6 @@ "node": ">= 12" } }, - "node_modules/component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha512-WZveuKPeKAG9qY+FkYDeADzdHyTYdIboXS59ixDeRJL5ZhxpqUnxSOwop4FQjMsiYm3/Or8cegVbpAHNA7pHxw==" - }, "node_modules/component-emitter": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", @@ -9629,11 +9557,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha512-w+LhYREhatpVqTESyGFg3NlP6Iu0kEKUHETY9GoZP/pQyW4mHFZuFWRUCIqVPZ36ueVLtoOEZaAqbCF2RDndaA==" - }, "node_modules/compress-commons": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-5.0.1.tgz", @@ -10221,11 +10144,6 @@ "node": "*" } }, - "node_modules/crypto-js": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.3.0.tgz", - "integrity": "sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q==" - }, "node_modules/css-box-model": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", @@ -11215,11 +11133,6 @@ "node": ">=0.4.0" } }, - "node_modules/delegate": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", - "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" - }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -11829,58 +11742,64 @@ } }, "node_modules/engine.io": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.6.1.tgz", - "integrity": "sha512-dfs8EVg/i7QjFsXxn7cCRQ+Wai1G1TlEvHhdYEi80fxn5R1vZ2K661O6v/rezj1FP234SZ14r9CmJke99iYDGg==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.4.1", - "debug": "~4.1.0", - "engine.io-parser": "~2.2.0", - "ws": "~7.4.2" + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=10.2.0" } }, "node_modules/engine.io-client": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.3.tgz", - "integrity": "sha512-qsgyc/CEhJ6cgMUwxRRtOndGVhIu5hpL5tR4umSpmX/MvkFoIxUTM7oFMDQumHNzlNLwSVy6qhstFPoWTf7dOw==", - "dependencies": { - "component-emitter": "~1.3.0", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.2.0", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.6", - "parseuri": "0.0.6", - "ws": "~7.4.2", - "xmlhttprequest-ssl": "~1.6.2", - "yeast": "0.1.2" + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz", + "integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0", + "xmlhttprequest-ssl": "~2.0.0" } }, "node_modules/engine.io-client/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "ms": "2.0.0" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/engine.io-client/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/engine.io-client/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", "engines": { - "node": ">=8.3.0" + "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", @@ -11896,32 +11815,40 @@ } }, "node_modules/engine.io-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz", - "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==", - "dependencies": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.4", - "blob": "0.0.5", - "has-binary2": "~1.0.2" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "engines": { + "node": ">=10.0.0" } }, "node_modules/engine.io/node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "ms": "^2.1.1" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, + "node_modules/engine.io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/engine.io/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", "engines": { - "node": ">=8.3.0" + "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", @@ -11940,7 +11867,6 @@ "version": "5.15.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", - "dev": true, "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -12091,8 +12017,7 @@ "node_modules/es-module-lexer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", - "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", - "dev": true + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" }, "node_modules/es-set-tostringtag": { "version": "2.0.1", @@ -13416,7 +13341,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -13778,7 +13702,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -13790,7 +13713,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -13799,7 +13721,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, "engines": { "node": ">=4.0" } @@ -14124,15 +14045,15 @@ ] }, "node_modules/express-validator": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.0.1.tgz", - "integrity": "sha512-oB+z9QOzQIE8FnlINqyIFA8eIckahC6qc8KtqLdLJcU3/phVyuhXH3bA4qzcrhme+1RYaCSwrq+TlZ/kAKIARA==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-5.3.1.tgz", + "integrity": "sha512-g8xkipBF6VxHbO1+ksC7nxUU7+pWif0+OZXjZTybKJ/V0aTVhuCoHbyhIPgSYVldwQLocGExPtB2pE0DqK4jsw==", "dependencies": { - "lodash": "^4.17.21", - "validator": "^13.9.0" + "lodash": "^4.17.10", + "validator": "^10.4.0" }, "engines": { - "node": ">= 8.0.0" + "node": ">= 6.0.0" } }, "node_modules/express/node_modules/body-parser": { @@ -15725,8 +15646,7 @@ "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, "node_modules/global": { "version": "4.4.0", @@ -15811,14 +15731,6 @@ "resolved": "https://registry.npmjs.org/golden-layout/-/golden-layout-2.6.0.tgz", "integrity": "sha512-sIVQCiRWOymHbVD1Aw/T9/ijbPYAVGBlgGYd1N9MRKfcyBNSpjr87Vg9nSHm+RCT8ELrvK8IJYJV0QRJuVUkCQ==" }, - "node_modules/good-listener": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", - "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", - "dependencies": { - "delegate": "^3.1.2" - } - }, "node_modules/google-auth-library": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.4.1.tgz", @@ -16067,24 +15979,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", - "dependencies": { - "isarray": "2.0.1" - } - }, - "node_modules/has-binary2/node_modules/isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ==" - }, - "node_modules/has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha512-g5VNKdkFuUuVCP9gYfDJHjK2nqdQJ7aDLTnycnc2+RvsOQbuLdF5pm7vuE5J76SEBIQjs4kQY/BWq74JUmjbXA==" - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -16722,7 +16616,7 @@ "node_modules/https": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https/-/https-1.0.0.tgz", - "integrity": "sha1-PDfHrhqO65ZpBKKtHpdaGUt+06Q=" + "integrity": "sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg==" }, "node_modules/https-browserify": { "version": "1.0.0", @@ -16855,27 +16749,6 @@ "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=" }, - "node_modules/iink-js": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/iink-js/-/iink-js-2.0.2.tgz", - "integrity": "sha512-8PEHjjrgQqoZ5pmhN0do8npFmMe5KNxO1om6dLYgCUP23qgyGQZ4/69bZ33galIKuqXgYdZg0PW6EUiCM7fcSw==", - "dependencies": { - "@babel/runtime": "^7.9.2", - "clipboard": "^1.7.1", - "crypto-js": "^3.3.0", - "d3-selection": "^1.4.1", - "json-css": "^1.5.6", - "lodash.merge": "^4.6.2", - "loglevel": "^1.6.8", - "perfect-scrollbar": "^1.5.0", - "uuid-js": "^0.7.5" - } - }, - "node_modules/iink-js/node_modules/d3-selection": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz", - "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==" - }, "node_modules/image-data-uri": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/image-data-uri/-/image-data-uri-2.0.1.tgz", @@ -17012,11 +16885,6 @@ "node": ">=0.8.19" } }, - "node_modules/indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha512-i0G7hLJ1z0DE8dsqJa2rycj9dBmNKgXBvotXtZYXakU9oivfB9Uj2ZBC27qqef2U58/ZLwalxa1X/RDCdkHtVg==" - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -18089,7 +17957,6 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -18103,7 +17970,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -18112,7 +17978,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -18393,11 +18258,6 @@ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, - "node_modules/json-css": { - "version": "1.5.6", - "resolved": "https://registry.npmjs.org/json-css/-/json-css-1.5.6.tgz", - "integrity": "sha1-65ZPg0ouTqobwvaY/12wB6JsfAA=" - }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -18796,7 +18656,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, "engines": { "node": ">=6.11.5" } @@ -18883,18 +18742,6 @@ "node": ">=4" } }, - "node_modules/loglevel": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.1.tgz", - "integrity": "sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==", - "engines": { - "node": ">= 0.6.0" - }, - "funding": { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/loglevel" - } - }, "node_modules/longest-streak": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", @@ -19491,8 +19338,7 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "node_modules/merge2": { "version": "1.4.1", @@ -21261,8 +21107,7 @@ "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "node_modules/netmask": { "version": "2.0.2", @@ -24961,16 +24806,6 @@ "url": "https://ko-fi.com/killymxi" } }, - "node_modules/parseqs": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", - "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==" - }, - "node_modules/parseuri": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", - "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==" - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -25242,11 +25077,6 @@ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" }, - "node_modules/perfect-scrollbar": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.5.tgz", - "integrity": "sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g==" - }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -26181,7 +26011,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -28118,11 +27947,6 @@ "url": "https://ko-fi.com/killymxi" } }, - "node_modules/select": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", - "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" - }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -28200,7 +28024,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -28650,74 +28473,89 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/socket.io": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.5.0.tgz", - "integrity": "sha512-gGunfS0od3VpwDBpGwVkzSZx6Aqo9uOcf1afJj2cKnKFAoyl16fvhpsUhmUFd4Ldbvl5JvRQed6eQw6oQp6n8w==", + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", + "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", "dependencies": { - "debug": "~4.1.0", - "engine.io": "~3.6.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.5.0", - "socket.io-parser": "~3.4.0" + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" } }, "node_modules/socket.io-adapter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", - "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dependencies": { + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-adapter/node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } }, "node_modules/socket.io-client": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.5.0.tgz", - "integrity": "sha512-lOO9clmdgssDykiOmVQQitwBAF3I6mYcQAo7hQ7AM6Ny5X7fp8hIJ3HcQs3Rjz4SoggoxA1OgrQyY8EgTbcPYw==", - "dependencies": { - "backo2": "1.0.2", - "component-bind": "1.0.0", - "component-emitter": "~1.3.0", - "debug": "~3.1.0", - "engine.io-client": "~3.5.0", - "has-binary2": "~1.0.2", - "indexof": "0.0.1", - "parseqs": "0.0.6", - "parseuri": "0.0.6", - "socket.io-parser": "~3.3.0", - "to-array": "0.1.4" + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz", + "integrity": "sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" } }, "node_modules/socket.io-client/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "ms": "2.0.0" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/socket.io-client/node_modules/isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ==" - }, "node_modules/socket.io-client/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/socket.io-client/node_modules/socket.io-parser": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.3.tgz", - "integrity": "sha512-qOg87q1PMWWTeO01768Yh9ogn7chB9zkKtQnya41Y355S0UmpXgpcrFwAgjYJxu9BdKug5r5e9YtVSeWhKBUZg==", - "dependencies": { - "component-emitter": "~1.3.0", - "debug": "~3.1.0", - "isarray": "2.0.1" - } + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", - "dev": true, "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -28730,7 +28568,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -28746,41 +28583,29 @@ "node_modules/socket.io-parser/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/socket.io/node_modules/component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha512-jPatnhd33viNplKjqXKRkGU345p263OIWzDL2wH3LGIGp5Kojo+uXizHmOADRvhGFFTnJqX3jBAKP6vvmSDKcA==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/socket.io/node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/socket.io/node_modules/isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ==" - }, - "node_modules/socket.io/node_modules/socket.io-parser": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.3.tgz", - "integrity": "sha512-1rE4dZN3kCI/E5wixd393hmbqa78vVpkKmnEJhLeWoS/C5hbFYAbcSfnWoaVH43u9ToUVtzKjguxEZq+1XZfCQ==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "component-emitter": "1.2.1", - "debug": "~4.1.0", - "isarray": "2.0.1" + "ms": "2.1.2" }, "engines": { - "node": ">=10.0.0" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, + "node_modules/socket.io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/sockjs": { "version": "0.3.24", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", @@ -29716,7 +29541,6 @@ "version": "5.3.9", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", - "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", @@ -29783,11 +29607,6 @@ "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==" }, - "node_modules/tiny-emitter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", - "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" - }, "node_modules/tiny-inflate": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", @@ -29827,11 +29646,6 @@ "node": ">=0.6.0" } }, - "node_modules/to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha512-LhVdShQD/4Mk4zXNroIQZJC+Ap3zgLcDuwEdcmLv9CCO73NWockQDwyUnW/m8VX/EElfL6FcYx7EeutN4HJA6A==" - }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -31100,14 +30914,6 @@ "uuid": "bin/uuid" } }, - "node_modules/uuid-js": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/uuid-js/-/uuid-js-0.7.5.tgz", - "integrity": "sha1-bIhtAqU9LUDc8l2RoXC0p7JblNA=", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -31126,9 +30932,9 @@ "integrity": "sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=" }, "node_modules/validator": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", - "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==", "engines": { "node": ">= 0.10" } @@ -31262,7 +31068,6 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -31314,7 +31119,6 @@ "version": "5.89.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", - "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.0", @@ -31487,14 +31291,14 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", "dependencies": { "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", + "ajv": "^8.9.0", "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" + "ajv-keywords": "^5.1.0" }, "engines": { "node": ">= 12.13.0" @@ -31737,22 +31541,30 @@ } }, "node_modules/webpack-merge": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", "dependencies": { "clone-deep": "^4.0.1", + "flat": "^5.0.2", "wildcard": "^2.0.0" }, "engines": { "node": ">=10.0.0" } }, + "node_modules/webpack-merge/node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "bin": { + "flat": "cli.js" + } + }, "node_modules/webpack-sources": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, "engines": { "node": ">=10.13.0" } @@ -31954,9 +31766,9 @@ } }, "node_modules/wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==" }, "node_modules/with": { "version": "7.0.2", @@ -32268,9 +32080,9 @@ } }, "node_modules/xmlhttprequest-ssl": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz", - "integrity": "sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", "engines": { "node": ">=0.4.0" } @@ -32394,11 +32206,6 @@ "fd-slicer": "~1.1.0" } }, - "node_modules/yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha512-8HFIh676uyGYP6wP13R/j6OJ/1HwJ46snpvzE7aHAN3Ryqh2yX6Xox2B4CUmTwwOIzlG3Bs7ocsP5dZH/R1Qbg==" - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index 97247ad67..dad4f4bf0 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,6 @@ "@types/rimraf": "^3.0.2", "@types/sharp": "^0.31.1", "@types/shelljs": "^0.8.15", - "@types/socket.io": "^3.0.1", "@types/socket.io-client": "^1.4.36", "@types/socket.io-parser": "^3.0.0", "@types/typescript": "^2.0.0", @@ -122,7 +121,6 @@ "tslint": "^5.20.1", "tslint-loader": "^3.6.0", "typescript": "^4.7.4", - "webpack": "^5.89.0", "webpack-dev-server": "^4.15.1", "webpack-hot-middleware": "^2.25.4" }, @@ -198,7 +196,7 @@ "express": "^4.18.2", "express-flash": "0.0.2", "express-session": "^1.17.3", - "express-validator": "^7.0.1", + "express-validator": "^5.3.1", "expressjs": "^1.0.1", "ffmpeg": "0.0.4", "file-loader": "^6.2.0", @@ -225,7 +223,6 @@ "https": "^1.0.0", "https-browserify": "^1.0.0", "i": "^0.3.7", - "iink-js": "^2.0.2", "image-data-uri": "^2.0.1", "image-size": "^1.0.2", "image-size-stream": "^1.1.0", @@ -314,8 +311,8 @@ "sass": "^1.69.5", "serializr": "^3.0.2", "shelljs": "^0.8.5", - "socket.io": "^2.5.0", - "socket.io-client": "^2.5.0", + "socket.io": "^4.7.2", + "socket.io-client": "^4.7.2", "solr-node": "^1.2.1", "standard-http-error": "^2.0.1", "stream-browserify": "^3.0.0", @@ -332,6 +329,7 @@ "uuid": "^3.4.0", "valid-url": "^1.0.9", "web-request": "^1.0.7", + "webpack": "^5.89.0", "webpack-cli": "^5.1.4", "webpack-dev-middleware": "^6.1.1", "webrtc-adapter": "^8.2.3", diff --git a/src/Utils.ts b/src/Utils.ts index 38a59d524..08ddfa817 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -1,6 +1,8 @@ import * as v4 from 'uuid/v4'; import * as v5 from 'uuid/v5'; import { ColorResult } from 'react-color'; +//import { Socket } from '../node_modules/socket.io-client'; +import { Socket } from '../node_modules/socket.io/dist/index'; import * as rp from 'request-promise'; import { DocumentType } from './client/documents/DocumentTypes'; import { Colors } from './client/views/global/globalEnums'; @@ -54,6 +56,14 @@ export namespace Utils { return v5(seed, v5.URL); } + export function GenerateMongoId(id: string): string { + return id.length !== 36 ? Utils.GenerateDeterministicGuid(id) : id; + } + + export function GuestID() { + return '__guest__'; + } + /** * Uploads an image buffer to the server and stores with specified filename. by default the image * is stored at multiple resolutions each retrieved by using the filename appended with _o, _s, _m, _l (indicating original, small, medium, or large) @@ -397,14 +407,14 @@ export namespace Utils { }; } - export function Emit(socket: SocketIOClient.Socket, message: Message, args: T) { + export function Emit(socket: { emit: (msg: string, args: T) => void }, message: Message, args: T) { log('Emit', message.Name, args, false); socket.emit(message.Message, args); } - export function EmitCallback(socket: SocketIOClient.Socket, message: Message, args: T): Promise; - export function EmitCallback(socket: SocketIOClient.Socket, message: Message, args: T, fn: (args: any) => any): void; - export function EmitCallback(socket: SocketIOClient.Socket, message: Message, args: T, fn?: (args: any) => any): void | Promise { + export function EmitCallback(socket: Socket, message: Message, args: T): Promise; + export function EmitCallback(socket: Socket, message: Message, args: T, fn: (args: any) => any): void; + export function EmitCallback(socket: Socket, message: Message, args: T, fn?: (args: any) => any): void | Promise { log('Emit', message.Name, args, false); if (fn) { socket.emit(message.Message, args, loggingCallback('Receiving', fn, message.Name)); @@ -413,20 +423,20 @@ export namespace Utils { } } - export function AddServerHandler(socket: SocketIOClient.Socket, message: Message, handler: (args: T) => any) { + export function AddServerHandler(socket: { on: (event: string, cb: (args: any) => void) => void }, message: Message, handler: (args: T) => any) { socket.on(message.Message, loggingCallback('Incoming', handler, message.Name)); } - export function AddServerHandlerCallback(socket: SocketIOClient.Socket, message: Message, handler: (args: [T, (res: any) => any]) => any) { + export function AddServerHandlerCallback(socket: { on: (event: string, cb: (arg: T, fn: (res: any) => any) => void) => void }, message: Message, handler: (args: [T, (res: any) => any]) => any) { socket.on(message.Message, (arg: T, fn: (res: any) => any) => { log('S receiving', message.Name, arg, true); handler([arg, loggingCallback('S sending', fn, message.Name)]); }); } - export type RoomHandler = (socket: SocketIOClient.Socket, room: string) => any; - export type UsedSockets = SocketIOClient.Socket; + export type RoomHandler = (socket: Socket, room: string) => any; + export type UsedSockets = Socket; export type RoomMessage = 'create or join' | 'created' | 'joined'; - export function AddRoomHandler(socket: SocketIOClient.Socket, message: RoomMessage, handler: RoomHandler) { + export function AddRoomHandler(socket: Socket, message: RoomMessage, handler: RoomHandler) { socket.on(message, (room: any) => handler(socket, room)); } } diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index 353e11775..df92fe50e 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -7,6 +7,7 @@ import { HandleUpdate, Id, Parent } from '../fields/FieldSymbols'; import { ObjectField } from '../fields/ObjectField'; import { RefField } from '../fields/RefField'; import { DocCast, StrCast } from '../fields/Types'; +import { Socket } from '../../node_modules/socket.io/dist/index'; //import MobileInkOverlay from '../mobile/MobileInkOverlay'; import { emptyFunction, Utils } from '../Utils'; import { GestureContent, MessageStore, MobileDocumentUploadContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent, YoutubeQueryTypes } from './../server/Message'; @@ -76,7 +77,7 @@ export namespace DocServer { json: true, }); } - export let _socket: SocketIOClient.Socket; + export let _socket: Socket; // this client's distinct GUID created at initialization let USER_ID: string; // indicates whether or not a document is currently being udpated, and, if so, its id @@ -189,20 +190,20 @@ export namespace DocServer { Utils.AddServerHandler(_socket, MessageStore.DeleteFields, respondToDelete); Utils.AddServerHandler(_socket, MessageStore.ConnectionTerminated, alertUser); - // mobile ink overlay socket events to communicate between mobile view and desktop view - _socket.addEventListener('receiveGesturePoints', (content: GestureContent) => { - // MobileInkOverlay.Instance.drawStroke(content); - }); - _socket.addEventListener('receiveOverlayTrigger', (content: MobileInkOverlayContent) => { - //GestureOverlay.Instance.enableMobileInkOverlay(content); - // MobileInkOverlay.Instance.initMobileInkOverlay(content); - }); - _socket.addEventListener('receiveUpdateOverlayPosition', (content: UpdateMobileInkOverlayPositionContent) => { - // MobileInkOverlay.Instance.updatePosition(content); - }); - _socket.addEventListener('receiveMobileDocumentUpload', (content: MobileDocumentUploadContent) => { - // MobileInkOverlay.Instance.uploadDocument(content); - }); + // // mobile ink overlay socket events to communicate between mobile view and desktop view + // _socket.addEventListener('receiveGesturePoints', (content: GestureContent) => { + // // MobileInkOverlay.Instance.drawStroke(content); + // }); + // _socket.addEventListener('receiveOverlayTrigger', (content: MobileInkOverlayContent) => { + // //GestureOverlay.Instance.enableMobileInkOverlay(content); + // // MobileInkOverlay.Instance.initMobileInkOverlay(content); + // }); + // _socket.addEventListener('receiveUpdateOverlayPosition', (content: UpdateMobileInkOverlayPositionContent) => { + // // MobileInkOverlay.Instance.updatePosition(content); + // }); + // _socket.addEventListener('receiveMobileDocumentUpload', (content: MobileDocumentUploadContent) => { + // // MobileInkOverlay.Instance.uploadDocument(content); + // }); } function errorFunc(): never { @@ -470,10 +471,13 @@ export namespace DocServer { // to their actual RefField | undefined values. This return value either becomes the input // argument to the caller's promise (i.e. GetRefFields(["_id1_", "_id2_", "_id3_"]).then(map => //do something with map...)) // or it is the direct return result if the promise is awaited (i.e. let fields = await GetRefFields(["_id1_", "_id2_", "_id3_"])). - return ids.reduce((map, id) => { - map[id] = _cache[id] as any; - return map; - }, {} as { [id: string]: Opt }); + return ids.reduce( + (map, id) => { + map[id] = _cache[id] as any; + return map; + }, + {} as { [id: string]: Opt } + ); }; let _GetRefFields: (ids: string[]) => Promise<{ [id: string]: Opt }> = errorFunc; diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index df81e12f0..4ec100728 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -30,7 +30,6 @@ import { DimUnit } from '../views/collections/collectionMulticolumn/CollectionMu import { CollectionView } from '../views/collections/CollectionView'; import { ContextMenu } from '../views/ContextMenu'; import { ContextMenuProps } from '../views/ContextMenuItem'; -import { DFLT_IMAGE_NATIVE_DIM } from '../views/global/globalCssVariables.scss'; import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, InkingStroke } from '../views/InkingStroke'; import { AudioBox, media_state } from '../views/nodes/AudioBox'; import { ColorBox } from '../views/nodes/ColorBox'; @@ -61,6 +60,8 @@ import { VideoBox } from '../views/nodes/VideoBox'; import { WebBox } from '../views/nodes/WebBox'; import { SearchBox } from '../views/search/SearchBox'; import { CollectionViewType, DocumentType } from './DocumentTypes'; +//import { DFLT_IMAGE_NATIVE_DIM } from '../views/global/globalCssVariables.scss'; +const DFLT_IMAGE_NATIVE_DIM = '900px'; const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace('px', '')); class EmptyBox { @@ -1299,7 +1300,7 @@ export namespace DocUtils { // 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('='); + const linkedToExp = (value ?? '').split('='); if (linkedToExp.length === 1) return Field.toScriptString(anchor) === value; return Field.toScriptString(DocCast(anchor[linkedToExp[0]])) === linkedToExp[1]; }; @@ -1918,7 +1919,7 @@ export namespace DocUtils { overwriteDoc.loadingError = (result as any).message; LoadingBox.removeCurrentlyLoading(overwriteDoc); } - } else newFilename && processFileupload(generatedDocuments, newFilename, mimetype??"", result, options, overwriteDoc); + } else newFilename && processFileupload(generatedDocuments, newFilename, mimetype ?? '', result, options, overwriteDoc); }); } diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index d3ed4ca7c..8b5f23aa4 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -561,7 +561,7 @@ export class CurrentUserUtils { toolTip: "Empty recently closed",}; DocUtils.AssignDocField(recentlyClosed, "layout_headerButton", (opts) => Docs.Create.FontIconDocument(opts), clearBtnsOpts, undefined, {onClick: clearAll("this.target")}); - if (!Cast(recentlyClosed.contextMenuScripts, listSpec(ScriptField),null)?.find((script) => script.script.originalScript === clearAll("self"))) { + if (!Cast(recentlyClosed.contextMenuScripts, listSpec(ScriptField),null)?.find((script) => script?.script.originalScript === clearAll("self"))) { recentlyClosed.contextMenuScripts = new List([ScriptField.MakeScript(clearAll("self"))!]) } return recentlyClosed; @@ -946,7 +946,7 @@ export class CurrentUserUtils { runInAction(() => CurrentUserUtils.ServerVersion = result.version); Doc.CurrentUserEmail = result.email; resolvedPorts = result.resolvedPorts as any; - DocServer.init(window.location.protocol, window.location.hostname, resolvedPorts.socket, result.email); + DocServer.init(window.location.protocol, window.location.hostname, resolvedPorts?.socket, result.email); if (result.cacheDocumentIds) { const ids = result.cacheDocumentIds.split(";"); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 162a0a11f..427b1c85f 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -7,13 +7,14 @@ import { ScriptField } from '../../fields/ScriptField'; import { ScriptCast, StrCast } from '../../fields/Types'; import { emptyFunction, Utils } from '../../Utils'; import { Docs, DocUtils } from '../documents/Documents'; -import * as globalCssVariables from '../views/global/globalCssVariables.scss'; import { CollectionFreeFormDocumentView } from '../views/nodes/CollectionFreeFormDocumentView'; import { DocumentView } from '../views/nodes/DocumentView'; import { ScriptingGlobals } from './ScriptingGlobals'; import { SelectionManager } from './SelectionManager'; import { SnappingManager } from './SnappingManager'; import { UndoManager } from './UndoManager'; +// import * as globalCssVariables from '../views/global/globalCssVariables.scss'; +const contextMenuZindex = 100002; export type dropActionType = 'embed' | 'copy' | 'move' | 'add' | 'same' | 'inSame' | 'proto' | 'none' | undefined; // undefined = move, "same" = move but don't call dropPropertiesToRemove @@ -85,7 +86,16 @@ export namespace DragManager { // event called when the drag operation results in a drop action export class DropEvent { - constructor(readonly x: number, readonly y: number, readonly complete: DragCompleteEvent, readonly shiftKey: boolean, readonly altKey: boolean, readonly metaKey: boolean, readonly ctrlKey: boolean, readonly embedKey: boolean) {} + constructor( + readonly x: number, + readonly y: number, + readonly complete: DragCompleteEvent, + readonly shiftKey: boolean, + readonly altKey: boolean, + readonly metaKey: boolean, + readonly ctrlKey: boolean, + readonly embedKey: boolean + ) {} } // event called when the drag operation has completed (aborted or completed a drop) -- this will be after any drop event has been generated @@ -209,16 +219,14 @@ export namespace DragManager { !dragData.isDocDecorationMove && !dragData.userDropAction && ScriptCast(d.onDragStart) ? addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result) : docDragData.dropAction === 'embed' - ? Doc.BestEmbedding(d) - : docDragData.dropAction === 'add' - ? d - : docDragData.dropAction === 'proto' - ? Doc.GetProto(d) - : docDragData.dropAction === 'copy' - ? ( - await Doc.MakeClone(d) - ).clone - : d + ? Doc.BestEmbedding(d) + : docDragData.dropAction === 'add' + ? d + : docDragData.dropAction === 'proto' + ? Doc.GetProto(d) + : docDragData.dropAction === 'copy' + ? (await Doc.MakeClone(d)).clone + : d ) ) ).filter(d => d); @@ -428,7 +436,7 @@ export namespace DragManager { color: 'black', transition: 'none', borderRadius: getComputedStyle(ele).borderRadius, - zIndex: globalCssVariables.contextMenuZindex, + zIndex: contextMenuZindex, transformOrigin: '0 0', width, height, diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index 8973306bf..c8c93b7d0 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -52,7 +52,7 @@ export class GroupManager extends React.Component<{}> { * Fetches the list of users stored on the database. */ populateUsers = async () => { - if (Doc.UserDoc()[Id] !== '__guest__') { + if (Doc.UserDoc()[Id] !== Utils.GuestID()) { const userList = await RequestPromise.get(Utils.prepend('/getUsers')); const raw = JSON.parse(userList) as User[]; raw.map(action(user => !this.users.some(umail => umail === user.email) && this.users.push(user.email))); @@ -258,10 +258,7 @@ export class GroupManager extends React.Component<{}> { alert('Please select a unique group name'); return; } - this.createGroupDoc( - value, - this.selectedUsers?.map(user => user.value) - ); + this.createGroupDoc(value, this.selectedUsers?.map(user => user.value)); this.selectedUsers = null; this.inputRef.current!.value = ''; this.buttonColour = '#979797'; diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index 400b63a1c..b3c694024 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -120,6 +120,35 @@ class ScriptingCompilerHost { } return undefined; } + resolveModuleNames(moduleNames: string[], containingFile: string): any { + const resolvedModules: ts.ResolvedModule[] = []; + for (const moduleName of moduleNames) { + // try to use standard resolution + let result = ts.resolveModuleName( + moduleName, + containingFile, + {}, + { + fileExists: (fileName: string) => true as any, + readFile: (fileName: string) => 'true', + } + ); + if (result.resolvedModule) { + resolvedModules.push(result.resolvedModule); + } else { + // check fallback locations, for simplicity assume that module at location + // should be represented by '.d.ts' file + // for (const location of moduleSearchLocations) { + // const modulePath = path.join(location, moduleName + ".d.ts"); + // if (fileExists(modulePath)) { + // resolvedModules.push({ resolvedFileName: modulePath }); + // } + // } + } + } + return resolvedModules; + } + // getDefaultLibFileName(options: ts.CompilerOptions): string { getDefaultLibFileName(options: any): string { return 'node_modules/typescript/lib/lib.d.ts'; // No idea what this means... @@ -247,7 +276,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp const funcScript = `(function(${paramString})${reqTypes} { ${body} })`; host.writeFile('file.ts', funcScript); - if (typecheck) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib); + if (typecheck && false) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib); const program = ts.createProgram(['file.ts'], {}, host); const testResult = program.emit(); const outputText = host.readFile('file.js'); diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 34e294a4a..403f4e090 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -133,7 +133,7 @@ export class SharingManager extends React.Component<{}> { * Populates the list of validated users (this.users) by adding registered users which have a sharingDocument. */ populateUsers = async () => { - if (!this.populating && Doc.UserDoc()[Id] !== '__guest__') { + if (!this.populating && Doc.UserDoc()[Id] !== Utils.GuestID()) { this.populating = true; const userList = await RequestPromise.get(Utils.prepend('/getUsers')); const raw = (JSON.parse(userList) as User[]).filter(user => user.email !== 'guest' && user.email !== Doc.CurrentUserEmail); diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx index 17136a737..b2ac208ca 100644 --- a/src/client/views/InkTranscription.tsx +++ b/src/client/views/InkTranscription.tsx @@ -1,350 +1,350 @@ -import * as iink from 'iink-js'; -import { action, observable } from 'mobx'; -import * as React from 'react'; -import { Doc, DocListCast } from '../../fields/Doc'; -import { InkData, InkField, InkTool } from '../../fields/InkField'; -import { Cast, DateCast, NumCast } from '../../fields/Types'; -import { aggregateBounds } from '../../Utils'; -import { DocumentType } from '../documents/DocumentTypes'; -import { DocumentManager } from '../util/DocumentManager'; -import { CollectionFreeFormView } from './collections/collectionFreeForm'; -import { InkingStroke } from './InkingStroke'; -import './InkTranscription.scss'; - -/** - * Class component that handles inking in writing mode - */ -export class InkTranscription extends React.Component { - static Instance: InkTranscription; - - @observable _mathRegister: any; - @observable _mathRef: any; - @observable _textRegister: any; - @observable _textRef: any; - private lastJiix: any; - private currGroup?: Doc; - - constructor(props: Readonly<{}>) { - super(props); - - InkTranscription.Instance = this; - } - - componentWillUnmount() { - this._mathRef.removeEventListener('exported', (e: any) => this.exportInk(e, this._mathRef)); - this._textRef.removeEventListener('exported', (e: any) => this.exportInk(e, this._textRef)); - } - - @action - setMathRef = (r: any) => { - if (!this._mathRegister) { - this._mathRegister = r - ? iink.register(r, { - recognitionParams: { - type: 'MATH', - protocol: 'WEBSOCKET', - server: { - host: 'cloud.myscript.com', - applicationKey: process.env.IINKJS_APP, - hmacKey: process.env.IINKJS_HMAC, - websocket: { - pingEnabled: false, - autoReconnect: true, - }, - }, - iink: { - math: { - mimeTypes: ['application/x-latex', 'application/vnd.myscript.jiix'], - }, - export: { - jiix: { - strokes: true, - }, - }, - }, - }, - }) - : null; - } - - r?.addEventListener('exported', (e: any) => this.exportInk(e, this._mathRef)); - - return (this._mathRef = r); - }; - - @action - setTextRef = (r: any) => { - if (!this._textRegister) { - this._textRegister = r - ? iink.register(r, { - recognitionParams: { - type: 'TEXT', - protocol: 'WEBSOCKET', - server: { - host: 'cloud.myscript.com', - applicationKey: '7277ec34-0c2e-4ee1-9757-ccb657e3f89f', - hmacKey: 'f5cb18f2-1f95-4ddb-96ac-3f7c888dffc1', - websocket: { - pingEnabled: false, - autoReconnect: true, - }, - }, - iink: { - text: { - mimeTypes: ['text/plain'], - }, - export: { - jiix: { - strokes: true, - }, - }, - }, - }, - }) - : null; - } - - r?.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef)); - - return (this._textRef = r); - }; - - /** - * Handles processing Dash Doc data for ink transcription. - * - * @param groupDoc the group which contains the ink strokes we want to transcribe - * @param inkDocs the ink docs contained within the selected group - * @param math boolean whether to do math transcription or not - */ - transcribeInk = (groupDoc: Doc | undefined, inkDocs: Doc[], math: boolean) => { - if (!groupDoc) return; - const validInks = inkDocs.filter(s => s.type === DocumentType.INK); - - const strokes: InkData[] = []; - const times: number[] = []; - validInks - .filter(i => Cast(i[Doc.LayoutFieldKey(i)], InkField)) - .forEach(i => { - const d = Cast(i[Doc.LayoutFieldKey(i)], InkField, null); - const inkStroke = DocumentManager.Instance.getDocumentView(i)?.ComponentView as InkingStroke; - strokes.push(d.inkData.map(pd => inkStroke.ptToScreen({ X: pd.X, Y: pd.Y }))); - times.push(DateCast(i.author_date).getDate().getTime()); - }); - - this.currGroup = groupDoc; - - const pointerData = { events: strokes.map((stroke, i) => this.inkJSON(stroke, times[i])) }; - const processGestures = false; - - if (math) { - this._mathRef.editor.pointerEvents(pointerData, processGestures); - } else { - this._textRef.editor.pointerEvents(pointerData, processGestures); - } - }; - - /** - * Converts the Dash Ink Data to JSON. - * - * @param stroke The dash ink data - * @param time the time of the stroke - * @returns json object representation of ink data - */ - inkJSON = (stroke: InkData, time: number) => { - return { - pointerType: 'PEN', - pointerId: 1, - x: stroke.map(point => point.X), - y: stroke.map(point => point.Y), - t: new Array(stroke.length).fill(time), - p: new Array(stroke.length).fill(1.0), - }; - }; - - /** - * Creates subgroups for each word for the whole text transcription - * @param wordInkDocMap the mapping of words to ink strokes (Ink Docs) - */ - subgroupsTranscriptions = (wordInkDocMap: Map) => { - // iterate through the keys of wordInkDocMap - wordInkDocMap.forEach(async (inkDocs: Doc[], word: string) => { - const selected = inkDocs.slice(); - if (!selected) { - return; - } - const ctx = await Cast(selected[0].embedContainer, Doc); - if (!ctx) { - return; - } - const docView: CollectionFreeFormView = DocumentManager.Instance.getDocumentView(ctx)?.ComponentView as CollectionFreeFormView; - - if (!docView) return; - const marqViewRef = docView._marqueeViewRef.current; - if (!marqViewRef) return; - this.groupInkDocs(selected, docView, word); - }); - }; - - /** - * Event listener function for when the 'exported' event is heard. - * - * @param e the event objects - * @param ref the ref to the editor - */ - exportInk = (e: any, ref: any) => { - const exports = e.detail.exports; - if (exports) { - if (exports['application/x-latex']) { - const latex = exports['application/x-latex']; - if (this.currGroup) { - this.currGroup.text = latex; - this.currGroup.title = latex; - } - - ref.editor.clear(); - } else if (exports['text/plain']) { - if (exports['application/vnd.myscript.jiix']) { - this.lastJiix = JSON.parse(exports['application/vnd.myscript.jiix']); - // map timestamp to strokes - const timestampWord = new Map(); - this.lastJiix.words.map((word: any) => { - if (word.items) { - word.items.forEach((i: { id: string; timestamp: string; X: Array; Y: Array; F: Array }) => { - const ms = Date.parse(i.timestamp); - timestampWord.set(ms, word.label); - }); - } - }); - - const wordInkDocMap = new Map(); - if (this.currGroup) { - const docList = DocListCast(this.currGroup.data); - docList.forEach((inkDoc: Doc) => { - // just having the times match up and be a unique value (actual timestamp doesn't matter) - const ms = DateCast(inkDoc.author_date).getDate().getTime() + 14400000; - const word = timestampWord.get(ms); - if (!word) { - return; - } - const entry = wordInkDocMap.get(word); - if (entry) { - entry.push(inkDoc); - wordInkDocMap.set(word, entry); - } else { - const newEntry = [inkDoc]; - wordInkDocMap.set(word, newEntry); - } - }); - if (this.lastJiix.words.length > 1) this.subgroupsTranscriptions(wordInkDocMap); - } - } - const text = exports['text/plain']; - - if (this.currGroup) { - this.currGroup.transcription = text; - this.currGroup.title = text.split('\n')[0]; - } - - ref.editor.clear(); - } - } - }; - - /** - * Creates the ink grouping once the user leaves the writing mode. - */ - createInkGroup() { - // TODO nda - if document being added to is a inkGrouping then we can just add to that group - if (Doc.ActiveTool === InkTool.Write) { - CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { - // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those - const selected = ffView.unprocessedDocs; - const newCollection = this.groupInkDocs( - selected.filter(doc => doc.embedContainer), - ffView - ); - ffView.unprocessedDocs = []; - - InkTranscription.Instance.transcribeInk(newCollection, selected, false); - }); - } - CollectionFreeFormView.collectionsWithUnprocessedInk.clear(); - } - - /** - * Creates the groupings for a given list of ink docs on a specific doc view - * @param selected: the list of ink docs to create a grouping of - * @param docView: the view in which we want the grouping to be created - * @param word: optional param if the group we are creating is a word (subgrouping individual words) - * @returns a new collection Doc or undefined if the grouping fails - */ - groupInkDocs(selected: Doc[], docView: CollectionFreeFormView, word?: string): Doc | undefined { - const bounds: { x: number; y: number; width?: number; height?: number }[] = []; - - // calculate the necessary bounds from the selected ink docs - selected.map( - action(d => { - const x = NumCast(d.x); - const y = NumCast(d.y); - const width = NumCast(d._width); - const height = NumCast(d._height); - bounds.push({ x, y, width, height }); - }) - ); - - // calculate the aggregated bounds - const aggregBounds = aggregateBounds(bounds, 0, 0); - const marqViewRef = docView._marqueeViewRef.current; - - // set the vals for bounds in marqueeView - if (marqViewRef) { - marqViewRef._downX = aggregBounds.x; - marqViewRef._downY = aggregBounds.y; - marqViewRef._lastX = aggregBounds.r; - marqViewRef._lastY = aggregBounds.b; - } - - // map through all the selected ink strokes and create the groupings - selected.map( - action(d => { - const dx = NumCast(d.x); - const dy = NumCast(d.y); - delete d.x; - delete d.y; - delete d.activeFrame; - delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection - delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection - // calculate pos based on bounds - if (marqViewRef?.Bounds) { - d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2; - d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2; - } - return d; - }) - ); - docView.props.removeDocument?.(selected); - // Gets a collection based on the selected nodes using a marquee view ref - const newCollection = marqViewRef?.getCollection(selected, undefined, true); - if (newCollection) { - newCollection.width = NumCast(newCollection._width); - newCollection.height = NumCast(newCollection._height); - // if the grouping we are creating is an individual word - if (word) { - newCollection.title = word; - } - } - - // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs - newCollection && docView.props.addDocument?.(newCollection); - return newCollection; - } - - render() { - return ( -
-
-
-
- ); - } -} +// import * as iink from 'iink-js'; +// import { action, observable } from 'mobx'; +// import * as React from 'react'; +// import { Doc, DocListCast } from '../../fields/Doc'; +// import { InkData, InkField, InkTool } from '../../fields/InkField'; +// import { Cast, DateCast, NumCast } from '../../fields/Types'; +// import { aggregateBounds } from '../../Utils'; +// import { DocumentType } from '../documents/DocumentTypes'; +// import { DocumentManager } from '../util/DocumentManager'; +// import { CollectionFreeFormView } from './collections/collectionFreeForm'; +// import { InkingStroke } from './InkingStroke'; +// import './InkTranscription.scss'; + +// /** +// * Class component that handles inking in writing mode +// */ +// export class InkTranscription extends React.Component { +// static Instance: InkTranscription; + +// @observable _mathRegister: any; +// @observable _mathRef: any; +// @observable _textRegister: any; +// @observable _textRef: any; +// private lastJiix: any; +// private currGroup?: Doc; + +// constructor(props: Readonly<{}>) { +// super(props); + +// InkTranscription.Instance = this; +// } + +// componentWillUnmount() { +// this._mathRef.removeEventListener('exported', (e: any) => this.exportInk(e, this._mathRef)); +// this._textRef.removeEventListener('exported', (e: any) => this.exportInk(e, this._textRef)); +// } + +// @action +// setMathRef = (r: any) => { +// if (!this._mathRegister) { +// this._mathRegister = r +// ? iink.register(r, { +// recognitionParams: { +// type: 'MATH', +// protocol: 'WEBSOCKET', +// server: { +// host: 'cloud.myscript.com', +// applicationKey: process.env.IINKJS_APP, +// hmacKey: process.env.IINKJS_HMAC, +// websocket: { +// pingEnabled: false, +// autoReconnect: true, +// }, +// }, +// iink: { +// math: { +// mimeTypes: ['application/x-latex', 'application/vnd.myscript.jiix'], +// }, +// export: { +// jiix: { +// strokes: true, +// }, +// }, +// }, +// }, +// }) +// : null; +// } + +// r?.addEventListener('exported', (e: any) => this.exportInk(e, this._mathRef)); + +// return (this._mathRef = r); +// }; + +// @action +// setTextRef = (r: any) => { +// if (!this._textRegister) { +// this._textRegister = r +// ? iink.register(r, { +// recognitionParams: { +// type: 'TEXT', +// protocol: 'WEBSOCKET', +// server: { +// host: 'cloud.myscript.com', +// applicationKey: '7277ec34-0c2e-4ee1-9757-ccb657e3f89f', +// hmacKey: 'f5cb18f2-1f95-4ddb-96ac-3f7c888dffc1', +// websocket: { +// pingEnabled: false, +// autoReconnect: true, +// }, +// }, +// iink: { +// text: { +// mimeTypes: ['text/plain'], +// }, +// export: { +// jiix: { +// strokes: true, +// }, +// }, +// }, +// }, +// }) +// : null; +// } + +// r?.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef)); + +// return (this._textRef = r); +// }; + +// /** +// * Handles processing Dash Doc data for ink transcription. +// * +// * @param groupDoc the group which contains the ink strokes we want to transcribe +// * @param inkDocs the ink docs contained within the selected group +// * @param math boolean whether to do math transcription or not +// */ +// transcribeInk = (groupDoc: Doc | undefined, inkDocs: Doc[], math: boolean) => { +// if (!groupDoc) return; +// const validInks = inkDocs.filter(s => s.type === DocumentType.INK); + +// const strokes: InkData[] = []; +// const times: number[] = []; +// validInks +// .filter(i => Cast(i[Doc.LayoutFieldKey(i)], InkField)) +// .forEach(i => { +// const d = Cast(i[Doc.LayoutFieldKey(i)], InkField, null); +// const inkStroke = DocumentManager.Instance.getDocumentView(i)?.ComponentView as InkingStroke; +// strokes.push(d.inkData.map(pd => inkStroke.ptToScreen({ X: pd.X, Y: pd.Y }))); +// times.push(DateCast(i.author_date).getDate().getTime()); +// }); + +// this.currGroup = groupDoc; + +// const pointerData = { events: strokes.map((stroke, i) => this.inkJSON(stroke, times[i])) }; +// const processGestures = false; + +// if (math) { +// this._mathRef.editor.pointerEvents(pointerData, processGestures); +// } else { +// this._textRef.editor.pointerEvents(pointerData, processGestures); +// } +// }; + +// /** +// * Converts the Dash Ink Data to JSON. +// * +// * @param stroke The dash ink data +// * @param time the time of the stroke +// * @returns json object representation of ink data +// */ +// inkJSON = (stroke: InkData, time: number) => { +// return { +// pointerType: 'PEN', +// pointerId: 1, +// x: stroke.map(point => point.X), +// y: stroke.map(point => point.Y), +// t: new Array(stroke.length).fill(time), +// p: new Array(stroke.length).fill(1.0), +// }; +// }; + +// /** +// * Creates subgroups for each word for the whole text transcription +// * @param wordInkDocMap the mapping of words to ink strokes (Ink Docs) +// */ +// subgroupsTranscriptions = (wordInkDocMap: Map) => { +// // iterate through the keys of wordInkDocMap +// wordInkDocMap.forEach(async (inkDocs: Doc[], word: string) => { +// const selected = inkDocs.slice(); +// if (!selected) { +// return; +// } +// const ctx = await Cast(selected[0].embedContainer, Doc); +// if (!ctx) { +// return; +// } +// const docView: CollectionFreeFormView = DocumentManager.Instance.getDocumentView(ctx)?.ComponentView as CollectionFreeFormView; + +// if (!docView) return; +// const marqViewRef = docView._marqueeViewRef.current; +// if (!marqViewRef) return; +// this.groupInkDocs(selected, docView, word); +// }); +// }; + +// /** +// * Event listener function for when the 'exported' event is heard. +// * +// * @param e the event objects +// * @param ref the ref to the editor +// */ +// exportInk = (e: any, ref: any) => { +// const exports = e.detail.exports; +// if (exports) { +// if (exports['application/x-latex']) { +// const latex = exports['application/x-latex']; +// if (this.currGroup) { +// this.currGroup.text = latex; +// this.currGroup.title = latex; +// } + +// ref.editor.clear(); +// } else if (exports['text/plain']) { +// if (exports['application/vnd.myscript.jiix']) { +// this.lastJiix = JSON.parse(exports['application/vnd.myscript.jiix']); +// // map timestamp to strokes +// const timestampWord = new Map(); +// this.lastJiix.words.map((word: any) => { +// if (word.items) { +// word.items.forEach((i: { id: string; timestamp: string; X: Array; Y: Array; F: Array }) => { +// const ms = Date.parse(i.timestamp); +// timestampWord.set(ms, word.label); +// }); +// } +// }); + +// const wordInkDocMap = new Map(); +// if (this.currGroup) { +// const docList = DocListCast(this.currGroup.data); +// docList.forEach((inkDoc: Doc) => { +// // just having the times match up and be a unique value (actual timestamp doesn't matter) +// const ms = DateCast(inkDoc.author_date).getDate().getTime() + 14400000; +// const word = timestampWord.get(ms); +// if (!word) { +// return; +// } +// const entry = wordInkDocMap.get(word); +// if (entry) { +// entry.push(inkDoc); +// wordInkDocMap.set(word, entry); +// } else { +// const newEntry = [inkDoc]; +// wordInkDocMap.set(word, newEntry); +// } +// }); +// if (this.lastJiix.words.length > 1) this.subgroupsTranscriptions(wordInkDocMap); +// } +// } +// const text = exports['text/plain']; + +// if (this.currGroup) { +// this.currGroup.transcription = text; +// this.currGroup.title = text.split('\n')[0]; +// } + +// ref.editor.clear(); +// } +// } +// }; + +// /** +// * Creates the ink grouping once the user leaves the writing mode. +// */ +// createInkGroup() { +// // TODO nda - if document being added to is a inkGrouping then we can just add to that group +// if (Doc.ActiveTool === InkTool.Write) { +// CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { +// // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those +// const selected = ffView.unprocessedDocs; +// const newCollection = this.groupInkDocs( +// selected.filter(doc => doc.embedContainer), +// ffView +// ); +// ffView.unprocessedDocs = []; + +// InkTranscription.Instance.transcribeInk(newCollection, selected, false); +// }); +// } +// CollectionFreeFormView.collectionsWithUnprocessedInk.clear(); +// } + +// /** +// * Creates the groupings for a given list of ink docs on a specific doc view +// * @param selected: the list of ink docs to create a grouping of +// * @param docView: the view in which we want the grouping to be created +// * @param word: optional param if the group we are creating is a word (subgrouping individual words) +// * @returns a new collection Doc or undefined if the grouping fails +// */ +// groupInkDocs(selected: Doc[], docView: CollectionFreeFormView, word?: string): Doc | undefined { +// const bounds: { x: number; y: number; width?: number; height?: number }[] = []; + +// // calculate the necessary bounds from the selected ink docs +// selected.map( +// action(d => { +// const x = NumCast(d.x); +// const y = NumCast(d.y); +// const width = NumCast(d._width); +// const height = NumCast(d._height); +// bounds.push({ x, y, width, height }); +// }) +// ); + +// // calculate the aggregated bounds +// const aggregBounds = aggregateBounds(bounds, 0, 0); +// const marqViewRef = docView._marqueeViewRef.current; + +// // set the vals for bounds in marqueeView +// if (marqViewRef) { +// marqViewRef._downX = aggregBounds.x; +// marqViewRef._downY = aggregBounds.y; +// marqViewRef._lastX = aggregBounds.r; +// marqViewRef._lastY = aggregBounds.b; +// } + +// // map through all the selected ink strokes and create the groupings +// selected.map( +// action(d => { +// const dx = NumCast(d.x); +// const dy = NumCast(d.y); +// delete d.x; +// delete d.y; +// delete d.activeFrame; +// delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection +// delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection +// // calculate pos based on bounds +// if (marqViewRef?.Bounds) { +// d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2; +// d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2; +// } +// return d; +// }) +// ); +// docView.props.removeDocument?.(selected); +// // Gets a collection based on the selected nodes using a marquee view ref +// const newCollection = marqViewRef?.getCollection(selected, undefined, true); +// if (newCollection) { +// newCollection.width = NumCast(newCollection._width); +// newCollection.height = NumCast(newCollection._height); +// // if the grouping we are creating is an individual word +// if (word) { +// newCollection.title = word; +// } +// } + +// // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs +// newCollection && docView.props.addDocument?.(newCollection); +// return newCollection; +// } + +// render() { +// return ( +//
+//
+//
+//
+// ); +// } +// } diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 13df352e3..41a2507f9 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -36,7 +36,6 @@ import { Transform } from '../util/Transform'; import { UndoManager } from '../util/UndoManager'; import { ContextMenu } from './ContextMenu'; import { ViewBoxBaseComponent } from './DocComponent'; -import { INK_MASK_SIZE } from './global/globalCssVariables.scss'; import { Colors } from './global/globalEnums'; import { InkControlPtHandles, InkEndPtHandles } from './InkControlPtHandles'; import './InkStroke.scss'; @@ -47,7 +46,8 @@ import { FieldView, FieldViewProps } from './nodes/FieldView'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { PinProps, PresBox } from './nodes/trails'; import { StyleProp } from './StyleProvider'; -import Color = require('color'); +// import { INK_MASK_SIZE } from './global/globalCssVariables.scss'; +const INK_MASK_SIZE = 1000; @observer export class InkingStroke extends ViewBoxBaseComponent() { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 53182497c..1408e3124 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -43,7 +43,6 @@ import { DashboardView } from './DashboardView'; import { DictationOverlay } from './DictationOverlay'; import { DocumentDecorations } from './DocumentDecorations'; import { GestureOverlay } from './GestureOverlay'; -import { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } from './global/globalCssVariables.scss'; import { KeyManager } from './GlobalKeyHandler'; import { InkTranscription } from './InkTranscription'; import { LightboxView } from './LightboxView'; @@ -71,6 +70,9 @@ import { PreviewCursor } from './PreviewCursor'; import { PropertiesView } from './PropertiesView'; import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider'; import { TopBar } from './topbar/TopBar'; +// import { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } from './global/globalCssVariables.scss'; +const LEFT_MENU_WIDTH = '60px'; +const TOPBAR_HEIGHT = '37px'; const _global = (window /* browser */ || global) /* node */ as any; @observer @@ -1063,7 +1065,7 @@ export class MainView extends React.Component { - + {/* */} {this.snapLines} diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index d6368464a..330cb93e4 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -10,11 +10,13 @@ import { DocumentType } from '../../documents/DocumentTypes'; import { DragManager } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; import { StyleProp } from '../StyleProvider'; -import { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } from '../global/globalCssVariables.scss'; import { DocFocusOptions, DocumentView } from '../nodes/DocumentView'; import './CollectionCarousel3DView.scss'; import { CollectionSubView } from './CollectionSubView'; - +// import { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } from '../global/globalCssVariables.scss'; +const CAROUSEL3D_CENTER_SCALE = '1'; +const CAROUSEL3D_SIDE_SCALE = '1'; +const CAROUSEL3D_TOP = '0'; @observer export class CollectionCarousel3DView extends CollectionSubView() { @computed get scrollSpeed() { diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index b5666b917..ac79e4fef 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -24,7 +24,6 @@ import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; import { undoable, undoBatch, UndoManager } from '../../util/UndoManager'; import { EditableView } from '../EditableView'; -import { TREE_BULLET_WIDTH } from '../global/globalCssVariables.scss'; import { DocumentView, DocumentViewInternal, DocumentViewProps, OpenWhere, StyleProviderFunc } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; @@ -36,6 +35,8 @@ import { CollectionView } from './CollectionView'; import { TreeSort } from './TreeSort'; import './TreeView.scss'; import * as React from 'react'; +// import { TREE_BULLET_WIDTH } from '../global/globalCssVariables.scss'; +const TREE_BULLET_WIDTH = '10px'; export interface TreeViewProps { treeView: CollectionTreeView; @@ -118,16 +119,16 @@ export class TreeView extends React.Component { return this.doc._type_collection === CollectionViewType.Docking ? this.fieldKey : this.props.treeView.dashboardMode - ? this.fieldKey - : this.props.treeView.fileSysMode - ? this.doc.isFolder - ? this.fieldKey - : 'data' // file system folders display their contents (data). used to be they displayed their embeddings but now its a tree structure and not a flat list - : this.props.treeView.outlineMode || this.childDocs - ? this.fieldKey - : Doc.noviceMode - ? 'layout' - : StrCast(this.props.treeView.doc.treeView_ExpandedView, 'fields'); + ? this.fieldKey + : this.props.treeView.fileSysMode + ? this.doc.isFolder + ? this.fieldKey + : 'data' // file system folders display their contents (data). used to be they displayed their embeddings but now its a tree structure and not a flat list + : this.props.treeView.outlineMode || this.childDocs + ? this.fieldKey + : Doc.noviceMode + ? 'layout' + : StrCast(this.props.treeView.doc.treeView_ExpandedView, 'fields'); } @computed get doc() { @@ -832,14 +833,14 @@ export class TreeView extends React.Component { ...(this.doc.isFolder ? folderOp : Doc.IsSystem(this.doc) - ? [] - : this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc) - ? [openEmbedding, makeFolder] - : this.doc._type_collection === CollectionViewType.Docking - ? [] - : this.props.treeView.Document === Doc.MyRecentlyClosed - ? [reopenDoc] - : [openEmbedding, focusDoc]), + ? [] + : this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc) + ? [openEmbedding, makeFolder] + : this.doc._type_collection === CollectionViewType.Docking + ? [] + : this.props.treeView.Document === Doc.MyRecentlyClosed + ? [reopenDoc] + : [openEmbedding, focusDoc]), ]; }; childContextMenuItems = () => { diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx index 9ac06cf3c..d422a7536 100644 --- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx +++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx @@ -10,8 +10,9 @@ import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../../Utils'; import { DragManager } from '../../../../util/DragManager'; import { DocumentView } from '../../DocumentView'; import { DataVizView } from '../DataVizBox'; -import { DATA_VIZ_TABLE_ROW_HEIGHT } from '../../../global/globalCssVariables.scss'; import './Chart.scss'; +//import { DATA_VIZ_TABLE_ROW_HEIGHT } from '../../../global/globalCssVariables.scss'; +const DATA_VIZ_TABLE_ROW_HEIGHT = '30px'; interface TableBoxProps { Document: Doc; diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index d10cbac5e..1b5161e47 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -13,8 +13,8 @@ import { FieldView, FieldViewProps } from './FieldView'; import './LinkAnchorBox.scss'; import { LinkDocPreview } from './LinkDocPreview'; import * as React from 'react'; -import globalCssVariables = require('../global/globalCssVariables.scss'); - +// import globalCssVariables = require('../global/globalCssVariables.scss'); +const MEDIUM_GRAY = 'lightGray'; @observer export class LinkAnchorBox extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string) { @@ -77,8 +77,8 @@ export class LinkAnchorBox extends ViewBoxBaseComponent() { const selView = SelectionManager.Views().lastElement()?.props.LayoutTemplateString?.includes('link_anchor_1') ? 'link_anchor_1' : SelectionManager.Views().lastElement()?.props.LayoutTemplateString?.includes('link_anchor_2') - ? 'link_anchor_2' - : ''; + ? 'link_anchor_2' + : ''; return (
() { onPointerDown={this.onPointerDown} onContextMenu={this.specificContextMenu} style={{ - border: selView && this.dataDoc[selView] === this.dataDoc[this.fieldKey] ? `solid ${globalCssVariables.MEDIUM_GRAY} 2px` : undefined, + border: selView && this.dataDoc[selView] === this.dataDoc[this.fieldKey] ? `solid ${MEDIUM_GRAY} 2px` : undefined, background, left: `calc(${x}% - ${small ? 2.5 : 7.5}px)`, top: `calc(${y}% - ${small ? 2.5 : 7.5}px)`, diff --git a/src/debug/Test.tsx b/src/debug/Test.tsx index 17d3db8fd..c906dcc03 100644 --- a/src/debug/Test.tsx +++ b/src/debug/Test.tsx @@ -1,13 +1,11 @@ import * as React from 'react'; -import * as ReactDOM from 'react-dom'; -import { DocServer } from '../client/DocServer'; -import { Doc } from '../fields/Doc'; -import * as Pdfjs from "pdfjs-dist"; -import "pdfjs-dist/web/pdf_viewer.css"; -import { Utils } from '../Utils'; -const PDFJSViewer = require("pdfjs-dist/web/pdf_viewer"); - -const protoId = "protoDoc"; -const delegateId = "delegateDoc"; +import * as ReactDOM from 'react-dom/client'; +console.log('ENTERED'); class Test extends React.Component { + render() { + return
HELLO WORLD
; + } } +const root = ReactDOM.createRoot(document.getElementById('root')!); + +root.render(); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 525ff7ec0..d441dafec 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -30,7 +30,7 @@ import { ComputedField, ScriptField } from './ScriptField'; import { BoolCast, Cast, DocCast, FieldValue, NumCast, StrCast, ToConstructor } from './Types'; import { AudioField, CsvField, ImageField, PdfField, VideoField, WebField } from './URLField'; import { containedFieldChangedHandler, deleteProperty, GetEffectiveAcl, getField, getter, makeEditable, makeReadOnly, setter, SharingPermissions } from './util'; -import JSZip = require('jszip'); +import * as JSZip from 'jszip'; export const LinkedTo = '-linkedTo'; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -816,7 +816,7 @@ export namespace Doc { } export function FindReferences(infield: Doc | List, references: Set, system: boolean | undefined) { - if (infield instanceof List) { + if (!(infield instanceof Doc)) { infield.forEach(val => (val instanceof Doc || val instanceof List) && FindReferences(val, references, system)); return; } @@ -1201,14 +1201,14 @@ export namespace Doc { return !doc ? undefined : doc.isTemplateDoc - ? doc - : Cast(doc.dragFactory, Doc, null)?.isTemplateDoc - ? doc.dragFactory - : Cast(Doc.Layout(doc), Doc, null)?.isTemplateDoc - ? Cast(Doc.Layout(doc), Doc, null).resolvedDataDoc - ? Doc.Layout(doc).proto - : Doc.Layout(doc) - : undefined; + ? doc + : Cast(doc.dragFactory, Doc, null)?.isTemplateDoc + ? doc.dragFactory + : Cast(Doc.Layout(doc), Doc, null)?.isTemplateDoc + ? Cast(Doc.Layout(doc), Doc, null).resolvedDataDoc + ? Doc.Layout(doc).proto + : Doc.Layout(doc) + : undefined; } export function deiconifyView(doc: Doc) { diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts index cd07a8885..03dc71c48 100644 --- a/src/fields/ScriptField.ts +++ b/src/fields/ScriptField.ts @@ -45,12 +45,12 @@ const scriptSchema = createSimpleSchema({ function finalizeScript(script: ScriptField) { const comp = CompileScript(script.script.originalScript, script.script.options); if (!comp.compiled) { - throw new Error("Couldn't compile loaded script"); + // throw new Error("Couldn't compile loaded script"); } if (script.setterscript) { const compset = CompileScript(script.setterscript?.originalScript, script.setterscript.options); if (!compset.compiled) { - throw new Error("Couldn't compile setter script"); + // throw new Error("Couldn't compile setter script"); } (script as any).setterscript = compset; } @@ -97,7 +97,7 @@ export class ScriptField extends ObjectField { constructor(script: CompiledScript | undefined, setterscript?: CompiledScript, rawscript?: string) { super(); - const captured = script?.options.capturedVariables; + const captured = script?.options?.capturedVariables; if (captured) { this.captures = new List(Object.keys(captured).map(key => key + ':' + (captured[key] instanceof Doc ? 'ID->' + (captured[key] as Doc)[Id] : captured[key].toString()))); } @@ -151,7 +151,7 @@ export class ComputedField extends ScriptField { _lastComputedResult: any; //TODO maybe add an observable cache based on what is passed in for doc, considering there shouldn't really be that many possible values for doc value = computedFn((doc: Doc) => this._valueOutsideReaction(doc)); - _valueOutsideReaction = (doc: Doc) => (this._lastComputedResult = this.script.run({ this: doc, self: doc, value: '', _last_: this._lastComputedResult, _readOnly_: true }, console.log).result); + _valueOutsideReaction = (doc: Doc) => (this._lastComputedResult = this.script.compiled && this.script.run({ this: doc, self: doc, value: '', _last_: this._lastComputedResult, _readOnly_: true }, console.log).result); [ToValue](doc: Doc) { return ComputedField.toValue(doc, this); diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index fd119e0bf..ee212e4af 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -5,7 +5,6 @@ import * as rp from 'request-promise'; import { DocServer } from '../client/DocServer'; import { Docs } from '../client/documents/Documents'; import { Networking } from '../client/Network'; -import { DFLT_IMAGE_NATIVE_DIM } from '../client/views/global/globalCssVariables.scss'; import { MainViewModal } from '../client/views/MainViewModal'; import { Doc, Opt } from '../fields/Doc'; import { List } from '../fields/List'; @@ -15,7 +14,8 @@ import { Utils } from '../Utils'; import './ImageUpload.scss'; import { MobileInterface } from './MobileInterface'; import * as React from 'react'; - +//import { DFLT_IMAGE_NATIVE_DIM } from '../client/views/global/globalCssVariables.scss'; +const DFLT_IMAGE_NATIVE_DIM = '50px'; export interface ImageUploadProps { Document: Doc; // Target document for upload (upload location) } diff --git a/src/server/ApiManagers/DeleteManager.ts b/src/server/ApiManagers/DeleteManager.ts index 56d8aff60..c6c4ca464 100644 --- a/src/server/ApiManagers/DeleteManager.ts +++ b/src/server/ApiManagers/DeleteManager.ts @@ -1,21 +1,19 @@ -import ApiManager, { Registration } from "./ApiManager"; -import { Method, _permission_denied } from "../RouteManager"; -import { WebSocket } from "../websocket"; -import { Database } from "../database"; -import { rimraf } from "rimraf"; -import { filesDirectory } from ".."; -import { DashUploadUtils } from "../DashUploadUtils"; -import { mkdirSync } from "fs"; -import RouteSubscriber from "../RouteSubscriber"; +import ApiManager, { Registration } from './ApiManager'; +import { Method, _permission_denied } from '../RouteManager'; +import { WebSocket } from '../websocket'; +import { Database } from '../database'; +import { rimraf } from 'rimraf'; +import { filesDirectory } from '..'; +import { DashUploadUtils } from '../DashUploadUtils'; +import { mkdirSync } from 'fs'; +import RouteSubscriber from '../RouteSubscriber'; export default class DeleteManager extends ApiManager { - protected initialize(register: Registration): void { - register({ method: Method.GET, requireAdminInRelease: true, - subscription: new RouteSubscriber("delete").add("target?"), + subscription: new RouteSubscriber('delete').add('target?'), secureHandler: async ({ req, res }) => { const { target } = req.params; @@ -24,12 +22,12 @@ export default class DeleteManager extends ApiManager { } else { let all = false; switch (target) { - case "all": + case 'all': all = true; - case "database": + case 'database': await WebSocket.doDelete(false); if (!all) break; - case "files": + case 'files': rimraf.sync(filesDirectory); mkdirSync(filesDirectory); await DashUploadUtils.buildFileDirectories(); @@ -39,10 +37,8 @@ export default class DeleteManager extends ApiManager { } } - res.redirect("/home"); - } + res.redirect('/home'); + }, }); - } - -} \ No newline at end of file +} diff --git a/src/server/ApiManagers/UserManager.ts b/src/server/ApiManagers/UserManager.ts index 9252202b0..0d36ee957 100644 --- a/src/server/ApiManagers/UserManager.ts +++ b/src/server/ApiManagers/UserManager.ts @@ -7,6 +7,7 @@ import { Opt } from '../../fields/Doc'; import { WebSocket } from '../websocket'; import { resolvedPorts } from '../server_Initialization'; import { DashVersion } from '../../fields/DocSymbols'; +import { Utils } from '../../Utils'; export const timeMap: { [id: string]: number } = {}; interface ActivityUnit { @@ -49,7 +50,7 @@ export default class UserManager extends ApiManager { method: Method.GET, subscription: '/getUserDocumentIds', secureHandler: ({ res, user }) => res.send({ userDocumentId: user.userDocumentId, linkDatabaseId: user.linkDatabaseId, sharingDocumentId: user.sharingDocumentId }), - publicHandler: ({ res }) => res.send({ userDocumentId: '__guest__', linkDatabaseId: 3, sharingDocumentId: 2 }), + publicHandler: ({ res }) => res.send({ userDocumentId: Utils.GuestID(), linkDatabaseId: 3, sharingDocumentId: 2 }), }); register({ @@ -81,7 +82,7 @@ export default class UserManager extends ApiManager { resolvedPorts, }) ), - publicHandler: ({ res }) => res.send(JSON.stringify({ id: '__guest__', email: 'guest' })), + publicHandler: ({ res }) => res.send(JSON.stringify({ userDocumentId: Utils.GuestID(), email: 'guest', resolvedPorts })), }); register({ diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index 643626ae9..2bea15915 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -200,7 +200,7 @@ export namespace DashUploadUtils { const category = types[0]; let format = `.${types[1]}`; - console.log(green(`Processing upload of file (${name}) and format (${format}) with upload type (${type}) in category (${category}).`)); + console.log(green(`Processing upload of file (${originalFilename}) and format (${format}) with upload type (${type}) in category (${category}).`)); switch (category) { case 'image': diff --git a/src/server/RouteManager.ts b/src/server/RouteManager.ts index 5683cd539..540bca776 100644 --- a/src/server/RouteManager.ts +++ b/src/server/RouteManager.ts @@ -1,6 +1,7 @@ import { cyan, green, red } from 'colors'; import { Express, Request, Response } from 'express'; import { AdminPriviliges } from '.'; +import { Utils } from '../Utils'; import { DashUserModel } from './authentication/DashUserModel'; import RouteSubscriber from './RouteSubscriber'; @@ -102,7 +103,7 @@ export default class RouteManager { let user = req.user as Partial | undefined; const { originalUrl: target } = req; if (process.env.DB === 'MEM' && !user) { - user = { id: 'guest', email: 'guest', userDocumentId: '__guest__' }; + user = { id: 'guest', email: 'guest', userDocumentId: Utils.GuestID() }; } const core = { req, res, isRelease }; const tryExecute = async (toExecute: (args: any) => any | Promise, args: any) => { diff --git a/src/server/authentication/AuthenticationManager.ts b/src/server/authentication/AuthenticationManager.ts index 74d8d2523..5bc6e96b4 100644 --- a/src/server/authentication/AuthenticationManager.ts +++ b/src/server/authentication/AuthenticationManager.ts @@ -46,7 +46,7 @@ export let postSignup = (req: Request, res: Response, next: NextFunction) => { const model = { email, password, - userDocumentId: email === 'guest' ? '__guest__' : Utils.GenerateGuid(), + userDocumentId: email === 'guest' ? Utils.GuestID() : Utils.GenerateGuid(), sharingDocumentId: email === 'guest' ? 2 : Utils.GenerateGuid(), linkDatabaseId: email === 'guest' ? 3 : Utils.GenerateGuid(), cacheDocumentIds: '', @@ -54,25 +54,21 @@ export let postSignup = (req: Request, res: Response, next: NextFunction) => { const user = new User(model); - User.findOne({ email }, (err: any, existingUser: any) => { - if (err) { - return next(err); - } - if (existingUser) { - return res.redirect('/login'); - } - user.save().then(undefined, (err: any) => { - if (err) { - return next(err); + User.findOne({ email }) + .then(existingUser => { + if (existingUser) { + return res.redirect('/login'); } - req.logIn(user, err => { - if (err) { - return next(err); - } - tryRedirectToTarget(req, res); - }); - }); - }); + user.save() + .then(() => { + req.logIn(user, err => { + if (err) return next(err); + tryRedirectToTarget(req, res); + }); + }) + .catch(err => next(err)); + }) + .catch(err => next(err)); }; const tryRedirectToTarget = (req: Request, res: Response) => { @@ -106,7 +102,9 @@ export let getLogin = (req: Request, res: Response) => { */ export let postLogin = (req: Request, res: Response, next: NextFunction) => { if (req.body.email === '') { - User.findOne({ email: 'guest' }, (err: any, user: DashUserModel) => !user && initializeGuest()); + User.findOne({ email: 'guest' }) + .then(user => !user && initializeGuest()) + .catch(err => err); req.body.email = 'guest'; req.body.password = 'guest'; } else { @@ -146,14 +144,7 @@ export let postLogin = (req: Request, res: Response, next: NextFunction) => { */ export let getLogout = (req: Request, res: Response) => { req.logout(emptyFunction); - const sess = req.session; - if (sess) { - sess.destroy(err => { - if (err) { - console.log(err); - } - }); - } + req.session?.destroy(err => err && console.log(err)); res.redirect('/login'); }; @@ -178,7 +169,7 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio }); }, function (token: string, done: any) { - User.findOne({ email }, function (err: any, user: DashUserModel) { + User.findOne({ email }).then(user => { if (!user) { // NO ACCOUNT WITH SUBMITTED EMAIL res.redirect('/forgotPassword'); @@ -186,9 +177,7 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio } user.passwordResetToken = token; user.passwordResetExpires = new Date(Date.now() + 3600000); // 1 HOUR - user.save().then(undefined, (err: any) => { - done(null, token, user); - }); + user.save().then(() => done(null, token, user)); }); }, function (token: Uint16Array, user: DashUserModel, done: any) { @@ -227,50 +216,43 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio }; export let getReset = function (req: Request, res: Response) { - User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }, function (err: any, user: DashUserModel) { - if (!user || err) { - return res.redirect('/forgotPassword'); - } - res.render('reset.pug', { - title: 'Reset Password', - user: req.user, - }); - }); + User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }) + .then(user => { + if (!user) return res.redirect('/forgotPassword'); + res.render('reset.pug', { + title: 'Reset Password', + user: req.user, + }); + }) + .catch(err => res.redirect('/forgotPassword')); }; export let postReset = function (req: Request, res: Response) { async.waterfall( [ function (done: any) { - User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }, function (err: any, user: DashUserModel) { - if (!user || err) { - return res.redirect('back'); - } + User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }) + .then(user => { + if (!user) return res.redirect('back'); - req.assert('password', 'Password must be at least 4 characters long').len({ min: 4 }); - req.assert('confirmPassword', 'Passwords do not match').equals(req.body.password); + req.assert('password', 'Password must be at least 4 characters long').len({ min: 4 }); + req.assert('confirmPassword', 'Passwords do not match').equals(req.body.password); - if (req.validationErrors()) { - return res.redirect('back'); - } + if (req.validationErrors()) return res.redirect('back'); - user.password = req.body.password; - user.passwordResetToken = undefined; - user.passwordResetExpires = undefined; + user.password = req.body.password; + user.passwordResetToken = undefined; + user.passwordResetExpires = undefined; - user.save().then(undefined, (err:any) => { - if (err) { - res.redirect('/login'); - return; - } - req.logIn(user, function (err) { - if (err) { - return; - } - }); + user.save() + .then( + () => (req as any).logIn(user), + (err: any) => err + ) + .catch(err => res.redirect('/login')); done(null, user); - }); - }); + }) + .catch(err => res.redirect('back')); }, function (user: DashUserModel, done: any) { const smtpTransport = nodemailer.createTransport({ @@ -286,9 +268,8 @@ export let postReset = function (req: Request, res: Response) { subject: 'Your password has been changed', text: 'Hello,\n\n' + 'This is a confirmation that the password for your account ' + user.email + ' has just been changed.\n', } as MailOptions; - smtpTransport.sendMail(mailOptions, function (err) { - done(null, err); - }); + + smtpTransport.sendMail(mailOptions, err => done(null, err)); }, ], function (err) { diff --git a/src/server/authentication/DashUserModel.ts b/src/server/authentication/DashUserModel.ts index a1883beab..dbb7a79ed 100644 --- a/src/server/authentication/DashUserModel.ts +++ b/src/server/authentication/DashUserModel.ts @@ -2,6 +2,7 @@ import * as bcrypt from 'bcrypt-nodejs'; //@ts-ignore import * as mongoose from 'mongoose'; +import { Utils } from '../../Utils'; export type DashUserModel = mongoose.Document & { email: String; @@ -25,7 +26,7 @@ export type DashUserModel = mongoose.Document & { comparePassword: comparePasswordFunction; }; -type comparePasswordFunction = (candidatePassword: string, cb: (err: any, isMatch: any) => {}) => void; +type comparePasswordFunction = (candidatePassword: string, cb: (err: any, isMatch: any) => void) => void; export type AuthToken = { accessToken: string; @@ -63,7 +64,7 @@ const userSchema = new mongoose.Schema( * Password hash middleware. */ userSchema.pre('save', function save(next) { - const user = this as DashUserModel; + const user = this as any as DashUserModel; if (!user.isModified('password')) { return next(); } @@ -101,7 +102,7 @@ export function initializeGuest() { new User({ email: 'guest', password: 'guest', - userDocumentId: '__guest__', + userDocumentId: Utils.GuestID(), sharingDocumentId: '2', linkDatabaseId: '3', cacheDocumentIds: '', diff --git a/src/server/authentication/Passport.ts b/src/server/authentication/Passport.ts index d7f891c34..a9cf6698b 100644 --- a/src/server/authentication/Passport.ts +++ b/src/server/authentication/Passport.ts @@ -1,6 +1,6 @@ import * as passport from 'passport'; import * as passportLocal from 'passport-local'; -import { default as User } from './DashUserModel'; +import { DashUserModel, default as User } from './DashUserModel'; const LocalStrategy = passportLocal.Strategy; @@ -9,21 +9,24 @@ passport.serializeUser((req, user, done) => { }); passport.deserializeUser((id, done) => { - User.findById(id, (err: any, user: any) => { - done(err, user); - }); + User.findById(id) + .exec() + .then(user => done(undefined, user)); }); // AUTHENTICATE JUST WITH EMAIL AND PASSWORD -passport.use(new LocalStrategy({ usernameField: 'email', passReqToCallback: true }, (req, email, password, done) => { - User.findOne({ email: email.toLowerCase() }, (error: any, user: any) => { - if (error) return done(error); - if (!user) return done(undefined, false, { message: "Invalid email or password" }); // invalid email - user.comparePassword(password, (error: Error, isMatch: boolean) => { - if (error) return done(error); - if (!isMatch) return done(undefined, false, { message: "Invalid email or password" }); // invalid password - // valid authentication HERE - return done(undefined, user); - }); - }); -})); \ No newline at end of file +passport.use( + new LocalStrategy({ usernameField: 'email', passReqToCallback: true }, (req, email, password, done) => { + User.findOne({ email: email.toLowerCase() }) + .then(user => { + if (!user) return done(undefined, false, { message: 'Invalid email or password' }); // invalid email + (user as any as DashUserModel).comparePassword(password, (error: Error, isMatch: boolean) => { + if (error) return done(error); + if (!isMatch) return done(undefined, false, { message: 'Invalid email or password' }); // invalid password + // valid authentication HERE + return done(undefined, user); + }); + }) + .catch(error => done(error)); + }) +); diff --git a/src/server/database.ts b/src/server/database.ts index 37bc00a85..0893bfd35 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -7,11 +7,14 @@ import { DocumentsCollection, IDatabase } from './IDatabase'; import { MemoryDatabase } from './MemoryDatabase'; import { Transferable } from './Message'; import { Upload } from './SharedMediaTypes'; -import { ObjectId } from 'mongodb'; export namespace Database { - export let disconnect: Function; + + class DocSchema implements mongodb.BSON.Document { + _id!: string; + id!: string; + } const schema = 'Dash'; const port = 27017; export const url = `mongodb://localhost:${port}/${schema}`; @@ -36,11 +39,11 @@ export namespace Database { resolve(); }); mongoose.connect(url, { - //useNewUrlParser: true, + //useNewUrlParser: true, dbName: schema, // reconnectTries: Number.MAX_VALUE, // reconnectInterval: 1000, - }); + }); }); } } catch (e) { @@ -60,10 +63,10 @@ export namespace Database { async doConnect() { console.error(`\nConnecting to Mongo with URL : ${url}\n`); return new Promise(resolve => { - this.MongoClient.connect(url, { connectTimeoutMS: 30000, socketTimeoutMS: 30000, }).then(client => { - console.error("mongo connect response\n"); + this.MongoClient.connect(url, { connectTimeoutMS: 30000, socketTimeoutMS: 30000 }).then(client => { + console.error('mongo connect response\n'); if (!client) { - console.error("\nMongo connect failed with the error:\n"); + console.error('\nMongo connect failed with the error:\n'); process.exit(0); } this.db = client.db(); @@ -75,18 +78,18 @@ export namespace Database { public async update(id: string, value: any, callback: (err: mongodb.MongoError, res: mongodb.UpdateResult) => void, upsert = true, collectionName = DocumentsCollection) { if (this.db) { - const collection = this.db.collection(collectionName); + const collection = this.db.collection(collectionName); const prom = this.currentWrites[id]; let newProm: Promise; const run = (): Promise => { return new Promise(resolve => { - collection.updateOne({ _id: new ObjectId(id) }, value, { upsert }).then(res => { - if (this.currentWrites[id] === newProm) { - delete this.currentWrites[id]; - } - resolve(); - callback(undefined as any, res); - }); + collection.updateOne({ _id: id }, value, { upsert }).then(res => { + if (this.currentWrites[id] === newProm) { + delete this.currentWrites[id]; + } + resolve(); + callback(undefined as any, res); + }); }); }; newProm = prom ? prom.then(run) : run(); @@ -99,18 +102,18 @@ export namespace Database { public replace(id: string, value: any, callback: (err: mongodb.MongoError, res: mongodb.UpdateResult) => void, upsert = true, collectionName = DocumentsCollection) { if (this.db) { - const collection = this.db.collection(collectionName); + const collection = this.db.collection(collectionName); const prom = this.currentWrites[id]; let newProm: Promise; const run = (): Promise => { return new Promise(resolve => { - collection.replaceOne({ _id: new ObjectId(id)}, value, { upsert }).then( res => { - if (this.currentWrites[id] === newProm) { - delete this.currentWrites[id]; - } - resolve(); - callback(undefined as any, res as any); - }); + collection.replaceOne({ _id: id }, value, { upsert }).then(res => { + if (this.currentWrites[id] === newProm) { + delete this.currentWrites[id]; + } + resolve(); + callback(undefined as any, res as any); + }); }); }; newProm = prom ? prom.then(run) : run(); @@ -135,12 +138,17 @@ export namespace Database { public delete(query: any, collectionName?: string): Promise; public delete(id: string, collectionName?: string): Promise; public delete(id: any, collectionName = DocumentsCollection) { - if (typeof id === "string") { - id = { _id: new ObjectId(id) }; + if (typeof id === 'string') { + id = { _id: id }; } if (this.db) { const db = this.db; - return new Promise(res => db.collection(collectionName).deleteMany(id).then(result => res(result))); + return new Promise(res => + db + .collection(collectionName) + .deleteMany(id) + .then(result => res(result)) + ); } else { return new Promise(res => this.onConnect.push(() => res(this.delete(id, collectionName)))); } @@ -167,12 +175,12 @@ export namespace Database { public async insert(value: any, collectionName = DocumentsCollection) { if (this.db && value !== null) { - if ("id" in value) { + if ('id' in value) { value._id = value.id; delete value.id; } const id = value._id; - const collection = this.db.collection(collectionName); + const collection = this.db.collection(collectionName); const prom = this.currentWrites[id]; let newProm: Promise; const run = (): Promise => { @@ -195,11 +203,12 @@ export namespace Database { public getDocument(id: string, fn: (result?: Transferable) => void, collectionName = DocumentsCollection) { if (this.db) { - this.db.collection(collectionName).findOne({ _id: new ObjectId(id) }).then(result => { + const collection = this.db.collection(collectionName); + collection.findOne({ _id: id }).then(result => { if (result) { result.id = result._id; //delete result._id; - fn(result.id); + fn(result as any); } else { fn(undefined); } @@ -209,19 +218,19 @@ export namespace Database { } } - public getDocuments(ids: string[], fn: (result: Transferable[]) => void, collectionName = DocumentsCollection) { + public async getDocuments(ids: string[], fn: (result: Transferable[]) => void, collectionName = DocumentsCollection) { if (this.db) { - this.db.collection(collectionName).find({ _id: { "$in": ids.map(id => new ObjectId(id)) } }).map(docs => { - // if (err) { - // console.log(err.message); - // console.log(err.errmsg); - // } - fn(docs.map((doc:any) => { + const found = await this.db + .collection(collectionName) + .find({ _id: { $in: ids } }) + .toArray(); + fn( + found.map((doc: any) => { doc.id = doc._id; delete doc._id; return doc; - })); - }); + }) + ); } else { this.onConnect.push(() => this.getDocuments(ids, fn, collectionName)); } @@ -256,7 +265,7 @@ export namespace Database { public query(query: { [key: string]: any }, projection?: { [key: string]: 0 | 1 }, collectionName = DocumentsCollection): Promise { if (this.db) { - let cursor = this.db.collection(collectionName).find(query); + let cursor = this.db.collection(collectionName).find(query); if (projection) { cursor = cursor.project(projection); } @@ -271,7 +280,12 @@ export namespace Database { public updateMany(query: any, update: any, collectionName = DocumentsCollection) { if (this.db) { const db = this.db; - return new Promise(res => db.collection(collectionName).updateMany(query, update).then(result => res(result))); + return new Promise(res => + db + .collection(collectionName) + .updateMany(query, update) + .then(result => res(result)) + ); } else { return new Promise(res => { this.onConnect.push(() => this.updateMany(query, update, collectionName).then(res)); @@ -280,13 +294,13 @@ export namespace Database { } public print() { - console.log("db says hi!"); + console.log('db says hi!'); } } function getDatabase() { switch (process.env.DB) { - case "MEM": + case 'MEM': return new MemoryDatabase(); default: return new Database(); @@ -301,13 +315,12 @@ export namespace Database { * or Dash-internal user data. */ export namespace Auxiliary { - /** * All the auxiliary MongoDB collections (schemas) */ export enum AuxiliaryCollections { - GooglePhotosUploadHistory = "uploadedFromGooglePhotos", - GoogleAccess = "googleAuthentication", + GooglePhotosUploadHistory = 'uploadedFromGooglePhotos', + GoogleAccess = 'googleAuthentication', } /** @@ -319,16 +332,18 @@ export namespace Database { const cursor = await Instance.query(query, undefined, collection); const results = await cursor.toArray(); const slice = results.slice(0, Math.min(cap, results.length)); - return removeId ? slice.map((result:any) => { - delete result._id; - return result; - }) : slice; + return removeId + ? slice.map((result: any) => { + delete result._id; + return result; + }) + : slice; }; /** * Searches for the @param query in the specified @param collection, * and returns at most the first result. If @param removeId is true, - * as it is by default, each object will be stripped of its database id. + * as it is by default, each object will be stripped of its database id. * Worth the special case since it converts the Array return type to a single * object of the specified type. */ @@ -338,7 +353,7 @@ export namespace Database { }; /** - * Checks to see if an image with the given @param contentSize + * Checks to see if an image with the given @param contentSize * already exists in the aux database, i.e. has already been downloaded from Google Photos. */ export const QueryUploadHistory = async (contentSize: number) => { @@ -352,7 +367,7 @@ export namespace Database { export const LogUpload = async (information: Upload.ImageInformation) => { const bundle = { _id: Utils.GenerateDeterministicGuid(String(information.contentSize)), - ...information + ...information, }; return Instance.insert(bundle, AuxiliaryCollections.GooglePhotosUploadHistory); }; @@ -362,7 +377,6 @@ export namespace Database { * facilitates interactions with all their APIs for a given account. */ export namespace GoogleAccessToken { - /** * Format stored in database. */ @@ -370,7 +384,7 @@ export namespace Database { /** * Retrieves the credentials associaed with @param userId - * and optionally removes their database id according to @param removeId. + * and optionally removes their database id according to @param removeId. */ export const Fetch = async (userId: string, removeId = true): Promise> => { return SanitizedSingletonQuery({ userId }, AuxiliaryCollections.GoogleAccess, removeId); @@ -378,7 +392,7 @@ export namespace Database { /** * Writes the @param enrichedCredentials to the database, associated - * with @param userId for later retrieval and updating. + * with @param userId for later retrieval and updating. */ export const Write = async (userId: string, enrichedCredentials: GoogleApiServerUtils.EnrichedCredentials) => { return Instance.insert({ userId, canAccess: [], ...enrichedCredentials }, AuxiliaryCollections.GoogleAccess); @@ -397,7 +411,7 @@ export namespace Database { }; /** - * Revokes the credentials associated with @param userId. + * Revokes the credentials associated with @param userId. */ export const Revoke = async (userId: string) => { const entry = await Fetch(userId, false); @@ -405,9 +419,6 @@ export namespace Database { Instance.delete({ _id: entry._id }, AuxiliaryCollections.GoogleAccess); } }; - } - } - } diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts index af8b8dfdd..a4deaa744 100644 --- a/src/server/server_Initialization.ts +++ b/src/server/server_Initialization.ts @@ -1,13 +1,10 @@ import * as bodyParser from 'body-parser'; import { blue, yellow } from 'colors'; -import * as cookieParser from 'cookie-parser'; import * as cors from 'cors'; import * as express from 'express'; import * as session from 'express-session'; import * as expressValidator from 'express-validator'; -import * as fs from 'fs'; -import { Server as HttpServer } from 'http'; -import { createServer, Server as HttpsServer } from 'https'; +import { createServer } from 'https'; import * as passport from 'passport'; import * as request from 'request'; import * as webpack from 'webpack'; @@ -22,10 +19,10 @@ import { Database } from './database'; import RouteManager from './RouteManager'; import RouteSubscriber from './RouteSubscriber'; import { WebSocket } from './websocket'; -import * as brotli from 'brotli'; import * as expressFlash from 'express-flash'; import * as flash from 'connect-flash'; -import * as MongoStoreConnect from 'connect-mongo'; +import * as brotli from 'brotli'; +import * as MongoStoreConnect from 'connect-mongo'; import * as config from '../../webpack.config'; /* RouteSetter is a wrapper around the server that prevents the server @@ -41,29 +38,21 @@ export default async function InitializeServer(routeSetter: RouteSetter) { const app = buildWithMiddleware(express()); const compiler = webpack(config as any); - app.use( - require('webpack-dev-middleware')(compiler, { - publicPath: config.output.publicPath, - }) - ); - - app.use(require('webpack-hot-middleware')(compiler)); - // route table managed by express. routes are tested sequentially against each of these map rules. when a match is found, the handler is called to process the request + app.use(wdm(compiler, { publicPath: config.output.publicPath })); + app.use(whm(compiler)); app.get(new RegExp(/^\/+$/), (req, res) => res.redirect(req.user ? '/home' : '/login')); // target urls that consist of one or more '/'s with nothing in between app.use(express.static(publicDirectory, { setHeaders: res => res.setHeader('Access-Control-Allow-Origin', '*') })); //all urls that start with dash's public directory: /files/ (e.g., /files/images, /files/audio, etc) app.use(cors({ origin: (_origin: any, callback: any) => callback(null, true) })); - app.use(wdm(compiler, { publicPath: config.output.publicPath })); - app.use(whm(compiler)); registerAuthenticationRoutes(app); // this adds routes to authenticate a user (login, etc) registerCorsProxy(app); // this adds a /corsProxy/ route to allow clients to get to urls that would otherwise be blocked by cors policies isRelease && !SSL.Loaded && SSL.exit(); routeSetter(new RouteManager(app, isRelease)); // this sets up all the regular supervised routes (things like /home, download/upload api's, pdf, search, session, etc) registerEmbeddedBrowseRelativePathHandler(app); // this allows renered web pages which internally have relative paths to find their content - let server: HttpServer | HttpsServer; isRelease && process.env.serverPort && (resolvedPorts.server = Number(process.env.serverPort)); - await new Promise(resolve => (server = isRelease ? createServer(SSL.Credentials, app).listen(resolvedPorts.server, resolve) : app.listen(resolvedPorts.server, resolve))); + const server = isRelease ? createServer(SSL.Credentials, app) : app; + await new Promise(resolve => server.listen(resolvedPorts.server, resolve)); logPort('server', resolvedPorts.server); resolvedServerUrl = `${isRelease && process.env.serverName ? `https://${process.env.serverName}.com` : 'http://localhost'}:${resolvedPorts.server}`; @@ -78,26 +67,27 @@ export default async function InitializeServer(routeSetter: RouteSetter) { const week = 7 * 24 * 60 * 60 * 1000; const secret = '64d6866242d3b5a5503c675b32c9605e4e90478e9b77bcf2bc'; +const store = process.env.DB === 'MEM' || true ? new session.MemoryStore() : MongoStoreConnect.create({ mongoUrl: Database.url }); function buildWithMiddleware(server: express.Express) { [ - cookieParser(), session({ secret, resave: true, cookie: { maxAge: week }, saveUninitialized: true, - store: process.env.DB === 'MEM' ? new session.MemoryStore() : MongoStoreConnect.create({ mongoUrl: Database.url }), + store, }), flash(), expressFlash(), bodyParser.json({ limit: '10mb' }), bodyParser.urlencoded({ extended: true }), - expressValidator.body, + expressValidator(), // adds functions (e.g., assert()) to 'req' that help validate the request in the route handling methods passport.initialize(), passport.session(), (req: express.Request, res: express.Response, next: express.NextFunction) => { res.locals.user = req.user; + console.log('HEADER:' + req.originalUrl + ' path = ' + req.path); if ((req.originalUrl.endsWith('.png') || req.originalUrl.endsWith('.jpg') || (process.env.RELEASE === 'true' && req.originalUrl.endsWith('.js'))) && req.method === 'GET') { const period = 30000; res.set('Cache-control', `public, max-age=${period}`); @@ -108,7 +98,7 @@ function buildWithMiddleware(server: express.Express) { next(); }, ].forEach(next => server.use(next)); - + return server; } diff --git a/src/server/websocket.ts b/src/server/websocket.ts index 4453001b0..a26b81bdf 100644 --- a/src/server/websocket.ts +++ b/src/server/websocket.ts @@ -1,10 +1,8 @@ import { blue } from 'colors'; import * as express from 'express'; -import { createServer, Server } from 'https'; +import { createServer } from 'https'; +import { Server, Socket } from '../../node_modules/socket.io/dist/index'; import { networkInterfaces } from 'os'; -import * as sio from 'socket.io'; -import * as _socket from 'socket.io'; -import { Opt } from '../fields/Doc'; import { Utils } from '../Utils'; import { logPort } from './ActionUtilities'; import { timeMap } from './ApiManagers/UserManager'; @@ -18,32 +16,31 @@ import { DocumentsCollection } from './IDatabase'; import { Diff, GestureContent, MessageStore, MobileDocumentUploadContent, MobileInkOverlayContent, Transferable, Types, UpdateMobileInkOverlayPositionContent, YoutubeQueryInput, YoutubeQueryTypes } from './Message'; import { Search } from './Search'; import { resolvedPorts } from './server_Initialization'; -var _ = require('lodash'); -type Socket = typeof _socket; +import * as _ from 'lodash'; export namespace WebSocket { export let _socket: Socket; export const clients: { [key: string]: Client } = {}; - export const socketMap = new Map(); + export const socketMap = new Map(); export const userOperations = new Map(); export let disconnect: Function; export async function initialize(isRelease: boolean, app: express.Express) { - let io: sio.Server; + let io: Server; if (isRelease) { const { socketPort } = process.env; if (socketPort) { resolvedPorts.socket = Number(socketPort); } - let socketEndpoint: Opt; - await new Promise(resolve => (socketEndpoint = createServer(SSL.Credentials, app).listen(resolvedPorts.socket, resolve))); - io = sio(socketEndpoint!, SSL.Credentials as any); + io = new Server(createServer(SSL.Credentials, app), SSL.Credentials as any); + io.listen(resolvedPorts.socket); } else { - io = sio().listen(resolvedPorts.socket); + io = new Server(); + io.listen(resolvedPorts.socket); } logPort('websocket', resolvedPorts.socket); - io.on('connection', function (socket: Socket) { + io.on('connection', socket => { _socket = socket; socket.use((_packet, next) => { const userEmail = socketMap.get(socket); @@ -69,7 +66,7 @@ export namespace WebSocket { console.log('Received request to create or join room ' + room); const clientsInRoom = socket.rooms.has(room); - const numClients = clientsInRoom ? Object.keys(clientsInRoom.sockets).length : 0; + const numClients = clientsInRoom ? Object.keys(room.sockets).length : 0; console.log('Room ' + room + ' now has ' + numClients + ' client(s)'); if (numClients === 0) { @@ -192,7 +189,7 @@ export namespace WebSocket { initializeGuest(); } - function barReceived(socket: SocketIO.Socket, userEmail: string) { + function barReceived(socket: Socket, userEmail: string) { clients[userEmail] = new Client(userEmail.toString()); const currentdate = new Date(); const datetime = currentdate.getDate() + '/' + (currentdate.getMonth() + 1) + '/' + currentdate.getFullYear() + ' @ ' + currentdate.getHours() + ':' + currentdate.getMinutes() + ':' + currentdate.getSeconds(); @@ -309,9 +306,9 @@ export namespace WebSocket { if (sendBack) { console.log('Warning: list modified during update. Composite list is being returned.'); const id = socket.id; - socket.id = ''; + (socket as any).id = ''; socket.broadcast.emit(MessageStore.UpdateField.Message, diff); - socket.id = id; + (socket as any).id = id; } else socket.broadcast.emit(MessageStore.UpdateField.Message, diff); dispatchNextOp(diff.id); }, @@ -402,9 +399,9 @@ export namespace WebSocket { // the two copies are different, so the server sends its copy. console.log('SEND BACK'); const id = socket.id; - socket.id = ''; + (socket as any).id = ''; socket.broadcast.emit(MessageStore.UpdateField.Message, diff); - socket.id = id; + (socket as any).id = id; } else socket.broadcast.emit(MessageStore.UpdateField.Message, diff); dispatchNextOp(diff.id); }, diff --git a/src/typings/index.d.ts b/src/typings/index.d.ts index 884e55fc7..6a1afbb03 100644 --- a/src/typings/index.d.ts +++ b/src/typings/index.d.ts @@ -13,7 +13,6 @@ declare module 'reveal'; declare module 'react-reveal'; declare module 'react-reveal/makeCarousel'; declare module 'react-resizable-rotatable-draggable'; -declare module 'socket.io'; declare module '@hig/flyout'; declare module 'uuid/v4'; declare module 'uuid/v5'; -- cgit v1.2.3-70-g09d2 From 07c30aed69dfa810ddb0b861ae2dc8e8f3a27356 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 11 Dec 2023 17:04:49 -0500 Subject: fixed includes of scss globals into typescript files. --- package-lock.json | 3 +- package.json | 2 +- src/client/documents/Documents.ts | 5 +- src/client/util/CaptureManager.scss | 7 +- src/client/util/DragManager.ts | 3 +- src/client/util/SettingsManager.scss | 4 +- src/client/util/reportManager/ReportManager.scss | 7 +- src/client/views/AntimodeMenu.scss | 11 +-- src/client/views/ContextMenu.scss | 2 +- src/client/views/DashboardView.scss | 52 +++++------ src/client/views/DocumentButtonBar.scss | 2 +- src/client/views/DocumentDecorations.scss | 2 +- src/client/views/InkingStroke.tsx | 4 +- src/client/views/Main.scss | 2 +- src/client/views/MainView.scss | 2 +- src/client/views/MainView.tsx | 4 +- src/client/views/PropertiesButtons.scss | 45 +++++---- src/client/views/PropertiesSection.scss | 7 +- src/client/views/PropertiesView.scss | 2 +- src/client/views/TemplateMenu.scss | 7 +- src/client/views/_nodeModuleOverrides.scss | 2 +- src/client/views/animationtimeline/Region.scss | 2 +- src/client/views/animationtimeline/Region.tsx | 2 +- src/client/views/animationtimeline/Timeline.scss | 18 +--- .../views/animationtimeline/TimelineMenu.scss | 78 +++++++--------- .../views/animationtimeline/TimelineOverview.scss | 6 +- src/client/views/animationtimeline/Track.scss | 5 +- .../collections/CollectionCarousel3DView.scss | 6 +- .../views/collections/CollectionCarousel3DView.tsx | 5 +- .../views/collections/CollectionDockingView.scss | 2 +- src/client/views/collections/CollectionMenu.scss | 4 +- .../collections/CollectionNoteTakingView.scss | 2 +- .../collections/CollectionStackedTimeline.scss | 2 +- .../views/collections/CollectionStackingView.scss | 2 +- .../views/collections/CollectionTreeView.scss | 2 +- src/client/views/collections/CollectionView.scss | 2 +- src/client/views/collections/TabDocView.scss | 2 +- src/client/views/collections/TreeView.scss | 2 +- src/client/views/collections/TreeView.tsx | 3 +- .../CollectionFreeFormRemoteCursors.scss | 10 +- .../collectionFreeForm/CollectionFreeFormView.scss | 2 +- .../collectionLinear/CollectionLinearView.scss | 2 +- .../collectionSchema/CollectionSchemaView.scss | 2 +- .../views/global/globalCssVariables.module.scss | 96 +++++++++++++++++++ .../global/globalCssVariables.module.scss.d.ts | 21 +++++ src/client/views/global/globalCssVariables.scss | 96 ------------------- .../views/global/globalCssVariables.scss.d.ts | 21 ----- src/client/views/linking/LinkMenu.scss | 6 +- src/client/views/linking/LinkMenuItem.scss | 2 +- src/client/views/nodes/AudioBox.scss | 10 +- .../views/nodes/DataVizBox/components/Chart.scss | 2 +- .../views/nodes/DataVizBox/components/TableBox.tsx | 4 +- src/client/views/nodes/DocumentLinksButton.scss | 2 +- src/client/views/nodes/DocumentView.scss | 2 +- src/client/views/nodes/EquationBox.scss | 2 +- .../views/nodes/FontIconBox/FontIconBox.scss | 2 +- src/client/views/nodes/KeyValueBox.scss | 54 +++++------ src/client/views/nodes/KeyValuePair.scss | 2 +- src/client/views/nodes/LinkAnchorBox.tsx | 7 +- src/client/views/nodes/LinkDescriptionPopup.scss | 8 +- src/client/views/nodes/MapBox/MapBox.scss | 2 +- src/client/views/nodes/PDFBox.scss | 16 +--- src/client/views/nodes/RadialMenu.scss | 14 ++- src/client/views/nodes/VideoBox.scss | 8 +- src/client/views/nodes/WebBox.scss | 2 +- .../views/nodes/formattedText/DashFieldView.scss | 2 +- .../nodes/formattedText/FormattedTextBox.scss | 4 +- .../views/nodes/formattedText/RichTextMenu.scss | 11 +-- .../views/nodes/formattedText/TooltipTextMenu.scss | 102 ++++++++++----------- src/client/views/nodes/trails/PresBox.scss | 2 +- src/client/views/search/CheckBox.scss | 7 +- src/client/views/search/CollectionFilters.scss | 4 +- src/client/views/search/IconBar.scss | 4 +- src/client/views/search/IconButton.scss | 8 +- src/client/views/search/IconButton.tsx | 2 +- src/client/views/search/NaviconButton.scss | 2 +- src/client/views/search/SearchBox.scss | 17 ++-- src/client/views/search/SelectorContextMenu.scss | 4 +- src/client/views/search/ToggleBar.scss | 4 +- src/client/views/topbar/TopBar.scss | 3 +- src/client/views/webcam/DashWebRTCVideo.scss | 9 +- src/mobile/ImageUpload.scss | 13 +-- src/mobile/ImageUpload.tsx | 3 +- webpack.config.js | 28 +++--- 84 files changed, 450 insertions(+), 494 deletions(-) create mode 100644 src/client/views/global/globalCssVariables.module.scss create mode 100644 src/client/views/global/globalCssVariables.module.scss.d.ts delete mode 100644 src/client/views/global/globalCssVariables.scss delete mode 100644 src/client/views/global/globalCssVariables.scss.d.ts (limited to 'src/client/views/collections/CollectionCarousel3DView.tsx') diff --git a/package-lock.json b/package-lock.json index 84b087892..4af642fc4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -176,6 +176,7 @@ "reveal.js": "^5.0.2", "rimraf": "^5.0.5", "sass": "^1.69.5", + "sass-loader": "^13.3.2", "serializr": "^3.0.2", "shelljs": "^0.8.5", "socket.io": "^4.7.2", @@ -269,7 +270,6 @@ "mocha": "^10.2.0", "prettier": "^3.1.0", "react-type-animation": "^3.2.0", - "sass-loader": "^13.3.2", "scss-loader": "0.0.1", "style-loader": "^3.3.3", "ts-loader": "^9.5.1", @@ -25578,7 +25578,6 @@ "version": "13.3.2", "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.2.tgz", "integrity": "sha512-CQbKl57kdEv+KDLquhC+gE3pXt74LEAzm+tzywcA0/aHZuub8wTErbjAoNI57rPUWRYRNC5WUnNl8eGJNbDdwg==", - "dev": true, "dependencies": { "neo-async": "^2.6.2" }, diff --git a/package.json b/package.json index be944ff01..e99bf3734 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,6 @@ "mocha": "^10.2.0", "prettier": "^3.1.0", "react-type-animation": "^3.2.0", - "sass-loader": "^13.3.2", "scss-loader": "0.0.1", "style-loader": "^3.3.3", "ts-loader": "^9.5.1", @@ -262,6 +261,7 @@ "reveal.js": "^5.0.2", "rimraf": "^5.0.5", "sass": "^1.69.5", + "sass-loader": "^13.3.2", "serializr": "^3.0.2", "shelljs": "^0.8.5", "socket.io": "^4.7.2", diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 1b39fdb41..dd6d6cdf6 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -58,8 +58,9 @@ import { VideoBox } from '../views/nodes/VideoBox'; import { WebBox } from '../views/nodes/WebBox'; import { SearchBox } from '../views/search/SearchBox'; import { CollectionViewType, DocumentType } from './DocumentTypes'; -//import { DFLT_IMAGE_NATIVE_DIM } from '../views/global/globalCssVariables.scss'; -const DFLT_IMAGE_NATIVE_DIM = '900px'; +const { + default: { DFLT_IMAGE_NATIVE_DIM }, +} = require('../views/global/globalCssVariables.module.scss'); const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace('px', '')); class EmptyBox { diff --git a/src/client/util/CaptureManager.scss b/src/client/util/CaptureManager.scss index 11e31fe2e..8679a0101 100644 --- a/src/client/util/CaptureManager.scss +++ b/src/client/util/CaptureManager.scss @@ -1,4 +1,4 @@ -@import "../views/global/globalCssVariables"; +@import '../views/global/globalCssVariables.module'; .capture-interface { //background-color: whitesmoke !important; @@ -39,7 +39,7 @@ align-items: center; justify-content: center; } - + .recordButtonInner { border-radius: 100%; width: 70%; @@ -106,7 +106,7 @@ display: flex; justify-content: center; align-items: center; - background-color: #BDDBE8; + background-color: #bddbe8; border-radius: 100%; font-weight: 800; margin-right: 5px; @@ -154,4 +154,3 @@ } } } - diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 427b1c85f..4b1cc1702 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -13,8 +13,7 @@ import { ScriptingGlobals } from './ScriptingGlobals'; import { SelectionManager } from './SelectionManager'; import { SnappingManager } from './SnappingManager'; import { UndoManager } from './UndoManager'; -// import * as globalCssVariables from '../views/global/globalCssVariables.scss'; -const contextMenuZindex = 100002; +const { default : { contextMenuZindex } } = require('../views/global/globalCssVariables.module.scss'); // prettier-ignore export type dropActionType = 'embed' | 'copy' | 'move' | 'add' | 'same' | 'inSame' | 'proto' | 'none' | undefined; // undefined = move, "same" = move but don't call dropPropertiesToRemove diff --git a/src/client/util/SettingsManager.scss b/src/client/util/SettingsManager.scss index bca649bc3..dbfc48c63 100644 --- a/src/client/util/SettingsManager.scss +++ b/src/client/util/SettingsManager.scss @@ -1,4 +1,4 @@ -@import '../views/global/globalCssVariables'; +@import '../views/global/globalCssVariables.module'; .settings-interface { //background-color: whitesmoke !important; @@ -187,14 +187,12 @@ display: flex; flex-direction: column; - .close-button { position: absolute; right: 2px; top: 2px; } - .settings-content { padding: 10px; width: 500px; diff --git a/src/client/util/reportManager/ReportManager.scss b/src/client/util/reportManager/ReportManager.scss index cd6a1d934..d82d7fdeb 100644 --- a/src/client/util/reportManager/ReportManager.scss +++ b/src/client/util/reportManager/ReportManager.scss @@ -1,4 +1,4 @@ -@import '../../views/global/globalCssVariables'; +@import '../../views/global/globalCssVariables.module'; // header @@ -360,5 +360,8 @@ padding: 4px 10px; font-size: 10px; border-radius: 32px; - transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease; + transition: + background-color 0.2s ease, + color 0.2s ease, + border-color 0.2s ease; } diff --git a/src/client/views/AntimodeMenu.scss b/src/client/views/AntimodeMenu.scss index b205a0f1e..4613cec76 100644 --- a/src/client/views/AntimodeMenu.scss +++ b/src/client/views/AntimodeMenu.scss @@ -1,5 +1,4 @@ -@import "./global/globalCssVariables"; - +@import './global/globalCssVariables.module'; .antimodeMenu-cont { position: absolute; @@ -16,7 +15,7 @@ gap: 3px; &.with-rows { - flex-direction: column + flex-direction: column; } .antimodeMenu-row { @@ -26,8 +25,8 @@ .antimodeMenu-dragger { height: 100%; - transition: width .2s; - background-image: url("https://logodix.com/logo/1020374.png"); + transition: width 0.2s; + background-image: url('https://logodix.com/logo/1020374.png'); background-size: 90% 100%; background-repeat: no-repeat; background-position: left center; @@ -63,4 +62,4 @@ background-color: #121212; } } -} \ No newline at end of file +} diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 588eff1d1..232362c5c 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -1,4 +1,4 @@ -@import 'global/globalCssVariables'; +@import 'global/globalCssVariables.module.scss'; .contextMenu-cont { position: absolute; diff --git a/src/client/views/DashboardView.scss b/src/client/views/DashboardView.scss index 6be2133ef..90f64b393 100644 --- a/src/client/views/DashboardView.scss +++ b/src/client/views/DashboardView.scss @@ -1,4 +1,4 @@ -@import './global/globalCssVariables'; +@import './global/globalCssVariables.module'; .dashboard-view { padding: 50px; @@ -7,18 +7,18 @@ width: 100%; position: absolute; height: 100%; - width:100%; + width: 100%; padding-right: 0px; overflow: auto; - .left-menu { - display: flex; - justify-content: flex-start; - flex-direction: column; - width: 250px; - min-width: 250px; - gap: 5px; - } + .left-menu { + display: flex; + justify-content: flex-start; + flex-direction: column; + width: 250px; + min-width: 250px; + gap: 5px; + } .all-dashboards { display: flex; @@ -75,20 +75,20 @@ left: 0; top: 0; z-index: -1; - } + } } .dashboard-container { - border-radius: 10px; - position: relative; - cursor: pointer; - width: 250px; - height: 200px; - outline: solid 2px $light-gray; - display: flex; - flex-direction: column; - margin: 0 0px 30px 30px; - overflow: hidden; + border-radius: 10px; + position: relative; + cursor: pointer; + width: 250px; + height: 200px; + outline: solid 2px $light-gray; + display: flex; + flex-direction: column; + margin: 0 0px 30px 30px; + overflow: hidden; &:hover { outline: solid 2px $light-blue; @@ -122,18 +122,18 @@ background: 'lightgreen'; } - .more { - z-index: 100; - } + .more { + z-index: 100; + } - .background { + .background { position: absolute; width: 100%; height: 100%; left: 0; top: 0; z-index: -1; - } + } } .new-dashboard { diff --git a/src/client/views/DocumentButtonBar.scss b/src/client/views/DocumentButtonBar.scss index 1abf33cac..11614d627 100644 --- a/src/client/views/DocumentButtonBar.scss +++ b/src/client/views/DocumentButtonBar.scss @@ -1,4 +1,4 @@ -@import 'global/globalCssVariables'; +@import 'global/globalCssVariables.module'; $linkGap: 3px; diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index bbd951481..ac0ef054c 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -1,4 +1,4 @@ -@import 'global/globalCssVariables'; +@import 'global/globalCssVariables.module'; $linkGap: 3px; $headerHeight: 20px; diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index d34df8742..15df03682 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -46,9 +46,7 @@ import { FieldView, FieldViewProps } from './nodes/FieldView'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { PinProps, PresBox } from './nodes/trails'; import { StyleProp } from './StyleProvider'; -// import { INK_MASK_SIZE } from './global/globalCssVariables.scss'; -const INK_MASK_SIZE = 1000; - +const { default: { INK_MASK_SIZE } } = require('./global/globalCssVariables.module.scss'); // prettier-ignore @observer export class InkingStroke extends ViewBoxBaseComponent() { static readonly MaskDim = INK_MASK_SIZE; // choose a really big number to make sure mask fits over container (which in theory can be arbitrarily big) diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index a403a10e3..02916e48e 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -1,4 +1,4 @@ -@import 'global/globalCssVariables'; +@import 'global/globalCssVariables.module'; @import 'nodeModuleOverrides'; :root { diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss index 4fb2ac279..28a0f7750 100644 --- a/src/client/views/MainView.scss +++ b/src/client/views/MainView.scss @@ -1,4 +1,4 @@ -@import 'global/globalCssVariables'; +@import 'global/globalCssVariables.module.scss'; @import 'nodeModuleOverrides'; html { overscroll-behavior-x: none; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index a8f4020ee..1e4c1e1d3 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -69,9 +69,7 @@ import { PreviewCursor } from './PreviewCursor'; import { PropertiesView } from './PropertiesView'; import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider'; import { TopBar } from './topbar/TopBar'; -// import { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } from './global/globalCssVariables.scss'; -const LEFT_MENU_WIDTH = '60px'; -const TOPBAR_HEIGHT = '37px'; +const { default: { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } } = require('./global/globalCssVariables.module.scss'); // prettier-ignore const _global = (window /* browser */ || global) /* node */ as any; @observer diff --git a/src/client/views/PropertiesButtons.scss b/src/client/views/PropertiesButtons.scss index b801b3abf..b8c73b6d3 100644 --- a/src/client/views/PropertiesButtons.scss +++ b/src/client/views/PropertiesButtons.scss @@ -1,6 +1,6 @@ -@import "global/globalCssVariables"; +@import 'global/globalCssVariables.module.scss'; -$linkGap : 3px; +$linkGap: 3px; .propertiesButtons-linkFlyout { grid-column: 2/4; @@ -23,7 +23,7 @@ $linkGap : 3px; // margin-right: 7px; // margin-left: 8px; height: 28px; - // width: 226px;//29px; + // width: 226px;//29px; display: flex; align-items: center; // height: 25px; @@ -39,10 +39,9 @@ $linkGap : 3px; // font-size: 75%; transition: transform 0.2s; // text-align: center; - // justify-content: center; - + // margin-right: 10px; // margin-left: 4px; @@ -55,34 +54,34 @@ $linkGap : 3px; .propertiesButtons-linkButton-empty.toggle-on { background-color: $medium-blue; color: $white; - width:100% + width: 100%; } .propertiesButtons-linkButton-empty.toggle-hover { background-color: $light-blue; color: $black; - width:100% + width: 100%; } .propertiesButtons-linkButton-empty.toggle-off { - background-color: white;//$dark-gray; + background-color: white; //$dark-gray; color: black; //white; - width:100% + width: 100%; } .propertiesButtons-icon { - margin-left:8px; + margin-left: 8px; } .propertiesButtons { - position:relative; + position: relative; width: 100%; // margin-top: 3px; -// // grid-column: 1/4; -// width: 100%; -// height: auto; -// display: flex; -// // flex-direction: row; -// // flex-wrap: wrap; -// padding-bottom: 5.5px; + // // grid-column: 1/4; + // width: 100%; + // height: auto; + // display: flex; + // // flex-direction: row; + // // flex-wrap: wrap; + // padding-bottom: 5.5px; } .onClickFlyout-editScript { @@ -95,11 +94,10 @@ $linkGap : 3px; padding: 4px; } - .propertiesButtons-button { pointer-events: auto; - padding-right: 8px;//5px; - width: 100%;//width: 25px; + padding-right: 8px; //5px; + width: 100%; //width: 25px; border-radius: 5px; margin-right: 20px; margin-bottom: 8px; @@ -161,12 +159,11 @@ $linkGap : 3px; margin-left: 4px; &:hover { - filter:brightness(0.85); + filter: brightness(0.85); cursor: pointer; } } - @-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); @@ -194,4 +191,4 @@ $linkGap : 3px; 100% { box-shadow: 0 0 0 10px rgba(0, 255, 0, 0); } -} \ No newline at end of file +} diff --git a/src/client/views/PropertiesSection.scss b/src/client/views/PropertiesSection.scss index 321b6300c..3f92a70f8 100644 --- a/src/client/views/PropertiesSection.scss +++ b/src/client/views/PropertiesSection.scss @@ -1,11 +1,10 @@ -@import './global/globalCssVariables.scss'; +@import './global/globalCssVariables.module.scss'; .propertiesView-section { - .propertiesView-content { padding: 10px; } - + .propertiesView-sectionTitle { text-align: center; display: flex; @@ -14,7 +13,7 @@ font-weight: bold; justify-content: space-between; align-items: center; - + .propertiesView-sectionTitle-icon { width: 20px; height: 20px; diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss index 2da2ec568..8581bdf73 100644 --- a/src/client/views/PropertiesView.scss +++ b/src/client/views/PropertiesView.scss @@ -1,4 +1,4 @@ -@import './global/globalCssVariables.scss'; +@import './global/globalCssVariables.module.scss'; .propertiesView-presentationTrails-title { display: flex; diff --git a/src/client/views/TemplateMenu.scss b/src/client/views/TemplateMenu.scss index f81cbdaab..4d0f1bf00 100644 --- a/src/client/views/TemplateMenu.scss +++ b/src/client/views/TemplateMenu.scss @@ -1,4 +1,4 @@ -@import "global/globalCssVariables"; +@import 'global/globalCssVariables.module.scss'; .templating-menu { position: absolute; pointer-events: auto; @@ -40,7 +40,8 @@ height: 100%; width: 100%; - .templateToggle, .chromeToggle { + .templateToggle, + .chromeToggle { text-align: left; color: black; } @@ -48,4 +49,4 @@ input { margin-right: 10px; } -} \ No newline at end of file +} diff --git a/src/client/views/_nodeModuleOverrides.scss b/src/client/views/_nodeModuleOverrides.scss index c99281323..db69d6e44 100644 --- a/src/client/views/_nodeModuleOverrides.scss +++ b/src/client/views/_nodeModuleOverrides.scss @@ -1,4 +1,4 @@ -@import './global/globalCssVariables'; +@import './global/globalCssVariables.module.scss'; // this file is for overriding all the css from installed node modules // goldenlayout stuff diff --git a/src/client/views/animationtimeline/Region.scss b/src/client/views/animationtimeline/Region.scss index f7476ab55..b390ae34e 100644 --- a/src/client/views/animationtimeline/Region.scss +++ b/src/client/views/animationtimeline/Region.scss @@ -1,4 +1,4 @@ -@import './../global/globalCssVariables.scss'; +@import './../global/globalCssVariables.module.scss'; $timelineColor: #9acedf; $timelineDark: #77a1aa; diff --git a/src/client/views/animationtimeline/Region.tsx b/src/client/views/animationtimeline/Region.tsx index 53c5c4718..bc87dc94d 100644 --- a/src/client/views/animationtimeline/Region.tsx +++ b/src/client/views/animationtimeline/Region.tsx @@ -6,7 +6,7 @@ import { List } from '../../../fields/List'; import { createSchema, defaultSpec, listSpec, makeInterface } from '../../../fields/Schema'; import { Cast, NumCast } from '../../../fields/Types'; import { Transform } from '../../util/Transform'; -import '../global/globalCssVariables.scss'; +import '../global/globalCssVariables.module.scss'; import './Region.scss'; import './Timeline.scss'; import { TimelineMenu } from './TimelineMenu'; diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss index 48422b789..35ba0fa7f 100644 --- a/src/client/views/animationtimeline/Timeline.scss +++ b/src/client/views/animationtimeline/Timeline.scss @@ -1,4 +1,4 @@ -@import "./../global/globalCssVariables.scss"; +@import './../global/globalCssVariables.module.scss'; $timelineColor: #9acedf; $timelineDark: #77a1aa; @@ -30,7 +30,6 @@ $timelineDark: #77a1aa; color: $timelineColor; margin-left: 3px; } - } .grid-box { @@ -61,7 +60,7 @@ $timelineDark: #77a1aa; -webkit-transform: scale(1.1); -ms-transform: scale(1.1); transform: scale(1.1); - transition: .2s ease; + transition: 0.2s ease; } } @@ -128,7 +127,6 @@ $timelineDark: #77a1aa; // margin-top: 0.5px; } } - } .time-input { @@ -154,7 +152,7 @@ $timelineDark: #77a1aa; .number-label { color: black; transform: rotate(-90deg) translate(-15px, 8px); - font-size: .85em; + font-size: 0.85em; } .timeline-container { @@ -178,7 +176,6 @@ $timelineDark: #77a1aa; background-color: transparent; height: 30px; width: 100%; - } .scrubber { @@ -217,7 +214,6 @@ $timelineDark: #77a1aa; position: absolute; // box-shadow: -10px 0px 10px 10px red; } - } .currentTime { @@ -266,7 +262,6 @@ $timelineDark: #77a1aa; p { hyphens: auto; } - } } @@ -280,8 +275,6 @@ $timelineDark: #77a1aa; } } - - .overview { position: absolute; height: 50px; @@ -298,7 +291,6 @@ $timelineDark: #77a1aa; } } - .timeline-checker { height: auto; width: auto; @@ -312,11 +304,11 @@ $timelineDark: #77a1aa; width: auto; overflow: hidden; margin: 0px 10px; - cursor: pointer + cursor: pointer; } .check { width: 50px; height: 50px; } -} \ No newline at end of file +} diff --git a/src/client/views/animationtimeline/TimelineMenu.scss b/src/client/views/animationtimeline/TimelineMenu.scss index 43a89419e..de2042f17 100644 --- a/src/client/views/animationtimeline/TimelineMenu.scss +++ b/src/client/views/animationtimeline/TimelineMenu.scss @@ -1,56 +1,49 @@ -@import "./../global/globalCssVariables.scss"; +@import './../global/globalCssVariables.module.scss'; - -.timeline-menu-container{ +.timeline-menu-container { position: absolute; display: flex; box-shadow: $medium-gray 0.2vw 0.2vw 0.4vw; flex-direction: column; background: whitesmoke; z-index: 10000; - width: 200px; + width: 200px; padding-bottom: 10px; border-radius: 15px; - border: solid #BBBBBBBB 1px; - - + border: solid #bbbbbbbb 1px; - .timeline-menu-input{ - font: $sans-serif; - font-size: 13px; - width:100%; - text-transform: uppercase; - letter-spacing: 2px; - margin-left: 10px; - background-color: transparent; - border-width: 0px; - transition: border-width 500ms; + .timeline-menu-input { + font: $sans-serif; + font-size: 13px; + width: 100%; + text-transform: uppercase; + letter-spacing: 2px; + margin-left: 10px; + background-color: transparent; + border-width: 0px; + transition: border-width 500ms; } - .timeline-menu-input:hover{ - border-width: 2px; + .timeline-menu-input:hover { + border-width: 2px; } - - - - .timeline-menu-header{ - border-top-left-radius: 15px; - border-top-right-radius: 15px; - text-transform: uppercase; - background: $dark-gray; - letter-spacing: 2px; + .timeline-menu-header { + border-top-left-radius: 15px; + border-top-right-radius: 15px; + text-transform: uppercase; + background: $dark-gray; + letter-spacing: 2px; - .timeline-menu-header-desc{ - font:$sans-serif; - font-size: 13px; - text-align: center; - color: whitesmoke; + .timeline-menu-header-desc { + font: $sans-serif; + font-size: 13px; + text-align: center; + color: whitesmoke; } } - .timeline-menu-item { // width: 11vw; //10vw height: 30px; //2vh @@ -64,7 +57,7 @@ -moz-user-select: none; -ms-user-select: none; user-select: none; - transition: all .1s; + transition: all 0.1s; border-style: none; // padding: 10px 0px 10px 0px; white-space: nowrap; @@ -73,22 +66,21 @@ letter-spacing: 2px; text-transform: uppercase; padding-right: 20px; - padding-left: 10px; + padding-left: 10px; } .timeline-menu-item:hover { - border-width: .11px; + border-width: 0.11px; border-style: none; border-color: $medium-gray; border-bottom-style: solid; border-top-style: solid; - background: $medium-blue; + background: $medium-blue; } .timeline-menu-desc { - padding-left: 10px; - font:$sans-serif; - font-size: 13px; + padding-left: 10px; + font: $sans-serif; + font-size: 13px; } - -} \ No newline at end of file +} diff --git a/src/client/views/animationtimeline/TimelineOverview.scss b/src/client/views/animationtimeline/TimelineOverview.scss index c8d96c399..2878232e6 100644 --- a/src/client/views/animationtimeline/TimelineOverview.scss +++ b/src/client/views/animationtimeline/TimelineOverview.scss @@ -1,4 +1,4 @@ -@import "./../global/globalCssVariables.scss"; +@import './../global/globalCssVariables.module.scss'; $timelineColor: #9acedf; $timelineDark: #77a1aa; @@ -66,8 +66,6 @@ $timelineDark: #77a1aa; } } - - .timeline-play-bar { position: relative; padding: 0px; @@ -104,4 +102,4 @@ $timelineDark: #77a1aa; border-radius: 20px; margin-top: -4px; cursor: pointer; -} \ No newline at end of file +} diff --git a/src/client/views/animationtimeline/Track.scss b/src/client/views/animationtimeline/Track.scss index f45e0556d..f56b2fe5f 100644 --- a/src/client/views/animationtimeline/Track.scss +++ b/src/client/views/animationtimeline/Track.scss @@ -1,7 +1,6 @@ -@import "./../global/globalCssVariables.scss"; +@import './../global/globalCssVariables.module.scss'; .track-container { - .track { .inner { top: 0px; @@ -12,4 +11,4 @@ z-index: 100; } } -} \ No newline at end of file +} diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index 1632d44db..a556d0fa7 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables'; +@import '../global/globalCssVariables.module.scss'; .collectionCarousel3DView-outer { height: 100%; position: relative; @@ -17,7 +17,9 @@ .collectionCarousel3DView-item, .collectionCarousel3DView-item-active { flex: 1; - transition: opacity 0.3s linear, transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955); + transition: + opacity 0.3s linear, + transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955); pointer-events: none; opacity: 0.5; z-index: 1; diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 330cb93e4..f03e38850 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -13,10 +13,7 @@ import { StyleProp } from '../StyleProvider'; import { DocFocusOptions, DocumentView } from '../nodes/DocumentView'; import './CollectionCarousel3DView.scss'; import { CollectionSubView } from './CollectionSubView'; -// import { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } from '../global/globalCssVariables.scss'; -const CAROUSEL3D_CENTER_SCALE = '1'; -const CAROUSEL3D_SIDE_SCALE = '1'; -const CAROUSEL3D_TOP = '0'; +const { default: { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } } = require('../global/globalCssVariables.module.scss'); // prettier-ignore @observer export class CollectionCarousel3DView extends CollectionSubView() { @computed get scrollSpeed() { diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss index 11543bbe5..7fad3e463 100644 --- a/src/client/views/collections/CollectionDockingView.scss +++ b/src/client/views/collections/CollectionDockingView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.scss'; +@import '../global/globalCssVariables.module.scss'; .lm_root { position: relative; diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss index 6eeccc94e..5d46649b2 100644 --- a/src/client/views/collections/CollectionMenu.scss +++ b/src/client/views/collections/CollectionMenu.scss @@ -1,4 +1,4 @@ -@import "../global/globalCssVariables"; +@import '../global/globalCssVariables.module.scss'; .collectionMenu-container { display: flex; @@ -19,4 +19,4 @@ display: flex; flex-direction: row; } -} \ No newline at end of file +} diff --git a/src/client/views/collections/CollectionNoteTakingView.scss b/src/client/views/collections/CollectionNoteTakingView.scss index be1800d81..91a82d40f 100644 --- a/src/client/views/collections/CollectionNoteTakingView.scss +++ b/src/client/views/collections/CollectionNoteTakingView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables'; +@import '../global/globalCssVariables.module.scss'; .collectionNoteTakingView-DocumentButtons { display: none; diff --git a/src/client/views/collections/CollectionStackedTimeline.scss b/src/client/views/collections/CollectionStackedTimeline.scss index a19d8e696..0ced3f9e3 100644 --- a/src/client/views/collections/CollectionStackedTimeline.scss +++ b/src/client/views/collections/CollectionStackedTimeline.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.scss'; +@import '../global/globalCssVariables.module.scss'; .collectionStackedTimeline-timelineContainer { height: 100%; diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 165ccbdb1..6225cc52a 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables'; +@import '../global/globalCssVariables.module.scss'; .collectionMasonryView { display: inline; diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index 21efeba44..bbbef78b4 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables'; +@import '../global/globalCssVariables.module.scss'; .collectionTreeView-container { transform-origin: top left; diff --git a/src/client/views/collections/CollectionView.scss b/src/client/views/collections/CollectionView.scss index 32b0c138d..de53a2c62 100644 --- a/src/client/views/collections/CollectionView.scss +++ b/src/client/views/collections/CollectionView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables'; +@import '../global/globalCssVariables.module.scss'; .collectionView { border-width: 0; diff --git a/src/client/views/collections/TabDocView.scss b/src/client/views/collections/TabDocView.scss index d447991a1..dd4c0b881 100644 --- a/src/client/views/collections/TabDocView.scss +++ b/src/client/views/collections/TabDocView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.scss'; +@import '../global/globalCssVariables.module.scss'; .tabDocView-content { height: 100%; diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss index cbcc7c710..0a1946f09 100644 --- a/src/client/views/collections/TreeView.scss +++ b/src/client/views/collections/TreeView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables'; +@import '../global/globalCssVariables.module.scss'; .treeView-label { max-height: 1.5em; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 27ff7166d..20e7fa071 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -35,8 +35,7 @@ import { CollectionView } from './CollectionView'; import { TreeSort } from './TreeSort'; import './TreeView.scss'; import * as React from 'react'; -// import { TREE_BULLET_WIDTH } from '../global/globalCssVariables.scss'; -const TREE_BULLET_WIDTH = '10px'; +const { default: { TREE_BULLET_WIDTH } } = require('../global/globalCssVariables.module.scss'); // prettier-ignore export interface TreeViewProps { treeView: CollectionTreeView; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss index 5fa01b102..7951aff65 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss @@ -1,14 +1,12 @@ -@import "global/globalCssVariables"; +@import 'global/globalCssVariables.module.scss'; .collectionFreeFormRemoteCursors-cont { - - position:absolute; + position: absolute; z-index: $remoteCursors-zindex; transform-origin: 'center center'; } .collectionFreeFormRemoteCursors-canvas { - - position:absolute; + position: absolute; width: 20px; height: 20px; opacity: 0.5; @@ -21,4 +19,4 @@ // fontStyle: "italic", margin-left: -12; margin-top: 4; -} \ No newline at end of file +} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index 1b596ab65..418c518ad 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -1,4 +1,4 @@ -@import '../../global/globalCssVariables'; +@import '../../global/globalCssVariables.module.scss'; .collectionfreeformview-none { position: inherit; diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.scss b/src/client/views/collections/collectionLinear/CollectionLinearView.scss index 3c2f5ccd7..b8ceec139 100644 --- a/src/client/views/collections/collectionLinear/CollectionLinearView.scss +++ b/src/client/views/collections/collectionLinear/CollectionLinearView.scss @@ -1,4 +1,4 @@ -@import '../../global/globalCssVariables'; +@import '../../global/globalCssVariables.module.scss'; @import '../../_nodeModuleOverrides'; .collectionLinearView { diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index 76bd392a5..02131ae22 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -1,4 +1,4 @@ -@import '../../global/globalCssVariables.scss'; +@import '../../global/globalCssVariables.module.scss'; .collectionSchemaView { cursor: default; diff --git a/src/client/views/global/globalCssVariables.module.scss b/src/client/views/global/globalCssVariables.module.scss new file mode 100644 index 000000000..44e8efe23 --- /dev/null +++ b/src/client/views/global/globalCssVariables.module.scss @@ -0,0 +1,96 @@ +@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap'); +// colors +$white: #ffffff; +$off-white: #fdfdfd; +$light-gray: #dfdfdf; +$medium-gray: #9f9f9f; +$medium-gray-dim: #9f9f9f30; +$dark-gray: #323232; +$black: #000000; + +$close-red: red; +$minimize-yellow: yellow; +$open-green: green; + +$light-blue: #bdddf5; +$light-blue-transparent: #bdddf590; +$medium-blue: #4476f7; +$medium-blue-alt: #0047ff54; +$pink: #e0217d; +$yellow: #f5d747; + +$close-red: #e48282; + +$drop-shadow: '#32323215'; + +$INK_MASK_SIZE: 50000; +$INK_MASK_SIZE_HALF: -25000px; + +//padding +$minimum-padding: 4px; +$medium-padding: 16px; +$large-padding: 32px; + +//icon sizes +$icon-size: 28px; + +// fonts +$sans-serif: 'Roboto', sans-serif; +$large-header: 16px; +$body-text: 13px; +$small-text: 10px; +// $sans-serif: "Roboto Slab", sans-serif; + +// misc values +$border-radius: 0.3em; +$search-thumnail-size: 130; +$topbar-height: 37px; +$antimodemenu-height: 36px; + +// dragged items +$contextMenu-zindex: 100002; // context menu shows up over everything +$radialMenu-zindex: 100000; // context menu shows up over everything + +// borders +$standard-border: solid 1px #9f9f9f; + +// border radius +$standard-border-radius: 3px; + +// shadow +$standard-box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3); + +$mainTextInput-zindex: 999; // then text input overlay so that it's context menu will appear over decorations, etc +$docDecorations-zindex: 998; // then doc decorations appear over everything else +$remoteCursors-zindex: 997; // ... not sure what level the remote cursors should go -- is this right? +$SCHEMA_DIVIDER_WIDTH: 4; +$MINIMIZED_ICON_SIZE: 24; +$MAX_ROW_HEIGHT: 44px; +$DFLT_IMAGE_NATIVE_DIM: 900px; +$LEFT_MENU_WIDTH: 60px; +$TREE_BULLET_WIDTH: 20px; + +$CAROUSEL3D_CENTER_SCALE: 1.3; +$CAROUSEL3D_SIDE_SCALE: 0.6; +$CAROUSEL3D_TOP: 15; + +$DATA_VIZ_TABLE_ROW_HEIGHT: 30; + +:export { + contextMenuZindex: $contextMenu-zindex; + SCHEMA_DIVIDER_WIDTH: $SCHEMA_DIVIDER_WIDTH; + MINIMIZED_ICON_SIZE: $MINIMIZED_ICON_SIZE; + MAX_ROW_HEIGHT: $MAX_ROW_HEIGHT; + SEARCH_THUMBNAIL_SIZE: $search-thumnail-size; + ANTIMODEMENU_HEIGHT: $antimodemenu-height; + TOPBAR_HEIGHT: $topbar-height; + DFLT_IMAGE_NATIVE_DIM: $DFLT_IMAGE_NATIVE_DIM; + LEFT_MENU_WIDTH: $LEFT_MENU_WIDTH; + TREE_BULLET_WIDTH: $TREE_BULLET_WIDTH; + INK_MASK_SIZE: $INK_MASK_SIZE; + MEDIUM_GRAY: $medium-gray; + CAROUSEL3D_CENTER_SCALE: $CAROUSEL3D_CENTER_SCALE; + CAROUSEL3D_SIDE_SCALE: $CAROUSEL3D_SIDE_SCALE; + CAROUSEL3D_TOP: $CAROUSEL3D_TOP; + DATA_VIZ_TABLE_ROW_HEIGHT: $DATA_VIZ_TABLE_ROW_HEIGHT; +} diff --git a/src/client/views/global/globalCssVariables.module.scss.d.ts b/src/client/views/global/globalCssVariables.module.scss.d.ts new file mode 100644 index 000000000..bcbb1f068 --- /dev/null +++ b/src/client/views/global/globalCssVariables.module.scss.d.ts @@ -0,0 +1,21 @@ +interface IGlobalScss { + contextMenuZindex: string; // context menu shows up over everything + SCHEMA_DIVIDER_WIDTH: string; + MINIMIZED_ICON_SIZE: string; + MAX_ROW_HEIGHT: string; + SEARCH_THUMBNAIL_SIZE: string; + ANTIMODEMENU_HEIGHT: string; + TOPBAR_HEIGHT: string; + DFLT_IMAGE_NATIVE_DIM: string; + LEFT_MENU_WIDTH: string; + TREE_BULLET_WIDTH: string; + INK_MASK_SIZE: number; + MEDIUM_GRAY: string; + CAROUSEL3D_CENTER_SCALE: string; + CAROUSEL3D_SIDE_SCALE: string; + CAROUSEL3D_TOP: string; + DATA_VIZ_TABLE_ROW_HEIGHT: string; +} +declare const globalCssVariables: IGlobalScss; + +export = globalCssVariables; diff --git a/src/client/views/global/globalCssVariables.scss b/src/client/views/global/globalCssVariables.scss deleted file mode 100644 index 44e8efe23..000000000 --- a/src/client/views/global/globalCssVariables.scss +++ /dev/null @@ -1,96 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap'); -// colors -$white: #ffffff; -$off-white: #fdfdfd; -$light-gray: #dfdfdf; -$medium-gray: #9f9f9f; -$medium-gray-dim: #9f9f9f30; -$dark-gray: #323232; -$black: #000000; - -$close-red: red; -$minimize-yellow: yellow; -$open-green: green; - -$light-blue: #bdddf5; -$light-blue-transparent: #bdddf590; -$medium-blue: #4476f7; -$medium-blue-alt: #0047ff54; -$pink: #e0217d; -$yellow: #f5d747; - -$close-red: #e48282; - -$drop-shadow: '#32323215'; - -$INK_MASK_SIZE: 50000; -$INK_MASK_SIZE_HALF: -25000px; - -//padding -$minimum-padding: 4px; -$medium-padding: 16px; -$large-padding: 32px; - -//icon sizes -$icon-size: 28px; - -// fonts -$sans-serif: 'Roboto', sans-serif; -$large-header: 16px; -$body-text: 13px; -$small-text: 10px; -// $sans-serif: "Roboto Slab", sans-serif; - -// misc values -$border-radius: 0.3em; -$search-thumnail-size: 130; -$topbar-height: 37px; -$antimodemenu-height: 36px; - -// dragged items -$contextMenu-zindex: 100002; // context menu shows up over everything -$radialMenu-zindex: 100000; // context menu shows up over everything - -// borders -$standard-border: solid 1px #9f9f9f; - -// border radius -$standard-border-radius: 3px; - -// shadow -$standard-box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3); - -$mainTextInput-zindex: 999; // then text input overlay so that it's context menu will appear over decorations, etc -$docDecorations-zindex: 998; // then doc decorations appear over everything else -$remoteCursors-zindex: 997; // ... not sure what level the remote cursors should go -- is this right? -$SCHEMA_DIVIDER_WIDTH: 4; -$MINIMIZED_ICON_SIZE: 24; -$MAX_ROW_HEIGHT: 44px; -$DFLT_IMAGE_NATIVE_DIM: 900px; -$LEFT_MENU_WIDTH: 60px; -$TREE_BULLET_WIDTH: 20px; - -$CAROUSEL3D_CENTER_SCALE: 1.3; -$CAROUSEL3D_SIDE_SCALE: 0.6; -$CAROUSEL3D_TOP: 15; - -$DATA_VIZ_TABLE_ROW_HEIGHT: 30; - -:export { - contextMenuZindex: $contextMenu-zindex; - SCHEMA_DIVIDER_WIDTH: $SCHEMA_DIVIDER_WIDTH; - MINIMIZED_ICON_SIZE: $MINIMIZED_ICON_SIZE; - MAX_ROW_HEIGHT: $MAX_ROW_HEIGHT; - SEARCH_THUMBNAIL_SIZE: $search-thumnail-size; - ANTIMODEMENU_HEIGHT: $antimodemenu-height; - TOPBAR_HEIGHT: $topbar-height; - DFLT_IMAGE_NATIVE_DIM: $DFLT_IMAGE_NATIVE_DIM; - LEFT_MENU_WIDTH: $LEFT_MENU_WIDTH; - TREE_BULLET_WIDTH: $TREE_BULLET_WIDTH; - INK_MASK_SIZE: $INK_MASK_SIZE; - MEDIUM_GRAY: $medium-gray; - CAROUSEL3D_CENTER_SCALE: $CAROUSEL3D_CENTER_SCALE; - CAROUSEL3D_SIDE_SCALE: $CAROUSEL3D_SIDE_SCALE; - CAROUSEL3D_TOP: $CAROUSEL3D_TOP; - DATA_VIZ_TABLE_ROW_HEIGHT: $DATA_VIZ_TABLE_ROW_HEIGHT; -} diff --git a/src/client/views/global/globalCssVariables.scss.d.ts b/src/client/views/global/globalCssVariables.scss.d.ts deleted file mode 100644 index bcbb1f068..000000000 --- a/src/client/views/global/globalCssVariables.scss.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -interface IGlobalScss { - contextMenuZindex: string; // context menu shows up over everything - SCHEMA_DIVIDER_WIDTH: string; - MINIMIZED_ICON_SIZE: string; - MAX_ROW_HEIGHT: string; - SEARCH_THUMBNAIL_SIZE: string; - ANTIMODEMENU_HEIGHT: string; - TOPBAR_HEIGHT: string; - DFLT_IMAGE_NATIVE_DIM: string; - LEFT_MENU_WIDTH: string; - TREE_BULLET_WIDTH: string; - INK_MASK_SIZE: number; - MEDIUM_GRAY: string; - CAROUSEL3D_CENTER_SCALE: string; - CAROUSEL3D_SIDE_SCALE: string; - CAROUSEL3D_TOP: string; - DATA_VIZ_TABLE_ROW_HEIGHT: string; -} -declare const globalCssVariables: IGlobalScss; - -export = globalCssVariables; diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss index 0b9f32eee..636b6415c 100644 --- a/src/client/views/linking/LinkMenu.scss +++ b/src/client/views/linking/LinkMenu.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables'; +@import '../global/globalCssVariables.module.scss'; .linkMenu { width: auto; @@ -11,7 +11,9 @@ display: inline-block; position: relative; border: 1px solid #e4e4e4; - box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23); + box-shadow: + 0 10px 20px rgba(0, 0, 0, 0.19), + 0 6px 6px rgba(0, 0, 0, 0.23); max-height: 230px; overflow-y: scroll; z-index: 10; diff --git a/src/client/views/linking/LinkMenuItem.scss b/src/client/views/linking/LinkMenuItem.scss index e83f631a1..44c74236f 100644 --- a/src/client/views/linking/LinkMenuItem.scss +++ b/src/client/views/linking/LinkMenuItem.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables'; +@import '../global/globalCssVariables.module.scss'; .linkMenu-item { // border-top: 0.5px solid $medium-gray; diff --git a/src/client/views/nodes/AudioBox.scss b/src/client/views/nodes/AudioBox.scss index d40537776..4337401e3 100644 --- a/src/client/views/nodes/AudioBox.scss +++ b/src/client/views/nodes/AudioBox.scss @@ -1,4 +1,4 @@ -@import "../global/globalCssVariables.scss"; +@import '../global/globalCssVariables.module.scss'; .audiobox-container { width: 100%; @@ -116,18 +116,18 @@ width: 10px; } - input[type="range"] { + input[type='range'] { width: 50px; -webkit-appearance: none; background: none; margin: 5px; } - input[type="range"]:focus { + input[type='range']:focus { outline: none; } - input[type="range"]::-webkit-slider-runnable-track { + input[type='range']::-webkit-slider-runnable-track { width: 100%; height: 6px; cursor: pointer; @@ -136,7 +136,7 @@ border-radius: 3px; } - input[type="range"]::-webkit-slider-thumb { + input[type='range']::-webkit-slider-thumb { box-shadow: 0; border: 0; height: 10px; diff --git a/src/client/views/nodes/DataVizBox/components/Chart.scss b/src/client/views/nodes/DataVizBox/components/Chart.scss index c788a64c2..c0c0f10a2 100644 --- a/src/client/views/nodes/DataVizBox/components/Chart.scss +++ b/src/client/views/nodes/DataVizBox/components/Chart.scss @@ -1,4 +1,4 @@ -@import '../../../global/globalCssVariables'; +@import '../../../global/globalCssVariables.module.scss'; .chart-container { display: flex; flex-direction: column; diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx index 33be87f46..3e7d3af8c 100644 --- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx +++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx @@ -11,9 +11,7 @@ import { DragManager } from '../../../../util/DragManager'; import { DocumentView } from '../../DocumentView'; import { DataVizView } from '../DataVizBox'; import './Chart.scss'; -//import { DATA_VIZ_TABLE_ROW_HEIGHT } from '../../../global/globalCssVariables.scss'; -const DATA_VIZ_TABLE_ROW_HEIGHT = '30'; - +const { default: { DATA_VIZ_TABLE_ROW_HEIGHT } } = require('../../../global/globalCssVariables.module.scss'); // prettier-ignore interface TableBoxProps { Document: Doc; layoutDoc: Doc; diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss index 6da0b73ba..b32b27e65 100644 --- a/src/client/views/nodes/DocumentLinksButton.scss +++ b/src/client/views/nodes/DocumentLinksButton.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.scss'; +@import '../global/globalCssVariables.module.scss'; .documentLinksButton-wrapper { transform-origin: top left; diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index 406a1b8fb..c4dab16fb 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables'; +@import '../global/globalCssVariables.module.scss'; .documentView-effectsWrapper { border-radius: inherit; diff --git a/src/client/views/nodes/EquationBox.scss b/src/client/views/nodes/EquationBox.scss index f5871db22..5009ec7a7 100644 --- a/src/client/views/nodes/EquationBox.scss +++ b/src/client/views/nodes/EquationBox.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.scss'; +@import '../global/globalCssVariables.module.scss'; .equationBox-cont { transform-origin: center; diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.scss b/src/client/views/nodes/FontIconBox/FontIconBox.scss index 9d9fa26b0..db2ffa756 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.scss +++ b/src/client/views/nodes/FontIconBox/FontIconBox.scss @@ -1,4 +1,4 @@ -@import '../../global/globalCssVariables'; +@import '../../global/globalCssVariables.module.scss'; .menuButton { height: 100%; diff --git a/src/client/views/nodes/KeyValueBox.scss b/src/client/views/nodes/KeyValueBox.scss index ffcba4981..a44f614b2 100644 --- a/src/client/views/nodes/KeyValueBox.scss +++ b/src/client/views/nodes/KeyValueBox.scss @@ -1,7 +1,7 @@ -@import "../global/globalCssVariables"; +@import '../global/globalCssVariables.module.scss'; .keyValueBox-cont { overflow-y: scroll; - width:100%; + width: 100%; height: 100%; background-color: $white; border: 1px solid $medium-gray; @@ -15,45 +15,45 @@ } $header-height: 30px; .keyValueBox-tbody { - width:100%; - height:100%; + width: 100%; + height: 100%; position: absolute; overflow-y: scroll; } .keyValueBox-key { display: inline-block; - height:100%; - width:50%; + height: 100%; + width: 50%; text-align: center; } .keyValueBox-fields { display: inline-block; - height:100%; - width:50%; + height: 100%; + width: 50%; text-align: center; } .keyValueBox-table { position: absolute; - width:100%; - height:100%; + width: 100%; + height: 100%; border-collapse: collapse; } .keyValueBox-td-key { - display:inline-block; - height:30px; + display: inline-block; + height: 30px; } .keyValueBox-td-value { - display:inline-block; - height:30px; + display: inline-block; + height: 30px; } .keyValueBox-valueRow { - width:100%; - height:30px; + width: 100%; + height: 30px; display: inline-block; } .keyValueBox-header { - width:100%; + width: 100%; position: relative; display: inline-block; background: $medium-gray; @@ -74,8 +74,8 @@ $header-height: 30px; .keyValueBox-evenRow { position: relative; display: flex; - width:100%; - height:$header-height; + width: 100%; + height: $header-height; background: $white; .formattedTextBox-cont { background: $white; @@ -86,10 +86,10 @@ $header-height: 30px; position: relative; } } -.keyValueBox-dividerDraggerThumb{ +.keyValueBox-dividerDraggerThumb { position: relative; width: 4px; - float: left; + float: left; height: 30px; width: 5px; z-index: 20; @@ -99,10 +99,10 @@ $header-height: 30px; background: black; pointer-events: all; } -.keyValueBox-dividerDragger{ - position: relative; +.keyValueBox-dividerDragger { + position: relative; width: 100%; - float: left; + float: left; height: 37px; z-index: 20; right: 0; @@ -114,10 +114,10 @@ $header-height: 30px; .keyValueBox-oddRow { position: relative; display: flex; - width:100%; - height:30px; + width: 100%; + height: 30px; background: $light-gray; .formattedTextBox-cont { background: $light-gray; } -} \ No newline at end of file +} diff --git a/src/client/views/nodes/KeyValuePair.scss b/src/client/views/nodes/KeyValuePair.scss index c29af7817..46ea9c18e 100644 --- a/src/client/views/nodes/KeyValuePair.scss +++ b/src/client/views/nodes/KeyValuePair.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables'; +@import '../global/globalCssVariables.module.scss'; .keyValuePair-td-key { display: inline-block; diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index 33c9b2e08..09ba0bc95 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -11,10 +11,11 @@ import { ViewBoxBaseComponent } from '../DocComponent'; import { StyleProp } from '../StyleProvider'; import { FieldView, FieldViewProps } from './FieldView'; import './LinkAnchorBox.scss'; -import { LinkDocPreview, LinkInfo } from './LinkDocPreview'; +import { LinkInfo } from './LinkDocPreview'; import * as React from 'react'; -// import globalCssVariables = require('../global/globalCssVariables.scss'); -const MEDIUM_GRAY = 'lightGray'; +const { + default: { MEDIUM_GRAY }, +} = require('../global/globalCssVariables.module.scss'); @observer export class LinkAnchorBox extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string) { diff --git a/src/client/views/nodes/LinkDescriptionPopup.scss b/src/client/views/nodes/LinkDescriptionPopup.scss index a8db5d360..104301656 100644 --- a/src/client/views/nodes/LinkDescriptionPopup.scss +++ b/src/client/views/nodes/LinkDescriptionPopup.scss @@ -1,7 +1,6 @@ -@import "../global/globalCssVariables.scss"; +@import '../global/globalCssVariables.module.scss'; .linkDescriptionPopup { - display: flex; flex-direction: row; justify-content: center; @@ -26,7 +25,6 @@ } .linkDescriptionPopup-btn { - float: right; justify-content: center; vertical-align: middle; @@ -53,6 +51,4 @@ color: black; } } - - -} \ No newline at end of file +} diff --git a/src/client/views/nodes/MapBox/MapBox.scss b/src/client/views/nodes/MapBox/MapBox.scss index 242677231..9b00c30cf 100644 --- a/src/client/views/nodes/MapBox/MapBox.scss +++ b/src/client/views/nodes/MapBox/MapBox.scss @@ -1,4 +1,4 @@ -@import '../../global/globalCssVariables.scss'; +@import '../../global/globalCssVariables.module.scss'; .mapBox { width: 100%; height: 100%; diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index 8a68f9647..0f5e25a0c 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -1,4 +1,4 @@ -@import "../global/globalCssVariables.scss"; +@import '../global/globalCssVariables.module.scss'; .pdfBox, .pdfBox-interactive { @@ -38,7 +38,7 @@ box-shadow: $standard-box-shadow; transition: 0.2s; - &:hover{ + &:hover { filter: brightness(0.85); } } @@ -51,7 +51,8 @@ left: 5px; top: 5px; - .pdfBox-fwdBtn, .pdfBox-backBtn { + .pdfBox-fwdBtn, + .pdfBox-backBtn { background: #121721; height: 25px; width: 25px; @@ -119,7 +120,6 @@ background: none; } - .pdfBox-settingsCont { position: absolute; right: 0; @@ -194,7 +194,7 @@ justify-content: center; align-items: center; overflow: hidden; - transition: left .5s; + transition: left 0.5s; pointer-events: all; .pdfBox-searchBar { @@ -204,7 +204,6 @@ } } - .pdfBox-title-outer { width: 100%; height: 100%; @@ -269,7 +268,6 @@ // CSS adjusted for mobile devices @media only screen and (max-device-width: 480px) { - .pdfBox .pdfBox-ui .pdfBox-settingsCont .pdfBox-settingsButton, .pdfBox-interactive .pdfBox-ui .pdfBox-settingsCont .pdfBox-settingsButton { height: 60px; @@ -288,15 +286,11 @@ } } - - .pdfBox .pdfBox-ui .pdfBox-settingsCont .pdfBox-settingsFlyout, .pdfBox-interactive .pdfBox-ui .pdfBox-settingsCont .pdfBox-settingsFlyout { font-size: 30px; } - - .pdfBox .pdfBox-ui .pdfBox-overlayCont, .pdfBox-interactive .pdfBox-ui .pdfBox-overlayCont { height: 60px; diff --git a/src/client/views/nodes/RadialMenu.scss b/src/client/views/nodes/RadialMenu.scss index 312b51013..9cd1ee23a 100644 --- a/src/client/views/nodes/RadialMenu.scss +++ b/src/client/views/nodes/RadialMenu.scss @@ -1,4 +1,4 @@ -@import "../global/globalCssVariables"; +@import '../global/globalCssVariables.module.scss'; .radialMenu-cont { position: absolute; @@ -26,7 +26,7 @@ -moz-user-select: none; -ms-user-select: none; user-select: none; - transition: all .1s; + transition: all 0.1s; border-style: none; white-space: nowrap; font-size: 13px; @@ -34,8 +34,7 @@ text-transform: uppercase; } -s -.radialMenu-itemSelected { +s .radialMenu-itemSelected { border-style: none; } @@ -50,8 +49,8 @@ s -moz-user-select: none; -ms-user-select: none; user-select: none; - transition: all .1s; - border-width: .11px; + transition: all 0.1s; + border-width: 0.11px; border-style: none; border-color: $medium-gray; // rgb(187, 186, 186); // padding: 10px 0px 10px 0px; @@ -62,9 +61,8 @@ s padding-left: 5px; } - .radialMenu-description { margin-left: 5px; text-align: left; display: inline; //need this? -} \ No newline at end of file +} diff --git a/src/client/views/nodes/VideoBox.scss b/src/client/views/nodes/VideoBox.scss index f90c19050..ae923ad60 100644 --- a/src/client/views/nodes/VideoBox.scss +++ b/src/client/views/nodes/VideoBox.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.scss'; +@import '../global/globalCssVariables.module.scss'; .mini-viewer { cursor: grab; @@ -172,7 +172,11 @@ top: 90%; transform: translate(-50%, -50%); width: 80%; - transition: top 0s, width 0s, opacity 0.3s, visibility 0.3s; + transition: + top 0s, + width 0s, + opacity 0.3s, + visibility 0.3s; } } diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss index 511c91da0..a1686adaf 100644 --- a/src/client/views/nodes/WebBox.scss +++ b/src/client/views/nodes/WebBox.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.scss'; +@import '../global/globalCssVariables.module.scss'; .webBox { height: 100%; diff --git a/src/client/views/nodes/formattedText/DashFieldView.scss b/src/client/views/nodes/formattedText/DashFieldView.scss index ad315acc8..3426ba1a7 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.scss +++ b/src/client/views/nodes/formattedText/DashFieldView.scss @@ -1,4 +1,4 @@ -@import '../../global/globalCssVariables'; +@import '../../global/globalCssVariables.module.scss'; .dashFieldView { position: relative; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss index 717efd5a9..03ff0436b 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.scss +++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss @@ -1,4 +1,4 @@ -@import '../../global/globalCssVariables'; +@import '../../global/globalCssVariables.module.scss'; .ProseMirror { width: 100%; @@ -592,7 +592,7 @@ footnote::before { } @media only screen and (max-width: 1000px) { - @import '../../global/globalCssVariables'; + @import '../../global/globalCssVariables.module.scss'; .ProseMirror { width: 100%; diff --git a/src/client/views/nodes/formattedText/RichTextMenu.scss b/src/client/views/nodes/formattedText/RichTextMenu.scss index 8afa0f6b5..d6ed5ebee 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.scss +++ b/src/client/views/nodes/formattedText/RichTextMenu.scss @@ -1,4 +1,4 @@ -@import "../../global/globalCssVariables"; +@import '../../global/globalCssVariables.module.scss'; .button-dropdown-wrapper { position: relative; @@ -55,7 +55,6 @@ input { color: black; } - } .richTextMenu { @@ -68,12 +67,12 @@ font-size: 12px; height: 100%; margin-right: 3px; - + &:focus, &:hover { background-color: black; } - + &::-ms-expand { color: white; } @@ -126,7 +125,7 @@ display: flex; justify-content: space-between; - >div { + > div { display: flex; } -} \ No newline at end of file +} diff --git a/src/client/views/nodes/formattedText/TooltipTextMenu.scss b/src/client/views/nodes/formattedText/TooltipTextMenu.scss index 8c4d77da9..87320943d 100644 --- a/src/client/views/nodes/formattedText/TooltipTextMenu.scss +++ b/src/client/views/nodes/formattedText/TooltipTextMenu.scss @@ -1,9 +1,9 @@ -@import "../views/global/globalCssVariables"; +@import '../views/global/globalCssVariables.module.scss'; .ProseMirror-menu-dropdown-wrap { display: inline-block; position: relative; } - + .ProseMirror-menu-dropdown { vertical-align: 1px; cursor: pointer; @@ -17,11 +17,11 @@ margin-right: 4px; &:after { - content: ""; + content: ''; border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 4px solid currentColor; - opacity: .6; + opacity: 0.6; position: absolute; right: 4px; top: calc(50% - 2px); @@ -33,7 +33,7 @@ margin-right: -4px; } -.ProseMirror-menu-dropdown-menu, +.ProseMirror-menu-dropdown-menu, .ProseMirror-menu-submenu { font-size: 12px; background: white; @@ -55,19 +55,18 @@ } } - .ProseMirror-menu-submenu-label:after { - content: ""; + content: ''; border-top: 4px solid transparent; border-bottom: 4px solid transparent; border-left: 4px solid currentColor; - opacity: .6; + opacity: 0.6; position: absolute; right: 4px; top: calc(50% - 4px); } - - .ProseMirror-icon { + +.ProseMirror-icon { display: inline-block; // line-height: .8; // vertical-align: -2px; /* Compensate for padding */ @@ -79,14 +78,14 @@ } svg { - fill:white; + fill: white; height: 1em; } span { vertical-align: text-top; - } - } + } +} .wrapper { position: absolute; @@ -99,10 +98,10 @@ background: #323232; border-radius: 6px; box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); - } -.tooltipMenu, .basic-tools { +.tooltipMenu, +.basic-tools { z-index: 3000; pointer-events: all; padding: 3px; @@ -111,17 +110,17 @@ align-items: center; .ProseMirror-example-setup-style hr { - padding: 2px 10px; - border: none; - margin: 1em 0; + padding: 2px 10px; + border: none; + margin: 1em 0; } - + .ProseMirror-example-setup-style hr:after { - content: ""; - display: block; - height: 1px; - background-color: silver; - line-height: 2px; + content: ''; + display: block; + height: 1px; + background-color: silver; + line-height: 2px; } } @@ -142,7 +141,7 @@ } } - &> * { + & > * { margin-top: 50%; margin-left: 50%; transform: translate(-50%, -50%); @@ -168,7 +167,7 @@ background-color: black; } - &> * { + & > * { margin-top: 50%; margin-left: 50%; transform: translate(-50%, -50%); @@ -208,18 +207,17 @@ margin-top: 13px; } - .font-size-indicator { - font-size: 12px; - padding-right: 0px; - } - .summarize{ - color: white; - height: 20px; - text-align: center; - } - - -.brush{ +.font-size-indicator { + font-size: 12px; + padding-right: 0px; +} +.summarize { + color: white; + height: 20px; + text-align: center; +} + +.brush { display: inline-block; width: 1em; height: 1em; @@ -229,7 +227,7 @@ margin-right: 15px; } -.brush-active{ +.brush-active { display: inline-block; width: 1em; height: 1em; @@ -269,7 +267,6 @@ } .buttonSettings-dropdown { - &.ProseMirror-menu-dropdown { width: 10px; height: 25px; @@ -301,7 +298,7 @@ padding: 3px; box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); - .ProseMirror-menu-dropdown-item{ + .ProseMirror-menu-dropdown-item { cursor: default; &:last-child { @@ -312,7 +309,8 @@ background-color: #323232; } - .button-setting, .button-setting-disabled { + .button-setting, + .button-setting-disabled { padding: 2px; border-radius: 2px; } @@ -328,25 +326,23 @@ } input { - color: black; - border: none; - border-radius: 1px; - padding: 3px; + color: black; + border: none; + border-radius: 1px; + padding: 3px; } button { - padding: 6px; - background-color: #323232; - border: 1px solid black; - border-radius: 1px; + padding: 6px; + background-color: #323232; + border: 1px solid black; + border-radius: 1px; &:hover { - background-color: black; + background-color: black; } } } - - } } diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index 0b51813a5..3b34a1f90 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -1,4 +1,4 @@ -@import '../../global/globalCssVariables'; +@import '../../global/globalCssVariables.module.scss'; .presBox-cont { cursor: auto; diff --git a/src/client/views/search/CheckBox.scss b/src/client/views/search/CheckBox.scss index 2a0085ade..4892facbc 100644 --- a/src/client/views/search/CheckBox.scss +++ b/src/client/views/search/CheckBox.scss @@ -1,4 +1,4 @@ -@import "../global/globalCssVariables"; +@import '../global/globalCssVariables.module.scss'; .checkboxfilter { display: flex; @@ -12,7 +12,7 @@ align-items: center; margin-top: 0px; - .check-container:hover~.check-box { + .check-container:hover ~ .check-box { background-color: $medium-blue; } @@ -55,5 +55,4 @@ text-transform: capitalize; margin-left: 15px; } - -} \ No newline at end of file +} diff --git a/src/client/views/search/CollectionFilters.scss b/src/client/views/search/CollectionFilters.scss index 845b16f67..6105df570 100644 --- a/src/client/views/search/CollectionFilters.scss +++ b/src/client/views/search/CollectionFilters.scss @@ -1,4 +1,4 @@ -@import "../global/globalCssVariables"; +@import '../global/globalCssVariables.module.scss'; .collection-filters { display: flex; @@ -17,4 +17,4 @@ float: right; opacity: 0; } -} \ No newline at end of file +} diff --git a/src/client/views/search/IconBar.scss b/src/client/views/search/IconBar.scss index 6aaf7918d..05aa099f7 100644 --- a/src/client/views/search/IconBar.scss +++ b/src/client/views/search/IconBar.scss @@ -1,4 +1,4 @@ -@import "../global/globalCssVariables"; +@import '../global/globalCssVariables.module.scss'; .icon-bar { display: flex; @@ -7,4 +7,4 @@ height: auto; width: 100%; flex-direction: row-reverse; -} \ No newline at end of file +} diff --git a/src/client/views/search/IconButton.scss b/src/client/views/search/IconButton.scss index 3cb08d756..d2a2ea369 100644 --- a/src/client/views/search/IconButton.scss +++ b/src/client/views/search/IconButton.scss @@ -1,4 +1,4 @@ -@import "../global/globalCssVariables"; +@import '../global/globalCssVariables.module.scss'; .type-outer { display: flex; @@ -24,7 +24,7 @@ .fontawesome-icon { height: 15px; - width: 15px + width: 15px; } } @@ -46,8 +46,8 @@ background-color: $medium-blue; opacity: 1; - +.filter-description { + + .filter-description { opacity: 1; } } -} \ No newline at end of file +} diff --git a/src/client/views/search/IconButton.tsx b/src/client/views/search/IconButton.tsx index e12e4511c..20084b64d 100644 --- a/src/client/views/search/IconButton.tsx +++ b/src/client/views/search/IconButton.tsx @@ -4,7 +4,7 @@ import { action, IReactionDisposer, observable, reaction, runInAction } from 'mo import { observer } from 'mobx-react'; import * as React from 'react'; import { DocumentType } from '../../documents/DocumentTypes'; -import '../global/globalCssVariables.scss'; +import '../global/globalCssVariables.module.scss'; import { IconBar } from './IconBar'; import './IconButton.scss'; import './SearchBox.scss'; diff --git a/src/client/views/search/NaviconButton.scss b/src/client/views/search/NaviconButton.scss index 13d31bbe9..917635c0b 100644 --- a/src/client/views/search/NaviconButton.scss +++ b/src/client/views/search/NaviconButton.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables'; +@import '../global/globalCssVariables.module.scss'; $height-icon: 15px; $width-line: 30px; diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index a439aea3e..a3c4bd2ed 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -1,5 +1,5 @@ -@import "../global/globalCssVariables"; -@import "./NaviconButton.scss"; +@import '../global/globalCssVariables.module.scss'; +@import './NaviconButton.scss'; .searchBox-container { width: 100%; @@ -47,7 +47,6 @@ } .section-header { - .section-title { font-size: $body-text; font-weight: 600; @@ -57,7 +56,7 @@ display: flex; color: $light-gray; } - + padding: 5px 10px; display: flex; flex-direction: column; @@ -71,7 +70,7 @@ flex-direction: column; width: 100%; height: fit-content; - justify-content: "center"; + justify-content: 'center'; .searchBox-recommendations-view { margin-top: 10px; @@ -81,8 +80,6 @@ flex-direction: column; gap: 10px; padding: 0px 10px; - - } } @@ -91,8 +88,8 @@ flex-direction: column; width: 100%; height: fit-content; - justify-content: "center"; - + justify-content: 'center'; + .searchBox-results-view { display: inline-block; width: 100%; @@ -147,4 +144,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/client/views/search/SelectorContextMenu.scss b/src/client/views/search/SelectorContextMenu.scss index a114f679c..097a6107d 100644 --- a/src/client/views/search/SelectorContextMenu.scss +++ b/src/client/views/search/SelectorContextMenu.scss @@ -1,4 +1,4 @@ -@import "../global/globalCssVariables"; +@import '../global/globalCssVariables.module.scss'; .parents { background: $light-blue; @@ -13,4 +13,4 @@ border-color: $medium-blue; border-bottom-style: solid; } -} \ No newline at end of file +} diff --git a/src/client/views/search/ToggleBar.scss b/src/client/views/search/ToggleBar.scss index 3a164f133..9e27db2bc 100644 --- a/src/client/views/search/ToggleBar.scss +++ b/src/client/views/search/ToggleBar.scss @@ -1,4 +1,4 @@ -@import "../global/globalCssVariables"; +@import '../global/globalCssVariables.module.scss'; .toggle-title { display: flex; @@ -38,4 +38,4 @@ border-radius: 10px; background-color: $white; } -} \ No newline at end of file +} diff --git a/src/client/views/topbar/TopBar.scss b/src/client/views/topbar/TopBar.scss index 2237d5ac1..20245104e 100644 --- a/src/client/views/topbar/TopBar.scss +++ b/src/client/views/topbar/TopBar.scss @@ -1,5 +1,4 @@ -@import '../global/globalCssVariables'; - +@import '../global/globalCssVariables.module.scss'; .topbar-container { flex-direction: column; diff --git a/src/client/views/webcam/DashWebRTCVideo.scss b/src/client/views/webcam/DashWebRTCVideo.scss index 249aee9d6..5744ebbcd 100644 --- a/src/client/views/webcam/DashWebRTCVideo.scss +++ b/src/client/views/webcam/DashWebRTCVideo.scss @@ -1,11 +1,11 @@ -@import "../global/globalCssVariables"; +@import '../global/globalCssVariables.module.scss'; .webcam-cont { background: whitesmoke; color: grey; border-radius: 15px; box-shadow: #9c9396 0.2vw 0.2vw 0.4vw; - border: solid #BBBBBBBB 5px; + border: solid #bbbbbbbb 5px; pointer-events: all; display: flex; flex-direction: column; @@ -44,7 +44,7 @@ #roomName { outline: none; border-radius: inherit; - border: 1px solid #BBBBBBBB; + border: 1px solid #bbbbbbbb; margin: 10px; padding: 10px; } @@ -79,5 +79,4 @@ margin: 5px; border: 1px solid black; } - -} \ No newline at end of file +} diff --git a/src/mobile/ImageUpload.scss b/src/mobile/ImageUpload.scss index 6669a3d21..e4156ee8e 100644 --- a/src/mobile/ImageUpload.scss +++ b/src/mobile/ImageUpload.scss @@ -1,4 +1,4 @@ -@import "../client/views/global/globalCssVariables.scss"; +@import '../client/views/global/globalCssVariables.module.scss'; .imgupload_cont { display: flex; @@ -50,7 +50,7 @@ z-index: -1; } - .inputfile+label { + .inputfile + label { font-weight: 700; color: black; background-color: rgba(0, 0, 0, 0); @@ -71,7 +71,7 @@ border-radius: 10px; } - .inputfile.active+label { + .inputfile.active + label { font-style: italic; color: black; background-color: lightgreen; @@ -81,7 +81,6 @@ .status { font-size: 2em; } - } .image-upload { @@ -134,5 +133,7 @@ border-radius: 20px; opacity: 0.2; background-color: black; - transition: all 2s, opacity 1.5s; -} \ No newline at end of file + transition: + all 2s, + opacity 1.5s; +} diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index ee212e4af..d2598c2db 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -14,8 +14,7 @@ import { Utils } from '../Utils'; import './ImageUpload.scss'; import { MobileInterface } from './MobileInterface'; import * as React from 'react'; -//import { DFLT_IMAGE_NATIVE_DIM } from '../client/views/global/globalCssVariables.scss'; -const DFLT_IMAGE_NATIVE_DIM = '50px'; +const { default: { DFLT_IMAGE_NATIVE_DIM } } = require('../client/views/global/globalCssVariables.module.scss'); // prettier-ignore export interface ImageUploadProps { Document: Doc; // Target document for upload (upload location) } diff --git a/webpack.config.js b/webpack.config.js index c1464ac2a..a153616b8 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -12,8 +12,8 @@ const plugins = [ // new ForkTsCheckerWebpackPlugin({ // typescript: { // // useTypescriptIncrementalApi: true, - // // tslint: true, - // memoryLimit: 4096, + // eslint: true, + // memoryLimit: 8192, // }, // // tslint: true, // // memoryLimit: 4096, @@ -108,16 +108,22 @@ module.exports = { }, { test: /\.scss|css$/, + exclude: /\.module\.scss$/i, use: [ - { - loader: 'style-loader', - }, - { - loader: 'css-loader', - }, - { - loader: 'sass-loader', - }, + { loader: 'style-loader' }, // eslint-disable-next-line prettier/prettier + { loader: 'css-loader' }, + { loader: 'sass-loader' }, + ], + }, + + // -------- + // SCSS MODULES - all have .module. in their name and can export to .tsx + { + test: /\.module\.scss$/i, + use: [ + { loader: 'style-loader' }, // eslint-disable-next-line prettier/prettier + { loader: 'css-loader', options: { modules: true } }, + { loader: 'sass-loader' }, ], }, { -- cgit v1.2.3-70-g09d2 From 1cf241544f8063e3d71406238a584299b6ced794 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 13 Dec 2023 21:17:50 -0500 Subject: cleaned up props/_props handling by inherting from ObservableReactComponent --- .vscode/settings.json | 4 +- src/Utils.ts | 7 ++- src/client/util/DocumentManager.ts | 3 +- src/client/util/SelectionManager.ts | 22 +++---- src/client/views/AntimodeMenu.tsx | 13 +---- src/client/views/ContextMenu.tsx | 5 +- src/client/views/ContextMenuItem.tsx | 15 ++--- src/client/views/DashboardView.tsx | 4 +- src/client/views/DocComponent.tsx | 43 ++++++-------- src/client/views/DocumentButtonBar.tsx | 8 +-- src/client/views/DocumentDecorations.tsx | 6 +- src/client/views/EditableView.tsx | 14 ++--- src/client/views/MainView.tsx | 47 +++++++-------- src/client/views/MarqueeAnnotator.tsx | 20 +++---- src/client/views/ObservableReactComponent.tsx | 21 +++++++ src/client/views/OverlayView.tsx | 18 ++---- src/client/views/PreviewCursor.tsx | 13 +++-- src/client/views/PropertiesDocContextSelector.tsx | 17 ++---- src/client/views/PropertiesView.tsx | 26 ++++----- src/client/views/ScriptingRepl.tsx | 29 +++------- src/client/views/SidebarAnnos.tsx | 25 ++++---- .../views/collections/CollectionCarousel3DView.tsx | 6 +- .../views/collections/CollectionCarouselView.tsx | 7 ++- .../views/collections/CollectionDockingView.tsx | 15 ++--- .../collections/CollectionMasonryViewFieldRow.tsx | 18 +++--- src/client/views/collections/CollectionMenu.tsx | 2 +- .../views/collections/CollectionNoteTakingView.tsx | 8 ++- .../views/collections/CollectionPileView.tsx | 7 ++- .../collections/CollectionStackedTimeline.tsx | 22 ++----- .../views/collections/CollectionStackingView.tsx | 15 ++--- .../CollectionStackingViewFieldColumn.tsx | 20 +++---- src/client/views/collections/CollectionSubView.tsx | 19 +++--- .../views/collections/CollectionTimeView.tsx | 7 ++- .../views/collections/CollectionTreeView.tsx | 16 ++---- src/client/views/collections/CollectionView.tsx | 26 ++++----- src/client/views/collections/TabDocView.tsx | 41 ++++++------- src/client/views/collections/TreeView.tsx | 23 ++++---- .../CollectionFreeFormInfoState.tsx | 20 +++---- .../CollectionFreeFormInfoUI.tsx | 33 ++++------- .../CollectionFreeFormLinkView.tsx | 15 ++--- .../collectionFreeForm/CollectionFreeFormView.tsx | 13 +---- .../collectionFreeForm/MarqueeOptionsMenu.tsx | 1 - .../collections/collectionFreeForm/MarqueeView.tsx | 23 ++++---- .../collectionGrid/CollectionGridView.tsx | 7 ++- .../collectionLinear/CollectionLinearView.tsx | 19 ++---- .../CollectionMulticolumnView.tsx | 11 +++- .../CollectionMultirowView.tsx | 11 +++- .../collectionSchema/CollectionSchemaView.tsx | 37 +++++------- .../collections/collectionSchema/SchemaRowBox.tsx | 14 ++--- .../collectionSchema/SchemaTableCell.tsx | 67 +++++++++------------- src/client/views/linking/LinkMenu.tsx | 9 +-- src/client/views/linking/LinkMenuItem.tsx | 26 ++++----- src/client/views/nodes/AudioBox.tsx | 20 +++---- .../views/nodes/CollectionFreeFormDocumentView.tsx | 29 ++++------ src/client/views/nodes/ComparisonBox.tsx | 20 ++----- src/client/views/nodes/DocumentContentsView.tsx | 32 ++++------- src/client/views/nodes/DocumentIcon.tsx | 26 ++++----- src/client/views/nodes/DocumentLinksButton.tsx | 19 ++---- src/client/views/nodes/DocumentView.tsx | 36 ++++-------- src/client/views/nodes/EquationBox.tsx | 14 +---- src/client/views/nodes/FontIconBox/FontIconBox.tsx | 14 ++--- src/client/views/nodes/FunctionPlotBox.tsx | 14 +---- src/client/views/nodes/ImageBox.tsx | 12 +--- src/client/views/nodes/KeyValueBox.tsx | 27 ++++----- src/client/views/nodes/KeyValuePair.tsx | 29 ++++------ src/client/views/nodes/LabelBox.tsx | 14 ++--- src/client/views/nodes/LinkAnchorBox.tsx | 19 ++---- src/client/views/nodes/LinkBox.tsx | 15 ++--- src/client/views/nodes/LinkDocPreview.tsx | 21 +++---- src/client/views/nodes/MapBox/MapAnchorMenu.tsx | 5 +- src/client/views/nodes/MapBox/MapBox.tsx | 22 +++---- src/client/views/nodes/PDFBox.tsx | 12 +--- src/client/views/nodes/VideoBox.tsx | 13 +---- src/client/views/nodes/WebBox.tsx | 11 +--- src/client/views/nodes/audio/AudioWaveform.tsx | 17 ++---- .../views/nodes/formattedText/DashFieldView.tsx | 18 +++--- .../views/nodes/formattedText/FormattedTextBox.tsx | 15 ++--- .../views/nodes/formattedText/RichTextMenu.tsx | 44 +++++--------- src/client/views/nodes/trails/PresElementBox.tsx | 17 ++---- src/client/views/pdf/AnchorMenu.tsx | 14 ++--- src/client/views/pdf/PDFViewer.tsx | 22 +++---- 81 files changed, 578 insertions(+), 911 deletions(-) create mode 100644 src/client/views/ObservableReactComponent.tsx (limited to 'src/client/views/collections/CollectionCarousel3DView.tsx') diff --git a/.vscode/settings.json b/.vscode/settings.json index 8849f30dd..5239d22c0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,5 +13,7 @@ "editor.defaultFormatter": "esbenp.prettier-vscode", "[typescriptreact]": { "editor.defaultFormatter": "esbenp.prettier-vscode" - } + }, + "terminal.integrated.shellIntegration.showWelcome": false, + "terminal.integrated.shellIntegration.enabled": true } diff --git a/src/Utils.ts b/src/Utils.ts index d54760100..3a2bbf9a1 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -440,7 +440,12 @@ export namespace Utils { socket.on(message, (room: any) => handler(socket, room)); } } -export function copyProps(thing: { _prevProps: any; props: any; _props: any }) { +export function copyProps(thing: { props: any; _props: any }, prevProps: any) { + Object.keys(prevProps).forEach(action(pkey => + (prevProps)[pkey] !== (thing.props as any)[pkey] && + ((thing._props as any)[pkey] = (thing.props as any)[pkey]))); // prettier-ignore +} +export function copyPropsFull(thing: { _prevProps: any; props: any; _props: any }) { Object.keys(thing._prevProps).forEach(action(pkey => (thing._prevProps as any)[pkey] !== (thing.props as any)[pkey] && ((thing._props as any)[pkey] = (thing.props as any)[pkey]))); // prettier-ignore diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 7fcda75cc..4816f3317 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,4 +1,4 @@ -import { action, computed, makeObservable, observable, ObservableSet, observe, reaction } from 'mobx'; +import { action, computed, makeObservable, observable, ObservableSet, observe } from 'mobx'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; import { AclAdmin, AclEdit, Animation } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; @@ -13,7 +13,6 @@ import { LightboxView } from '../views/LightboxView'; import { DocFocusOptions, DocumentView, DocumentViewInternal, OpenWhere, OpenWhereMod } from '../views/nodes/DocumentView'; import { KeyValueBox } from '../views/nodes/KeyValueBox'; import { LinkAnchorBox } from '../views/nodes/LinkAnchorBox'; -import { LoadingBox } from '../views/nodes/LoadingBox'; import { PresBox } from '../views/nodes/trails'; import { ScriptingGlobals } from './ScriptingGlobals'; import { SelectionManager } from './SelectionManager'; diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 7cf0d62d0..4bd6647c0 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -1,4 +1,4 @@ -import { action, makeObservable, observable } from 'mobx'; +import { action, makeObservable, observable, runInAction } from 'mobx'; import { Doc, Opt } from '../../fields/Doc'; import { DocViews } from '../../fields/DocSymbols'; import { List } from '../../fields/List'; @@ -26,13 +26,13 @@ export class SelectionManager { } @action - public static SelectSchemaViewDoc(doc: Opt, deselectAllFirst?: boolean) { + public static SelectSchemaViewDoc = (doc: Opt, deselectAllFirst?: boolean) => { if (deselectAllFirst) this.DeselectAll(); this.Instance.SelectedSchemaDocument = doc; - } + }; @action - public static SelectView(docView: DocumentView, extendSelection: boolean): void { + public static SelectView = (docView: DocumentView | undefined, extendSelection: boolean): void => { if (!docView) this.DeselectAll(); else if (!docView.SELECTED) { if (!extendSelection) this.DeselectAll(); @@ -40,29 +40,29 @@ export class SelectionManager { docView.SELECTED = true; docView._props.whenChildContentsActiveChanged(true); } - } + }; @action - public static DeselectView(docView?: DocumentView): void { + public static DeselectView = (docView?: DocumentView): void => { if (docView && this.Instance.SelectedViews.includes(docView)) { docView.SELECTED = false; this.Instance.SelectedViews.splice(this.Instance.SelectedViews.indexOf(docView), 1); docView._props.whenChildContentsActiveChanged(false); } - } - @action - public static DeselectAll(except?: Doc): void { + }; + + public static DeselectAll = (except?: Doc): void => { const found = this.Instance.SelectedViews.find(dv => dv.Document === except); LinkManager.currentLink = undefined; LinkManager.currentLinkAnchor = undefined; - this.Instance.SelectedSchemaDocument = undefined; + runInAction(() => (this.Instance.SelectedSchemaDocument = undefined)); this.Instance.SelectedViews.forEach(dv => { dv.SELECTED = false; dv._props.whenChildContentsActiveChanged(false); }); this.Instance.SelectedViews.length = 0; if (found) this.SelectView(found, false); - } + }; public static IsSelected = (doc?: Doc) => Array.from(doc?.[DocViews] ?? []).some(dv => dv?.SELECTED); public static get Views() { return this.Instance.SelectedViews; } // prettier-ignore diff --git a/src/client/views/AntimodeMenu.tsx b/src/client/views/AntimodeMenu.tsx index f89624941..4c82b10fd 100644 --- a/src/client/views/AntimodeMenu.tsx +++ b/src/client/views/AntimodeMenu.tsx @@ -1,32 +1,25 @@ import { action, makeObservable, observable, runInAction } from 'mobx'; import * as React from 'react'; import { SettingsManager } from '../util/SettingsManager'; -import { copyProps } from '../../Utils'; import './AntimodeMenu.scss'; +import { ObservableReactComponent } from './ObservableReactComponent'; export interface AntimodeMenuProps {} /** * This is an abstract class that serves as the base for a PDF-style or Marquee-style * menu. To use this class, look at PDFMenu.tsx or MarqueeOptionsMenu.tsx for an example. */ -export abstract class AntimodeMenu extends React.Component { +export abstract class AntimodeMenu extends ObservableReactComponent { protected _offsetY: number = 0; protected _offsetX: number = 0; protected _mainCont: React.RefObject = React.createRef(); protected _dragging: boolean = false; - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - @observable protected _top: number = -300; @observable protected _left: number = -300; @observable protected _opacity: number = 0; diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 118a2c5f5..e55bf24a1 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -6,9 +6,10 @@ import { StrCast } from '../../fields/Types'; import { SettingsManager } from '../util/SettingsManager'; import './ContextMenu.scss'; import { ContextMenuItem, ContextMenuProps, OriginalMenuProps } from './ContextMenuItem'; +import { ObservableReactComponent } from './ObservableReactComponent'; @observer -export class ContextMenu extends React.Component { +export class ContextMenu extends ObservableReactComponent<{}> { static Instance: ContextMenu; private _ignoreUp = false; @@ -36,8 +37,8 @@ export class ContextMenu extends React.Component { constructor(props: any) { super(props); - makeObservable(this); ContextMenu.Instance = this; + makeObservable(this); } public setIgnoreEvents(ignore: boolean) { diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 59b223c14..3c9d821a9 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -5,7 +5,7 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { UndoManager } from '../util/UndoManager'; import { SettingsManager } from '../util/SettingsManager'; -import { copyProps } from '../../Utils'; +import { ObservableReactComponent } from './ObservableReactComponent'; export interface OriginalMenuProps { description: string; @@ -27,24 +27,17 @@ export interface SubmenuProps { export type ContextMenuProps = OriginalMenuProps | SubmenuProps; @observer -export class ContextMenuItem extends React.Component { +export class ContextMenuItem extends ObservableReactComponent { @observable private _items: Array = []; @observable private overItem = false; - _prevProps: ContextMenuProps & { selected?: boolean }; - @observable _props: ContextMenuProps & { selected?: boolean }; - constructor(props: ContextMenuProps & { selected?: boolean }) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - componentDidMount() { - runInAction(() => this._items.length = 0); + runInAction(() => (this._items.length = 0)); if ((this.props as SubmenuProps)?.subitems) { (this.props as SubmenuProps).subitems?.forEach(i => runInAction(() => this._items.push(i))); } diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx index 35c0d617b..85cee83d4 100644 --- a/src/client/views/DashboardView.tsx +++ b/src/client/views/DashboardView.tsx @@ -27,6 +27,7 @@ import './DashboardView.scss'; import { Colors } from './global/globalEnums'; import { MainViewModal } from './MainViewModal'; import { ButtonType } from './nodes/FontIconBox/FontIconBox'; +import { ObservableReactComponent } from './ObservableReactComponent'; enum DashboardGroup { MyDashboards, @@ -36,9 +37,8 @@ enum DashboardGroup { // DashboardView is the view with the dashboard previews, rendered when the app first loads @observer -export class DashboardView extends React.Component { +export class DashboardView extends ObservableReactComponent<{}> { public static _urlState: HistoryUtil.DocUrl; - constructor(props: any) { super(props); makeObservable(this); diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 2ce0c085a..235b0dc68 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -1,17 +1,17 @@ -import { action, computed, makeObservable, observable, runInAction, untracked } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; +import * as React from 'react'; +import { returnFalse } from '../../Utils'; import { DateField } from '../../fields/DateField'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; import { AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, DocData } from '../../fields/DocSymbols'; import { List } from '../../fields/List'; -import { Cast } from '../../fields/Types'; import { GetEffectiveAcl, inheritParentAcls } from '../../fields/util'; -import { returnFalse } from '../../Utils'; -import { DocUtils } from '../documents/Documents'; import { DocumentType } from '../documents/DocumentTypes'; -import { DocumentView } from './nodes/DocumentView'; -import * as React from 'react'; +import { DocUtils } from '../documents/Documents'; import { DocumentManager } from '../util/DocumentManager'; +import { ObservableReactComponent } from './ObservableReactComponent'; import { CollectionFreeFormView } from './collections/collectionFreeForm'; +import { DocumentView } from './nodes/DocumentView'; /// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView) export interface DocComponentProps { @@ -20,18 +20,14 @@ export interface DocComponentProps { LayoutTemplateString?: string; } export function DocComponent

() { - class Component extends React.Component> { - @observable _props!: React.PropsWithChildren

; - constructor(props: React.PropsWithChildren

) { + class Component extends ObservableReactComponent> { + constructor(props: any) { super(props); - this._props = props; makeObservable(this); } - componentDidUpdate() { - // untracked(() => (this._props = this.props)); - } + //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then - @computed get Document() { + get Document() { return this._props.Document; } // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info @@ -57,24 +53,18 @@ interface ViewBoxBaseProps { renderDepth: number; } export function ViewBoxBaseComponent

() { - class Component extends React.Component> { - @observable _props: React.PropsWithChildren

; - constructor(props: React.PropsWithChildren

) { - super(props); - this._props = props; - makeObservable(this); - } + class Component extends ObservableReactComponent> { //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then //@computed get Document(): T { return schemaCtor(this.props.Document); } get Document() { return this._props.Document; } // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info - get layoutDoc() { + @computed get layoutDoc() { return Doc.Layout(this.Document); } // This is the data part of a document -- ie, the data that is constant across all views of the document - get dataDoc() { + @computed get dataDoc() { return this.Document.isTemplateForField || this.Document.isTemplateDoc ? this._props.TemplateDataDocument ?? this.Document[DocData] : this.Document[DocData]; } // key where data is stored @@ -99,13 +89,12 @@ export interface ViewBoxAnnotatableProps { isAnnotationOverlay?: boolean; } export function ViewBoxAnnotatableComponent

() { - class Component extends React.Component> { - @observable _props: React.PropsWithChildren

; - constructor(props: React.PropsWithChildren

) { + class Component extends ObservableReactComponent> { + constructor(props: any) { super(props); - this._props = props; makeObservable(this); } + @observable _annotationKeySuffix = () => 'annotations'; @observable _isAnyChildContentActive = false; //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index a8ad4150e..50ca3af06 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -28,6 +28,7 @@ import { GoogleRef } from './nodes/formattedText/FormattedTextBox'; import { PinProps } from './nodes/trails'; import { TemplateMenu } from './TemplateMenu'; import * as React from 'react'; +import { ObservableReactComponent } from './ObservableReactComponent'; // import * as higflyout from '@hig/flyout'; // export const { anchorPoints } = higflyout; // export const Flyout = higflyout.default; @@ -42,12 +43,11 @@ enum UtilityButtonState { } @observer -export class DocumentButtonBar extends React.Component<{ views: () => (DocumentView | undefined)[]; stack?: any }, {}> { +export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (DocumentView | undefined)[]; stack?: any }> { private _dragRef = React.createRef(); private _pullAnimating = false; private _pushAnimating = false; private _pullColorAnimating = false; - @observable private pushIcon: IconProp = 'arrow-alt-circle-up'; @observable private pullIcon: IconProp = 'arrow-alt-circle-down'; @observable private pullColor: string = 'white'; @@ -60,12 +60,10 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV public static hasPushedHack = false; public static hasPulledHack = false; - @observable _props: { views: () => (DocumentView | undefined)[] }; constructor(props: { views: () => (DocumentView | undefined)[] }) { super(props); - this._props = props; + DocumentButtonBar.Instance = this; makeObservable(this); - runInAction(() => (DocumentButtonBar.Instance = this)); } public startPullOutcome = action((success: boolean) => { diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 8bcc1cb56..7003485d2 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -34,6 +34,7 @@ import { DocumentView, OpenWhereMod } from './nodes/DocumentView'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { ImageBox } from './nodes/ImageBox'; import * as React from 'react'; +import { ObservableReactComponent } from './ObservableReactComponent'; interface DocumentDecorationsProps { PanelWidth: number; @@ -42,7 +43,7 @@ interface DocumentDecorationsProps { boundsTop: number; } @observer -export class DocumentDecorations extends React.Component { +export class DocumentDecorations extends ObservableReactComponent { static Instance: DocumentDecorations; private _resizeHdlId = ''; private _keyinput = React.createRef(); @@ -66,11 +67,10 @@ export class DocumentDecorations extends React.Component; constructor(props: React.PropsWithChildren) { super(props); - this._props = props; makeObservable(this); + DocumentDecorations.Instance = this; document.addEventListener('pointermove', // show decorations whenever pointer moves outside of selection bounds. action(e => { diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 3db77be71..836a184eb 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -1,13 +1,13 @@ -import * as React from 'react'; import { action, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import * as Autosuggest from 'react-autosuggest'; import { ObjectField } from '../../fields/ObjectField'; import './EditableView.scss'; import { DocumentIconContainer } from './nodes/DocumentIcon'; -import { OverlayView } from './OverlayView'; -import { copyProps } from '../../Utils'; import { FieldView, FieldViewProps } from './nodes/FieldView'; +import { ObservableReactComponent } from './ObservableReactComponent'; +import { OverlayView } from './OverlayView'; export interface EditableProps { /** @@ -60,18 +60,15 @@ export interface EditableProps { * of the content, and set the value based on the entered string. */ @observer -export class EditableView extends React.Component { +export class EditableView extends ObservableReactComponent { private _ref = React.createRef(); private _inputref: HTMLInputElement | HTMLTextAreaElement | null = null; _overlayDisposer?: () => void; _editingDisposer?: IReactionDisposer; @observable _editing: boolean = false; - _prevProps: EditableProps; - @observable _props: EditableProps; constructor(props: EditableProps) { super(props); - this._props = this._prevProps = props; makeObservable(this); this._editing = this._props.editing ? true : false; } @@ -96,8 +93,7 @@ export class EditableView extends React.Component { ); } - componentDidUpdate() { - copyProps(this); + componentDidUpdate(prevProps: Readonly) { if (this._editing && this._props.editing === false) { this._inputref?.value && this.finalizeEdit(this._inputref.value, false, true, false); } else if (this._props.editing !== undefined) { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 4f96b9234..f65675792 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -8,20 +8,19 @@ import { observer } from 'mobx-react'; import 'normalize.css'; import * as React from 'react'; import '../../../node_modules/browndash-components/dist/styles/global.min.css'; +import { Utils, emptyFunction, lightOrDark, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents } from '../../Utils'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; import { DocCast, StrCast } from '../../fields/Types'; -import { emptyFunction, lightOrDark, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, Utils } from '../../Utils'; -import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { DocServer } from '../DocServer'; -import { Docs } from '../documents/Documents'; +import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; +import { Docs } from '../documents/Documents'; import { CaptureManager } from '../util/CaptureManager'; import { DocumentManager } from '../util/DocumentManager'; import { DragManager } from '../util/DragManager'; import { GroupManager } from '../util/GroupManager'; import { HistoryUtil } from '../util/History'; import { Hypothesis } from '../util/HypothesisUtils'; -import { ReportManager } from '../util/reportManager/ReportManager'; import { RTFMarkup } from '../util/RTFMarkup'; import { ScriptingGlobals } from '../util/ScriptingGlobals'; import { SelectionManager } from '../util/SelectionManager'; @@ -30,13 +29,7 @@ import { SettingsManager } from '../util/SettingsManager'; import { SharingManager } from '../util/SharingManager'; import { SnappingManager } from '../util/SnappingManager'; import { Transform } from '../util/Transform'; -import { TimelineMenu } from './animationtimeline/TimelineMenu'; -import { CollectionDockingView } from './collections/CollectionDockingView'; -import { MarqueeOptionsMenu } from './collections/collectionFreeForm/MarqueeOptionsMenu'; -import { CollectionLinearView } from './collections/collectionLinear'; -import { CollectionMenu } from './collections/CollectionMenu'; -import { TabDocView } from './collections/TabDocView'; -import './collections/TreeView.scss'; +import { ReportManager } from '../util/reportManager/ReportManager'; import { ComponentDecorations } from './ComponentDecorations'; import { ContextMenu } from './ContextMenu'; import { DashboardView } from './DashboardView'; @@ -45,15 +38,24 @@ import { DocumentDecorations } from './DocumentDecorations'; import { GestureOverlay } from './GestureOverlay'; import { KeyManager } from './GlobalKeyHandler'; import { LightboxView } from './LightboxView'; -import { LinkMenu } from './linking/LinkMenu'; import './MainView.scss'; +import { ObservableReactComponent } from './ObservableReactComponent'; +import { OverlayView } from './OverlayView'; +import { PreviewCursor } from './PreviewCursor'; +import { PropertiesView } from './PropertiesView'; +import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider'; +import { TimelineMenu } from './animationtimeline/TimelineMenu'; +import { CollectionDockingView } from './collections/CollectionDockingView'; +import { CollectionMenu } from './collections/CollectionMenu'; +import { TabDocView } from './collections/TabDocView'; +import './collections/TreeView.scss'; +import { CollectionFreeFormLinksView } from './collections/collectionFreeForm'; +import { MarqueeOptionsMenu } from './collections/collectionFreeForm/MarqueeOptionsMenu'; +import { CollectionLinearView } from './collections/collectionLinear'; +import { LinkMenu } from './linking/LinkMenu'; import { AudioBox } from './nodes/AudioBox'; import { DocButtonState } from './nodes/DocumentLinksButton'; import { DocumentView, DocumentViewInternal, OpenWhere, OpenWhereMod } from './nodes/DocumentView'; -import { DashFieldViewMenu } from './nodes/formattedText/DashFieldView'; -import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; -import { RichTextMenu } from './nodes/formattedText/RichTextMenu'; -import GenerativeFill from './nodes/generativeFill/GenerativeFill'; import { ImageBox } from './nodes/ImageBox'; import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup'; import { LinkDocPreview, LinkInfo } from './nodes/LinkDocPreview'; @@ -61,20 +63,19 @@ import { MapAnchorMenu } from './nodes/MapBox/MapAnchorMenu'; import { MapBox } from './nodes/MapBox/MapBox'; import { RadialMenu } from './nodes/RadialMenu'; import { TaskCompletionBox } from './nodes/TaskCompletedBox'; +import { DashFieldViewMenu } from './nodes/formattedText/DashFieldView'; +import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; +import { RichTextMenu } from './nodes/formattedText/RichTextMenu'; +import GenerativeFill from './nodes/generativeFill/GenerativeFill'; import { PresBox } from './nodes/trails'; -import { OverlayView } from './OverlayView'; import { AnchorMenu } from './pdf/AnchorMenu'; import { GPTPopup } from './pdf/GPTPopup/GPTPopup'; -import { PreviewCursor } from './PreviewCursor'; -import { PropertiesView } from './PropertiesView'; -import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider'; import { TopBar } from './topbar/TopBar'; -import { CollectionFreeFormLinksView } from './collections/collectionFreeForm'; const { default: { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } } = require('./global/globalCssVariables.module.scss'); // prettier-ignore const _global = (window /* browser */ || global) /* node */ as any; @observer -export class MainView extends React.Component { +export class MainView extends ObservableReactComponent<{}> { public static Instance: MainView; public static Live: boolean = false; private _docBtnRef = React.createRef(); @@ -1064,7 +1065,7 @@ export class MainView extends React.Component { - {this.mapBoxHack} + {/* {this.mapBoxHack} */} {/* */} diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 3f0db4258..2e27d1f70 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -15,6 +15,7 @@ import './MarqueeAnnotator.scss'; import { DocumentView } from './nodes/DocumentView'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { AnchorMenu } from './pdf/AnchorMenu'; +import { ObservableReactComponent } from './ObservableReactComponent'; const _global = (window /* browser */ || global) /* node */ as any; export interface MarqueeAnnotatorProps { @@ -38,23 +39,18 @@ export interface MarqueeAnnotatorProps { highlightDragSrcColor?: string; } @observer -export class MarqueeAnnotator extends React.Component { +export class MarqueeAnnotator extends ObservableReactComponent { private _start: { x: number; y: number } = { x: 0, y: 0 }; - @observable private _width: number = 0; - @observable private _height: number = 0; - @computed get top() { return Math.min(this._start.y, this._start.y + this._height); } // prettier-ignore - @computed get left() { return Math.min(this._start.x, this._start.x + this._width);} // prettier-ignore - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidMount() { - copyProps(this); - } + + @observable private _width: number = 0; + @observable private _height: number = 0; + @computed get top() { return Math.min(this._start.y, this._start.y + this._height); } // prettier-ignore + @computed get left() { return Math.min(this._start.x, this._start.x + this._width);} // prettier-ignore @action static clearAnnotations(savedAnnotations: ObservableMap) { diff --git a/src/client/views/ObservableReactComponent.tsx b/src/client/views/ObservableReactComponent.tsx new file mode 100644 index 000000000..2d8dc9af9 --- /dev/null +++ b/src/client/views/ObservableReactComponent.tsx @@ -0,0 +1,21 @@ +import { makeObservable, observable } from 'mobx'; +import * as React from 'react'; +import { copyProps } from '../../Utils'; +import './AntimodeMenu.scss'; +export interface AntimodeMenuProps {} + +/** + * This is an abstract class that serves as the base for a PDF-style or Marquee-style + * menu. To use this class, look at PDFMenu.tsx or MarqueeOptionsMenu.tsx for an example. + */ +export abstract class ObservableReactComponent extends React.Component { + @observable _props: React.PropsWithChildren; + constructor(props: React.PropsWithChildren) { + super(props); + this._props = props; + makeObservable(this); + } + componentDidUpdate(prevProps: Readonly): void { + copyProps(this, prevProps); + } +} diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 673432a60..915c3c18f 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -1,9 +1,9 @@ -import { action, computed, makeObservable, observable, toJS } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; import ReactLoading from 'react-loading'; -import { Utils, copyProps, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue, setupMoveUpEvents } from '../../Utils'; +import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue, setupMoveUpEvents } from '../../Utils'; import { Doc } from '../../fields/Doc'; import { Height, Width } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; @@ -12,6 +12,7 @@ import { DocumentType } from '../documents/DocumentTypes'; import { DragManager } from '../util/DragManager'; import { Transform } from '../util/Transform'; import { LightboxView } from './LightboxView'; +import { ObservableReactComponent } from './ObservableReactComponent'; import './OverlayView.scss'; import { DefaultStyleProvider } from './StyleProvider'; import { DocumentView, DocumentViewInternal } from './nodes/DocumentView'; @@ -34,19 +35,14 @@ export interface OverlayWindowProps { } @observer -export class OverlayWindow extends React.Component { +export class OverlayWindow extends ObservableReactComponent { @observable x: number = 0; @observable y: number = 0; @observable width: number = 0; @observable height: number = 0; - - _prevProps: OverlayWindowProps; - @observable _props: OverlayWindowProps; constructor(props: OverlayWindowProps) { super(props); - this._props = this._prevProps = props; makeObservable(this); - const opts = props.overlayOptions; this.x = opts.x; this.y = opts.y; @@ -54,10 +50,6 @@ export class OverlayWindow extends React.Component { this.height = opts.height || 200; } - componentDidUpdate() { - copyProps(this); - } - onPointerDown = (_: React.PointerEvent) => { document.removeEventListener('pointermove', this.onPointerMove); document.removeEventListener('pointerup', this.onPointerUp); @@ -115,7 +107,7 @@ export class OverlayWindow extends React.Component { } @observer -export class OverlayView extends React.Component { +export class OverlayView extends ObservableReactComponent<{}> { public static Instance: OverlayView; @observable.shallow _elements: JSX.Element[] = []; diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 6e1a2cfb1..5ec9a7d46 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -1,17 +1,18 @@ import { action, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Doc, Opt } from '../../fields/Doc'; import { lightOrDark, returnFalse } from '../../Utils'; -import { Docs, DocumentOptions, DocUtils } from '../documents/Documents'; +import { Doc, Opt } from '../../fields/Doc'; +import { DocUtils, Docs, DocumentOptions } from '../documents/Documents'; import { ImageUtils } from '../util/Import & Export/ImageUtils'; import { Transform } from '../util/Transform'; -import { undoBatch, UndoManager } from '../util/UndoManager'; -import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; +import { UndoManager, undoBatch } from '../util/UndoManager'; +import { ObservableReactComponent } from './ObservableReactComponent'; import './PreviewCursor.scss'; +import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; @observer -export class PreviewCursor extends React.Component<{}> { +export class PreviewCursor extends ObservableReactComponent<{}> { static _instance: PreviewCursor; public static get Instance() { return PreviewCursor._instance; @@ -28,8 +29,8 @@ export class PreviewCursor extends React.Component<{}> { public Doc: Opt; constructor(props: any) { super(props); - PreviewCursor._instance = this; makeObservable(this); + PreviewCursor._instance = this; this._clickPoint = observable([0, 0]); document.addEventListener('keydown', this.onKeyPress); document.addEventListener('paste', this.paste, true); diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx index 5bde9d3c4..a710e7816 100644 --- a/src/client/views/PropertiesDocContextSelector.tsx +++ b/src/client/views/PropertiesDocContextSelector.tsx @@ -1,14 +1,14 @@ -import { computed, makeObservable, observable } from 'mobx'; +import { computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; import { Cast, StrCast } from '../../fields/Types'; import { DocFocusOrOpen } from '../util/DocumentManager'; +import { ObservableReactComponent } from './ObservableReactComponent'; +import './PropertiesDocContextSelector.scss'; import { CollectionDockingView } from './collections/CollectionDockingView'; import { DocumentView, OpenWhere } from './nodes/DocumentView'; -import './PropertiesDocContextSelector.scss'; -import { copyProps } from '../../Utils'; type PropertiesDocContextSelectorProps = { DocView?: DocumentView; @@ -18,17 +18,12 @@ type PropertiesDocContextSelectorProps = { }; @observer -export class PropertiesDocContextSelector extends React.Component { - _prevProps: PropertiesDocContextSelectorProps; - @observable _props: PropertiesDocContextSelectorProps; - constructor(props: PropertiesDocContextSelectorProps) { +export class PropertiesDocContextSelector extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } + @computed get _docs() { if (!this._props.DocView) return []; const target = this._props.DocView._props.Document; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 442d09739..c857c2d6b 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -1,14 +1,15 @@ -import * as React from 'react'; import { IconLookup } from '@fortawesome/fontawesome-svg-core'; import { faAnchor, faArrowRight, faWindowMaximize } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Checkbox, Tooltip } from '@mui/material'; import { Colors, EditableText, IconButton, NumberInput, Size, Slider, Type } from 'browndash-components'; import { concat } from 'lodash'; -import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; +import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { ColorResult, SketchPicker } from 'react-color'; import * as Icons from 'react-icons/bs'; //{BsCollectionFill, BsFillFileEarmarkImageFill} from "react-icons/bs" +import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../Utils'; import { Doc, DocListCast, Field, FieldResult, HierarchyMapping, NumListCast, Opt, ReverseHierarchyMap, StrListCast } from '../../fields/Doc'; import { AclAdmin, DocAcl, DocData } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; @@ -16,8 +17,7 @@ import { InkField } from '../../fields/InkField'; import { List } from '../../fields/List'; import { ComputedField } from '../../fields/ScriptField'; import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types'; -import { GetEffectiveAcl, normalizeEmail, SharingPermissions } from '../../fields/util'; -import { copyProps, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../Utils'; +import { GetEffectiveAcl, SharingPermissions, normalizeEmail } from '../../fields/util'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; import { DocumentManager } from '../util/DocumentManager'; import { GroupManager } from '../util/GroupManager'; @@ -26,19 +26,20 @@ import { SelectionManager } from '../util/SelectionManager'; import { SettingsManager } from '../util/SettingsManager'; import { SharingManager } from '../util/SharingManager'; import { Transform } from '../util/Transform'; -import { undoable, undoBatch, UndoManager } from '../util/UndoManager'; +import { UndoManager, undoBatch, undoable } from '../util/UndoManager'; import { EditableView } from './EditableView'; import { FilterPanel } from './FilterPanel'; import { InkStrokeProperties } from './InkStrokeProperties'; -import { DocumentView, OpenWhere, StyleProviderFunc } from './nodes/DocumentView'; -import { KeyValueBox } from './nodes/KeyValueBox'; -import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails'; +import { ObservableReactComponent } from './ObservableReactComponent'; import { PropertiesButtons } from './PropertiesButtons'; import { PropertiesDocBacklinksSelector } from './PropertiesDocBacklinksSelector'; import { PropertiesDocContextSelector } from './PropertiesDocContextSelector'; import { PropertiesSection } from './PropertiesSection'; import './PropertiesView.scss'; import { DefaultStyleProvider } from './StyleProvider'; +import { DocumentView, OpenWhere, StyleProviderFunc } from './nodes/DocumentView'; +import { KeyValueBox } from './nodes/KeyValueBox'; +import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails'; const _global = (window /* browser */ || global) /* node */ as any; interface PropertiesViewProps { @@ -49,15 +50,12 @@ interface PropertiesViewProps { } @observer -export class PropertiesView extends React.Component { +export class PropertiesView extends ObservableReactComponent { private _widthUndo?: UndoManager.Batch; public static Instance: PropertiesView | undefined; - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; constructor(props: React.PropsWithChildren) { super(props); - this._props = this._prevProps = props; makeObservable(this); PropertiesView.Instance = this; } @@ -120,10 +118,6 @@ export class PropertiesView extends React.Component { ); } - componentDidUpdate() { - copyProps(this); - } - componentWillUnmount() { Object.values(this._disposers).forEach(disposer => disposer?.()); } diff --git a/src/client/views/ScriptingRepl.tsx b/src/client/views/ScriptingRepl.tsx index 8251d20dc..5f20bc745 100644 --- a/src/client/views/ScriptingRepl.tsx +++ b/src/client/views/ScriptingRepl.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, observable, makeObservable } from 'mobx'; +import { action, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { DocumentManager } from '../util/DocumentManager'; @@ -7,29 +7,23 @@ import { CompileScript, Transformer, ts } from '../util/Scripting'; import { ScriptingGlobals } from '../util/ScriptingGlobals'; import { SettingsManager } from '../util/SettingsManager'; import { undoable } from '../util/UndoManager'; -import { DocumentIconContainer } from './nodes/DocumentIcon'; +import { ObservableReactComponent } from './ObservableReactComponent'; import { OverlayView } from './OverlayView'; import './ScriptingRepl.scss'; -import { copyProps } from '../../Utils'; +import { DocumentIconContainer } from './nodes/DocumentIcon'; interface ReplProps { scrollToBottom: () => void; value: { [key: string]: any }; name?: string; } -export class ScriptingObjectDisplay extends React.Component { +export class ScriptingObjectDisplay extends ObservableReactComponent { @observable collapsed = true; - _prevProps: ReplProps; - @observable _props: ReplProps; - constructor(props: ReplProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate(): void { - copyProps(this); - } @action toggle = () => { @@ -84,17 +78,12 @@ interface replValueProps { name?: string; } @observer -export class ScriptingValueDisplay extends React.Component { - _prevProps: replValueProps; - @observable _props: replValueProps; - constructor(props: replValueProps) { +export class ScriptingValueDisplay extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } + render() { const val = this._props.name ? this._props.value[this._props.name] : this._props.value; if (typeof val === 'object') { @@ -126,7 +115,7 @@ export class ScriptingValueDisplay extends React.Component { } @observer -export class ScriptingRepl extends React.Component { +export class ScriptingRepl extends ObservableReactComponent<{}> { constructor(props: any) { super(props); makeObservable(this); diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index 19473de2b..0f4a4260c 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -1,22 +1,23 @@ -import { computed, makeObservable, observable } from 'mobx'; +import { computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { emptyFunction, returnAll, returnFalse, returnOne, returnZero } from '../../Utils'; import { Doc, DocListCast, Field, FieldResult, StrListCast } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; import { List } from '../../fields/List'; import { RichTextField } from '../../fields/RichTextField'; import { DocCast, NumCast, StrCast } from '../../fields/Types'; -import { copyProps, emptyFunction, returnAll, returnFalse, returnOne, returnTrue, returnZero } from '../../Utils'; -import { Docs, DocUtils } from '../documents/Documents'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; +import { DocUtils, Docs } from '../documents/Documents'; import { LinkManager } from '../util/LinkManager'; import { SearchUtil } from '../util/SearchUtil'; import { Transform } from '../util/Transform'; +import { ObservableReactComponent } from './ObservableReactComponent'; +import './SidebarAnnos.scss'; +import { StyleProp } from './StyleProvider'; import { CollectionStackingView } from './collections/CollectionStackingView'; import { FieldViewProps } from './nodes/FieldView'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; -import './SidebarAnnos.scss'; -import { StyleProp } from './StyleProvider'; -import * as React from 'react'; interface ExtraProps { fieldKey: string; @@ -34,18 +35,12 @@ interface ExtraProps { moveDocument: (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean, annotationKey?: string) => boolean; } @observer -export class SidebarAnnos extends React.Component { - _prevProps: FieldViewProps & ExtraProps; - @observable _props: FieldViewProps & ExtraProps; - constructor(props: FieldViewProps & ExtraProps) { +export class SidebarAnnos extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); - // this._props.dataDoc[this.sidebarKey] = new List(); // bcz: can't do this here. it blows away existing things and isn't a robust solution for making sure the field exists -- instead this should happen when the document is created and/or shared - } - componentDidUpdate() { - copyProps(this); } + _stackRef = React.createRef(); @computed get allMetadata() { const keys = new Map>(); diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index f03e38850..a11c53d4d 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { computed } from 'mobx'; +import { computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Utils, returnFalse, returnZero } from '../../../Utils'; @@ -19,6 +19,10 @@ export class CollectionCarousel3DView extends CollectionSubView() { @computed get scrollSpeed() { return this.layoutDoc._autoScrollSpeed ? NumCast(this.layoutDoc._autoScrollSpeed) : 1000; //default scroll speed } + constructor(props: any) { + super(props); + makeObservable(this); + } private _dropDisposer?: DragManager.DragDropDisposer; diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index 299a4d5d3..5d09f14ef 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { computed } from 'mobx'; +import { computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { StopEvent, emptyFunction, returnFalse, returnOne, returnZero } from '../../../Utils'; @@ -16,6 +16,11 @@ import { CollectionSubView } from './CollectionSubView'; export class CollectionCarouselView extends CollectionSubView() { private _dropDisposer?: DragManager.DragDropDisposer; + constructor(props: any) { + super(props); + makeObservable(this); + } + componentWillUnmount() { this._dropDisposer?.(); } diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 4ddf9e69b..0d3ff8bba 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -1,5 +1,6 @@ -import { action, IReactionDisposer, makeObservable, observable, override, reaction, runInAction, untracked } from 'mobx'; +import { action, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import * as GoldenLayout from '../../../client/goldenLayout'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; @@ -10,7 +11,7 @@ import { List } from '../../../fields/List'; import { ImageCast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { GetEffectiveAcl, inheritParentAcls } from '../../../fields/util'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, copyProps, emptyFunction, incrementTitleCopy } from '../../../Utils'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, incrementTitleCopy } from '../../../Utils'; import { DocServer } from '../../DocServer'; import { Docs } from '../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; @@ -19,6 +20,7 @@ import { DragManager } from '../../util/DragManager'; import { InteractionUtils } from '../../util/InteractionUtils'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SelectionManager } from '../../util/SelectionManager'; +import { SettingsManager } from '../../util/SettingsManager'; import { undoable, undoBatch, UndoManager } from '../../util/UndoManager'; import { DashboardView } from '../DashboardView'; import { LightboxView } from '../LightboxView'; @@ -30,8 +32,6 @@ import './CollectionDockingView.scss'; import { CollectionFreeFormView } from './collectionFreeForm'; import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView'; import { TabDocView } from './TabDocView'; -import * as React from 'react'; -import { SettingsManager } from '../../util/SettingsManager'; const _global = (window /* browser */ || global) /* node */ as any; @observer @@ -63,11 +63,8 @@ export class CollectionDockingView extends CollectionSubView() { private _goldenLayout: any = null; static _highlightStyleSheet: any = addStyleSheet(); - _prevProps: SubCollectionViewProps; - @override _props: SubCollectionViewProps; constructor(props: SubCollectionViewProps) { super(props); - this._props = this._prevProps = props; makeObservable(this); if (this._props.renderDepth < 0) runInAction(() => (CollectionDockingView.Instance = this)); //Why is this here? @@ -77,10 +74,6 @@ export class CollectionDockingView extends CollectionSubView() { this.Document.myTrails; // this is equivalent to having a prefetchProxy for myTrails which is needed for the My Trails button in the UI which assumes that Doc.ActiveDashboard.myTrails is legit... } - componentDidUpdate() { - copyProps(this); - } - /** * Switches from dragging a document around a freeform canvas to dragging it as a tab to be docked. * diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index 0905aa078..5dba9e72a 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -1,12 +1,12 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { emptyFunction, numberRange, returnEmptyString, returnFalse, setupMoveUpEvents } from '../../../Utils'; import { Doc, DocListCast } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { PastelSchemaPalette, SchemaHeaderField } from '../../../fields/SchemaHeaderField'; import { ScriptField } from '../../../fields/ScriptField'; -import { emptyFunction, numberRange, returnEmptyString, returnFalse, setupMoveUpEvents } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; import { CompileScript } from '../../util/Scripting'; @@ -14,6 +14,7 @@ import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; import { undoBatch } from '../../util/UndoManager'; import { EditableView } from '../EditableView'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { CollectionStackingView } from './CollectionStackingView'; import './CollectionStackingView.scss'; @@ -41,19 +42,18 @@ interface CMVFieldRowProps { } @observer -export class CollectionMasonryViewFieldRow extends React.Component { +export class CollectionMasonryViewFieldRow extends ObservableReactComponent { + constructor(props: any) { + super(props); + makeObservable(this); + } + @observable private _background = 'inherit'; @observable private _createEmbeddingSelected: boolean = false; @observable private heading: string = ''; @observable private color: string = '#f1efeb'; @observable private collapsed: boolean = false; @observable private _paletteOn = false; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { - super(props); - this._props = props; - makeObservable(this); - } private set _heading(value: string) { runInAction(() => this._props.headingObject && (this._props.headingObject.heading = this.heading = value)); } diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 08fcd544e..3ade2ab56 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -9,7 +9,7 @@ import { List } from '../../../fields/List'; import { ObjectField } from '../../../fields/ObjectField'; import { RichTextField } from '../../../fields/RichTextField'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../../Utils'; +import { copyProps, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../../Utils'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; import { DragManager } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index 702775307..f9d258490 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { action, computed, IReactionDisposer, observable, reaction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import { Doc, Field, Opt } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; @@ -44,6 +44,12 @@ export class CollectionNoteTakingView extends CollectionSubView() { public DividerWidth = 16; @observable docsDraggedRowCol: number[] = []; @observable _scroll = 0; + + constructor(props: any) { + super(props); + makeObservable(this); + } + @computed get chromeHidden() { return BoolCast(this.layoutDoc.chromeHidden) || this.props.onBrowseClick?.() ? true : false; } diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx index a0f8b9c89..170b1f1ec 100644 --- a/src/client/views/collections/CollectionPileView.tsx +++ b/src/client/views/collections/CollectionPileView.tsx @@ -1,4 +1,4 @@ -import { action, computed, IReactionDisposer } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import { Doc, DocListCast } from '../../../fields/Doc'; import { ScriptField } from '../../../fields/ScriptField'; @@ -19,6 +19,11 @@ export class CollectionPileView extends CollectionSubView() { _originalChrome: any = ''; _disposers: { [name: string]: IReactionDisposer } = {}; + constructor(props: any) { + super(props); + makeObservable(this); + } + componentDidMount() { if (this.layoutEngine() !== computePassLayout.name && this.layoutEngine() !== computeStarburstLayout.name) { this.Document._freeform_pileEngine = computePassLayout.name; diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 1b14b31ac..d37a942d0 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -1,4 +1,4 @@ -import { action, computed, IReactionDisposer, makeObservable, observable, override, reaction, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; @@ -9,7 +9,7 @@ import { listSpec } from '../../../fields/Schema'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; import { Cast, NumCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; -import { copyProps, emptyFunction, formatTime, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnTrue, returnZero, setupMoveUpEvents, smoothScrollHorizontal, StopEvent } from '../../../Utils'; +import { emptyFunction, formatTime, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnTrue, returnZero, setupMoveUpEvents, smoothScrollHorizontal, StopEvent } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; import { DocumentManager } from '../../util/DocumentManager'; @@ -26,6 +26,7 @@ import { AudioWaveform } from '../nodes/audio/AudioWaveform'; import { DocFocusFunc, DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere } from '../nodes/DocumentView'; import { LabelBox } from '../nodes/LabelBox'; import { VideoBox } from '../nodes/VideoBox'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import './CollectionStackedTimeline.scss'; export type CollectionStackedTimelineProps = { @@ -56,17 +57,10 @@ export enum TrimScope { export class CollectionStackedTimeline extends CollectionSubView() { @observable static SelectingRegion: CollectionStackedTimeline | undefined = undefined; @observable public static CurrentlyPlaying: DocumentView[]; - - _prevProps: React.PropsWithChildren; - @override _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } static LabelScript: ScriptField; static LabelPlayScript: ScriptField; @@ -697,21 +691,15 @@ interface StackedTimelineAnchorProps { } @observer -class StackedTimelineAnchor extends React.Component { +class StackedTimelineAnchor extends ObservableReactComponent { _lastTimecode: number; _disposer: IReactionDisposer | undefined; - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; constructor(props: React.PropsWithChildren) { super(props); - this._props = this._prevProps = props; makeObservable(this); this._lastTimecode = this._props.currentTimecode(); } - componentDidUpdate() { - copyProps(this); - } // updates marker document title to reflect correct timecodes computeTitle = () => { diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index d6105c184..16adf4b96 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -1,8 +1,8 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import * as CSS from 'csstype'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction, untracked } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Doc, Opt } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; @@ -11,7 +11,7 @@ import { listSpec } from '../../../fields/Schema'; import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { copyProps, emptyFunction, returnEmptyDoclist, returnFalse, returnNone, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnFalse, returnNone, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { CollectionViewType } from '../../documents/DocumentTypes'; import { DragManager, dropActionType } from '../../util/DragManager'; @@ -31,7 +31,7 @@ import { StyleProp } from '../StyleProvider'; import { CollectionMasonryViewFieldRow } from './CollectionMasonryViewFieldRow'; import './CollectionStackingView.scss'; import { CollectionStackingViewFieldColumn } from './CollectionStackingViewFieldColumn'; -import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView'; +import { CollectionSubView } from './CollectionSubView'; const _global = (window /* browser */ || global) /* node */ as any; export type collectionStackingViewProps = { @@ -115,22 +115,15 @@ export class CollectionStackingView extends CollectionSubView>; - _props: React.PropsWithChildren>; constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); - if (this.colHeaderData === undefined) { // TODO: what is a layout doc? Is it literally how this document is supposed to be layed out? // here we're making an empty list of column headers (again, what Mehek showed us) this.dataDoc['_' + this.fieldKey + '_columnHeaders'] = new List(); } } - componentDidUpdate() { - copyProps(this); - } // TODO: plj - these are the children children = (docs: Doc[]) => { diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 7ea146479..2302bfbc3 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -1,15 +1,15 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction, untracked } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { RichTextField } from '../../../fields/RichTextField'; import { PastelSchemaPalette, SchemaHeaderField } from '../../../fields/SchemaHeaderField'; import { ScriptField } from '../../../fields/ScriptField'; -import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types'; +import { BoolCast, NumCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, setupMoveUpEvents, returnFalse, returnEmptyString } from '../../../Utils'; +import { emptyFunction, returnEmptyString, setupMoveUpEvents } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; import { DragManager } from '../../util/DragManager'; @@ -19,9 +19,9 @@ import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { EditableView } from '../EditableView'; -import './CollectionStackingView.scss'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; -import { Id } from '../../../fields/FieldSymbols'; +import './CollectionStackingView.scss'; +import { ObservableReactComponent } from '../ObservableReactComponent'; // So this is how we are storing a column interface CSVFieldColumnProps { @@ -49,7 +49,7 @@ interface CSVFieldColumnProps { } @observer -export class CollectionStackingViewFieldColumn extends React.Component { +export class CollectionStackingViewFieldColumn extends ObservableReactComponent { private dropDisposer?: DragManager.DragDropDisposer; private _disposers: { [name: string]: IReactionDisposer } = {}; private _headerRef: React.RefObject = React.createRef(); @@ -58,10 +58,8 @@ export class CollectionStackingViewFieldColumn extends React.Component (this._props = this.props)); - } - @action componentDidMount() { this._disposers.collapser = reaction( diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 79b15fdb1..0131af6f2 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -1,5 +1,7 @@ -import { action, computed, makeObservable, observable, override, runInAction, untracked } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; +import * as React from 'react'; import * as rp from 'request-promise'; +import { Utils, returnFalse } from '../../../Utils'; import CursorField from '../../../fields/CursorField'; import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../fields/Doc'; import { AclPrivate } from '../../../fields/DocSymbols'; @@ -10,21 +12,19 @@ import { BoolCast, Cast, ScriptCast, StrCast } from '../../../fields/Types'; import { WebField } from '../../../fields/URLField'; import { GetEffectiveAcl, TraceMobx } from '../../../fields/util'; import { GestureUtils } from '../../../pen-gestures/GestureUtils'; -import { returnFalse, Utils } from '../../../Utils'; import { DocServer } from '../../DocServer'; -import { Docs, DocumentOptions, DocUtils } from '../../documents/Documents'; -import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; import { Networking } from '../../Network'; +import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; +import { DocUtils, Docs, DocumentOptions } from '../../documents/Documents'; import { DragManager, dropActionType } from '../../util/DragManager'; import { ImageUtils } from '../../util/Import & Export/ImageUtils'; import { SelectionManager } from '../../util/SelectionManager'; import { SnappingManager } from '../../util/SnappingManager'; -import { undoBatch, UndoManager } from '../../util/UndoManager'; +import { UndoManager, undoBatch } from '../../util/UndoManager'; import { ViewBoxBaseComponent } from '../DocComponent'; -import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { LoadingBox } from '../nodes/LoadingBox'; +import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { CollectionView, CollectionViewProps } from './CollectionView'; -import * as React from 'react'; export interface SubCollectionViewProps extends CollectionViewProps { isAnyChildContentActive: () => boolean; @@ -35,16 +35,11 @@ export function CollectionSubView(moreProps?: X) { private dropDisposer?: DragManager.DragDropDisposer; private gestureDisposer?: GestureUtils.GestureEventDisposer; protected _mainCont?: HTMLDivElement; - @override _props: X & SubCollectionViewProps; constructor(props: any) { super(props); - this._props = props; makeObservable(this); } - componentDidUpdate() { - // untracked(() => (this._props = this.props)); - } @observable _focusFilters: Opt; // childFilters that are overridden when previewing a link to an anchor which has childFilters set on it @observable _focusRangeFilters: Opt; // childFiltersByRanges that are overridden when previewing a link to an anchor which has childFiltersByRanges set on it diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index e65f24702..c440a7e3f 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -1,5 +1,5 @@ import { toUpper } from 'lodash'; -import { action, computed, observable, runInAction } from 'mobx'; +import { action, computed, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { Doc, Opt, StrListCast } from '../../../fields/Doc'; import { List } from '../../../fields/List'; @@ -32,6 +32,11 @@ export class CollectionTimeView extends CollectionSubView() { @observable _viewDefDivClick: Opt; @observable _focusPivotField: Opt; + constructor(props: any) { + super(props); + makeObservable(this); + } + async componentDidMount() { this.props.setContentView?.(this); runInAction(() => { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 658d60523..7f8d42088 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -1,5 +1,6 @@ -import { action, computed, IReactionDisposer, makeObservable, observable, override, reaction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Doc, DocListCast, Opt, StrListCast } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; @@ -7,7 +8,7 @@ import { listSpec } from '../../../fields/Schema'; import { ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { copyProps, emptyFunction, returnAll, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnOne, returnTrue, returnZero } from '../../../Utils'; +import { emptyFunction, returnAll, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnOne, returnTrue, returnZero } from '../../../Utils'; import { DocUtils } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType } from '../../util/DragManager'; @@ -23,10 +24,9 @@ import { FieldViewProps } from '../nodes/FieldView'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { StyleProp } from '../StyleProvider'; import { CollectionFreeFormView } from './collectionFreeForm'; -import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView'; +import { CollectionSubView } from './CollectionSubView'; import './CollectionTreeView.scss'; import { TreeView } from './TreeView'; -import * as React from 'react'; const _global = (window /* browser */ || global) /* node */ as any; export type collectionTreeViewProps = { @@ -59,16 +59,10 @@ export class CollectionTreeView extends CollectionSubView = new Set(); // list of tree view items to monitor for height changes private observer: any; // observer for monitoring tree view items. - _prevProps: React.PropsWithChildren>; - @override _props: React.PropsWithChildren>; - constructor(props: React.PropsWithChildren>) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } get dataDoc() { return this._props.TemplateDataDocument || this.Document; diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index e84c12e02..f1ef52e60 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,14 +1,14 @@ -import { IReactionDisposer, makeObservable, observable, override, reaction, runInAction, untracked } from 'mobx'; +import { IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { returnEmptyString } from '../../../Utils'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { ObjectField } from '../../../fields/ObjectField'; import { ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { copyProps, returnEmptyString } from '../../../Utils'; -import { DocUtils } from '../../documents/Documents'; import { CollectionViewType } from '../../documents/DocumentTypes'; +import { DocUtils } from '../../documents/Documents'; import { dropActionType } from '../../util/DragManager'; import { ImageUtils } from '../../util/Import & Export/ImageUtils'; import { ContextMenu } from '../ContextMenu'; @@ -19,19 +19,19 @@ import { FieldView, FieldViewProps } from '../nodes/FieldView'; import { CollectionCarousel3DView } from './CollectionCarousel3DView'; import { CollectionCarouselView } from './CollectionCarouselView'; import { CollectionDockingView } from './CollectionDockingView'; -import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; -import { CollectionGridView } from './collectionGrid/CollectionGridView'; -import { CollectionLinearView } from './collectionLinear'; -import { CollectionMulticolumnView } from './collectionMulticolumn/CollectionMulticolumnView'; -import { CollectionMultirowView } from './collectionMulticolumn/CollectionMultirowView'; import { CollectionNoteTakingView } from './CollectionNoteTakingView'; import { CollectionPileView } from './CollectionPileView'; -import { CollectionSchemaView } from './collectionSchema/CollectionSchemaView'; import { CollectionStackingView } from './CollectionStackingView'; import { SubCollectionViewProps } from './CollectionSubView'; import { CollectionTimeView } from './CollectionTimeView'; import { CollectionTreeView } from './CollectionTreeView'; import './CollectionView.scss'; +import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; +import { CollectionGridView } from './collectionGrid/CollectionGridView'; +import { CollectionLinearView } from './collectionLinear'; +import { CollectionMulticolumnView } from './collectionMulticolumn/CollectionMulticolumnView'; +import { CollectionMultirowView } from './collectionMulticolumn/CollectionMultirowView'; +import { CollectionSchemaView } from './collectionSchema/CollectionSchemaView'; const path = require('path'); interface CollectionViewProps_ extends FieldViewProps { @@ -78,16 +78,10 @@ export class CollectionView extends ViewBoxAnnotatableComponent; - @override _props: React.PropsWithChildren; constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); - runInAction(() => (this._annotationKeySuffix = returnEmptyString)); - } - componentDidUpdate() { - copyProps(this); + this._annotationKeySuffix = returnEmptyString; } componentDidMount() { diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 8bc0f62dc..2eb13fd2f 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -2,40 +2,41 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Popup, Type } from 'browndash-components'; import { clamp } from 'lodash'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableSet, reaction, runInAction } from 'mobx'; +import { IReactionDisposer, ObservableSet, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; +import { DashColor, Utils, emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick } from '../../../Utils'; import { Doc, Opt } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { FieldId } from '../../../fields/RefField'; +import { ComputedField } from '../../../fields/ScriptField'; import { Cast, DocCast, NumCast, StrCast } from '../../../fields/Types'; -import { copyProps, DashColor, emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from '../../../Utils'; import { DocServer } from '../../DocServer'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; +import { Docs } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; import { SettingsManager } from '../../util/SettingsManager'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; -import { undoable, UndoManager } from '../../util/UndoManager'; +import { UndoManager, undoable } from '../../util/UndoManager'; import { DashboardView } from '../DashboardView'; -import { Colors } from '../global/globalEnums'; import { LightboxView } from '../LightboxView'; +import { ObservableReactComponent } from '../ObservableReactComponent'; +import { DefaultStyleProvider, StyleProp } from '../StyleProvider'; +import { Colors } from '../global/globalEnums'; import { DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere, OpenWhereMod } from '../nodes/DocumentView'; -import { DashFieldView } from '../nodes/formattedText/DashFieldView'; import { KeyValueBox } from '../nodes/KeyValueBox'; +import { DashFieldView } from '../nodes/formattedText/DashFieldView'; import { PinProps, PresBox, PresMovement } from '../nodes/trails'; -import { DefaultStyleProvider, StyleProp } from '../StyleProvider'; import { CollectionDockingView } from './CollectionDockingView'; -import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; import { CollectionView } from './CollectionView'; import './TabDocView.scss'; -import * as React from 'react'; -import { Docs } from '../../documents/Documents'; -import { ComputedField } from '../../../fields/ScriptField'; +import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; const _global = (window /* browser */ || global) /* node */ as any; interface TabDocViewProps { @@ -44,16 +45,13 @@ interface TabDocViewProps { glContainer: any; } @observer -export class TabDocView extends React.Component { +export class TabDocView extends ObservableReactComponent { static _allTabs = new ObservableSet(); _mainCont: HTMLDivElement | null = null; _tabReaction: IReactionDisposer | undefined; - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } @@ -341,9 +339,8 @@ export class TabDocView extends React.Component { // { fireImmediately: true }); runInAction(() => TabDocView._allTabs.add(this)); } - componentDidUpdate() { + componentDidUpdate(prevProps: Readonly) { this._view && DocumentManager.Instance.AddView(this._view); - copyProps(this); } componentWillUnmount() { @@ -521,14 +518,14 @@ interface TabMiniThumbProps { miniTop: () => number; miniLeft: () => number; } -@observer + class TabMiniThumb extends React.Component { render() { return

; } } @observer -export class TabMinimapView extends React.Component { +export class TabMinimapView extends ObservableReactComponent { static miniStyleProvider = (doc: Opt, props: Opt, property: string): any => { if (doc) { switch (property.split(':')[0]) { @@ -556,12 +553,6 @@ export class TabMinimapView extends React.Component { } }; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { - super(props); - this._props = props; - makeObservable(this); - } @computed get renderBounds() { const compView = this._props.tabView()?.ComponentView as CollectionFreeFormView; const bounds = compView?.freeformData?.(true)?.bounds; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 224d74882..52ecdfbec 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -1,8 +1,10 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { IconButton, Size } from 'browndash-components'; -import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; +import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { Utils, emptyFunction, lightOrDark, return18, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, simulateMouseClick } from '../../../Utils'; import { Doc, DocListCast, Field, FieldResult, Opt, StrListCast } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; @@ -12,9 +14,8 @@ import { listSpec } from '../../../fields/Schema'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { copyProps, emptyFunction, lightOrDark, return18, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, simulateMouseClick, Utils } from '../../../Utils'; -import { Docs, DocUtils } from '../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; +import { DocUtils, Docs } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType } from '../../util/DragManager'; import { LinkManager } from '../../util/LinkManager'; @@ -22,19 +23,19 @@ import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SettingsManager } from '../../util/SettingsManager'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; -import { undoable, undoBatch, UndoManager } from '../../util/UndoManager'; +import { UndoManager, undoBatch, undoable } from '../../util/UndoManager'; import { EditableView } from '../EditableView'; +import { ObservableReactComponent } from '../ObservableReactComponent'; +import { StyleProp } from '../StyleProvider'; import { DocumentView, DocumentViewInternal, DocumentViewProps, OpenWhere, StyleProviderFunc } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; +import { KeyValueBox } from '../nodes/KeyValueBox'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { RichTextMenu } from '../nodes/formattedText/RichTextMenu'; -import { KeyValueBox } from '../nodes/KeyValueBox'; -import { StyleProp } from '../StyleProvider'; import { CollectionTreeView, TreeViewType } from './CollectionTreeView'; import { CollectionView } from './CollectionView'; import { TreeSort } from './TreeSort'; import './TreeView.scss'; -import * as React from 'react'; const { default: { TREE_BULLET_WIDTH } } = require('../global/globalCssVariables.module.scss'); // prettier-ignore export interface TreeViewProps { @@ -86,7 +87,7 @@ const treeBulletWidth = function () { * treeView_ExpandedView : name of field whose contents are being displayed as the document's subtree */ @observer -export class TreeView extends React.Component { +export class TreeView extends ObservableReactComponent { static _editTitleOnLoad: Opt<{ id: string; parent: TreeView | CollectionTreeView | undefined }>; static _openTitleScript: Opt; static _openLevelScript: Opt; @@ -254,11 +255,8 @@ export class TreeView extends React.Component { static GetRunningChildren = new Map(); static ToggleChildrenRun = new Map void>(); - _prevProps: TreeViewProps; - @observable _props: TreeViewProps; constructor(props: TreeViewProps) { super(props); - this._props = this._prevProps = props; makeObservable(this); if (!TreeView._openLevelScript) { TreeView._openTitleScript = ScriptField.MakeScript('scriptContext.setEditTitle(documentView)', { scriptContext: 'any', documentView: 'any' }); @@ -297,8 +295,7 @@ export class TreeView extends React.Component { this._props.hierarchyIndex !== undefined && this._props.RemFromMap?.(this.Document, this._props.hierarchyIndex); } - componentDidUpdate() { - copyProps(this); + componentDidUpdate(prevProps: Readonly) { this._disposers.opening = reaction( () => this.treeViewOpen, open => !open && (this._renderCount = 20) diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx index dd7e12e41..0d5fcdaeb 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx @@ -1,8 +1,9 @@ -import { IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; +import { IReactionDisposer, makeObservable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { copyProps } from '../../../../Utils'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; import './CollectionFreeFormView.scss'; +import { copyProps } from '../../../../Utils'; /** * An Fsa Arc. The first array element is a test condition function that will be observed. @@ -47,14 +48,11 @@ export interface CollectionFreeFormInfoStateProps { } @observer -export class CollectionFreeFormInfoState extends React.Component { +export class CollectionFreeFormInfoState extends ObservableReactComponent { _disposers: IReactionDisposer[] = []; - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } @@ -62,7 +60,7 @@ export class CollectionFreeFormInfoState extends React.Component this.State[key]); + return Object.keys(this.State ?? []).map(key => this.State?.[key]); } clearState = () => this._disposers.map(disposer => disposer()); @@ -84,8 +82,8 @@ export class CollectionFreeFormInfoState extends React.Component) { + copyProps(this, prevProps); this.clearState(); this.initState(); } @@ -93,6 +91,6 @@ export class CollectionFreeFormInfoState extends React.Component{this.State[StateMessage]}
; + return
{this.State?.[StateMessage]}
; } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx index f0a052c1d..4d3752c02 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx @@ -1,21 +1,13 @@ -import { IReactionDisposer, computed, observable, reaction, action, runInAction, makeObservable } from 'mobx'; +import { IReactionDisposer, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; -import { Doc } from '../../../../fields/Doc'; -import { ScriptField } from '../../../../fields/ScriptField'; -import { PresBox } from '../../nodes/trails/PresBox'; -import './CollectionFreeFormView.scss'; import * as React from 'react'; -import { CollectionFreeFormView } from './CollectionFreeFormView'; -import { NumCast } from '../../../../fields/Types'; +import { Doc } from '../../../../fields/Doc'; import { LinkManager } from '../../../util/LinkManager'; -import { InkTool } from '../../../../fields/InkField'; -import { LinkDocPreview } from '../../nodes/LinkDocPreview'; -import { DocumentLinksButton, DocButtonState } from '../../nodes/DocumentLinksButton'; -import { DocumentManager } from '../../../util/DocumentManager'; -import { CollectionFreeFormInfoState, infoState, StateMessage, infoArc, StateEntryFunc, InfoState } from './CollectionFreeFormInfoState'; -import { string32 } from 'pdfjs-dist/types/src/shared/util'; -import { any } from 'bluebird'; -import { copyProps } from '../../../../Utils'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; +import { DocButtonState } from '../../nodes/DocumentLinksButton'; +import { CollectionFreeFormInfoState, InfoState, StateEntryFunc, infoState } from './CollectionFreeFormInfoState'; +import { CollectionFreeFormView } from './CollectionFreeFormView'; +import './CollectionFreeFormView.scss'; export interface CollectionFreeFormInfoUIProps { Document: Doc; @@ -23,7 +15,7 @@ export interface CollectionFreeFormInfoUIProps { } @observer -export class CollectionFreeFormInfoUI extends React.Component { +export class CollectionFreeFormInfoUI extends ObservableReactComponent { private _disposers: { [name: string]: IReactionDisposer } = {}; @observable _currState: infoState | undefined = undefined; @@ -33,17 +25,12 @@ export class CollectionFreeFormInfoUI extends React.Component; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + + constructor(props: any) { super(props); - this._props = this._prevProps = this.props; makeObservable(this); this.currState = this.setupStates(); } - componentDidUpdate() { - copyProps(this); - } setCurrState = (state: infoState) => { if (state) { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index be3d2439c..6337c8d34 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -1,19 +1,20 @@ import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Doc, Field } from '../../../../fields/Doc'; import { Brushed, DocCss } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; import { Cast, NumCast, StrCast } from '../../../../fields/Types'; -import { copyProps, emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; +import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; import { LinkManager } from '../../../util/LinkManager'; import { SelectionManager } from '../../../util/SelectionManager'; import { SettingsManager } from '../../../util/SettingsManager'; import { SnappingManager } from '../../../util/SnappingManager'; import { Colors } from '../../global/globalEnums'; import { DocumentView } from '../../nodes/DocumentView'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; import './CollectionFreeFormLinkView.scss'; -import * as React from 'react'; export interface CollectionFreeFormLinkViewProps { A: DocumentView; @@ -24,22 +25,16 @@ export interface CollectionFreeFormLinkViewProps { // props.screentolocatransform @observer -export class CollectionFreeFormLinkView extends React.Component { +export class CollectionFreeFormLinkView extends ObservableReactComponent { @observable _opacity: number = 0; @observable _start = 0; _anchorDisposer: IReactionDisposer | undefined; _timeout: NodeJS.Timeout | undefined; - _prevProps: CollectionFreeFormLinkViewProps; - @observable _props: CollectionFreeFormLinkViewProps; - constructor(props: CollectionFreeFormLinkViewProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } componentWillUnmount() { this._anchorDisposer?.(); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index aa40fb809..1f4688729 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,6 +1,6 @@ import { Bezier } from 'bezier-js'; import { Colors } from 'browndash-components'; -import { action, computed, IReactionDisposer, makeObservable, observable, override, reaction, runInAction, toJS } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction, toJS } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; @@ -16,7 +16,7 @@ import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../ import { ImageField } from '../../../../fields/URLField'; import { TraceMobx } from '../../../../fields/util'; import { GestureUtils } from '../../../../pen-gestures/GestureUtils'; -import { aggregateBounds, copyProps, DashColor, emptyFunction, intersectRect, lightOrDark, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, Utils } from '../../../../Utils'; +import { aggregateBounds, DashColor, emptyFunction, intersectRect, lightOrDark, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, Utils } from '../../../../Utils'; import { CognitiveServices } from '../../../cognitive_services/CognitiveServices'; import { Docs, DocUtils } from '../../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; @@ -43,7 +43,7 @@ import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { PinProps, PresBox } from '../../nodes/trails/PresBox'; import { CreateImage } from '../../nodes/WebBoxRenderer'; import { StyleProp } from '../../StyleProvider'; -import { CollectionSubView, SubCollectionViewProps } from '../CollectionSubView'; +import { CollectionSubView } from '../CollectionSubView'; import { TreeViewType } from '../CollectionTreeView'; import { CollectionFreeFormBackgroundGrid } from './CollectionFreeFormBackgroundGrid'; import { CollectionFreeFormInfoUI } from './CollectionFreeFormInfoUI'; @@ -72,17 +72,10 @@ export class CollectionFreeFormView extends CollectionSubView>; - @override _props: React.PropsWithChildren>; constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - @observable public static ShowPresPaths = false; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx index 825bd5f19..7aa68b0d9 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx @@ -20,7 +20,6 @@ export class MarqueeOptionsMenu extends AntimodeMenu { public isShown = () => this._opacity > 0; constructor(props: Readonly<{}>) { super(props); - MarqueeOptionsMenu.Instance = this; } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 10beb120a..2c65726b2 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -1,5 +1,7 @@ import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { Utils, intersectRect, lightOrDark, returnFalse } from '../../../../Utils'; import { Doc, Opt } from '../../../../fields/Doc'; import { AclAdmin, AclAugment, AclEdit, DocData } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; @@ -7,25 +9,24 @@ import { InkData, InkField, InkTool } from '../../../../fields/InkField'; import { List } from '../../../../fields/List'; import { RichTextField } from '../../../../fields/RichTextField'; import { Cast, FieldValue, NumCast, StrCast } from '../../../../fields/Types'; -import { ImageField, nullAudio } from '../../../../fields/URLField'; +import { ImageField } from '../../../../fields/URLField'; import { GetEffectiveAcl } from '../../../../fields/util'; -import { intersectRect, lightOrDark, returnFalse, Utils } from '../../../../Utils'; import { CognitiveServices } from '../../../cognitive_services/CognitiveServices'; -import { Docs, DocumentOptions, DocUtils } from '../../../documents/Documents'; import { DocumentType } from '../../../documents/DocumentTypes'; +import { DocUtils, Docs, DocumentOptions } from '../../../documents/Documents'; import { SelectionManager } from '../../../util/SelectionManager'; +import { freeformScrollMode } from '../../../util/SettingsManager'; import { Transform } from '../../../util/Transform'; -import { undoBatch, UndoManager } from '../../../util/UndoManager'; +import { UndoManager, undoBatch } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; +import { PreviewCursor } from '../../PreviewCursor'; import { DocumentView, OpenWhere } from '../../nodes/DocumentView'; -import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { pasteImageBitmap } from '../../nodes/WebBoxRenderer'; -import { PreviewCursor } from '../../PreviewCursor'; +import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { SubCollectionViewProps } from '../CollectionSubView'; import { MarqueeOptionsMenu } from './MarqueeOptionsMenu'; import './MarqueeView.scss'; -import * as React from 'react'; -import { freeformScrollMode } from '../../../util/SettingsManager'; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -51,16 +52,14 @@ export interface MarqueeViewBounds { } @observer -export class MarqueeView extends React.Component { +export class MarqueeView extends ObservableReactComponent { public static CurViewBounds(pinDoc: Doc, panelWidth: number, panelHeight: number) { const ps = NumCast(pinDoc._freeform_scale, 1); return { left: NumCast(pinDoc._freeform_panX) - panelWidth / 2 / ps, top: NumCast(pinDoc._freeform_panY) - panelHeight / 2 / ps, width: panelWidth / ps, height: panelHeight / ps }; } - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = props; makeObservable(this); } diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index 697a11ccc..1e19964d7 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -1,4 +1,4 @@ -import { action, computed, Lambda, observable, reaction } from 'mobx'; +import { action, computed, Lambda, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, Opt } from '../../../../fields/Doc'; @@ -27,6 +27,11 @@ export class CollectionGridView extends CollectionSubView() { @observable private _scroll: number = 0; // required to make sure the decorations box container updates on scroll private dropLocation: object = {}; // sets the drop location for external drops + constructor(props: any) { + super(props); + makeObservable(this); + } + onChildClickHandler = () => ScriptCast(this.Document.onChildClick); @computed get numCols() { diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx index a9782f699..f1fb68003 100644 --- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx +++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx @@ -1,26 +1,26 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; import { Toggle, ToggleType, Type } from 'browndash-components'; -import { action, IReactionDisposer, makeObservable, observable, override, reaction, runInAction, untracked } from 'mobx'; +import { IReactionDisposer, action, makeObservable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { Utils, emptyFunction, returnEmptyDoclist, returnTrue } from '../../../../Utils'; import { Doc, Opt } from '../../../../fields/Doc'; import { Height, Width } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; -import { copyProps, emptyFunction, returnEmptyDoclist, returnTrue, Utils } from '../../../../Utils'; import { CollectionViewType } from '../../../documents/DocumentTypes'; import { BranchingTrailManager } from '../../../util/BranchingTrailManager'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager, dropActionType } from '../../../util/DragManager'; import { SettingsManager } from '../../../util/SettingsManager'; import { Transform } from '../../../util/Transform'; +import { UndoStack } from '../../UndoStack'; import { DocumentLinksButton } from '../../nodes/DocumentLinksButton'; import { DocumentView } from '../../nodes/DocumentView'; import { LinkDescriptionPopup } from '../../nodes/LinkDescriptionPopup'; -import { UndoStack } from '../../UndoStack'; import { CollectionStackedTimeline } from '../CollectionStackedTimeline'; -import { CollectionSubView, SubCollectionViewProps } from '../CollectionSubView'; +import { CollectionSubView } from '../CollectionSubView'; import './CollectionLinearView.scss'; /** @@ -33,24 +33,15 @@ import './CollectionLinearView.scss'; */ @observer export class CollectionLinearView extends CollectionSubView() { - @observable public addMenuToggle = React.createRef(); - @observable private _selectedIndex = -1; private _dropDisposer?: DragManager.DragDropDisposer; private _widthDisposer?: IReactionDisposer; private _selectedDisposer?: IReactionDisposer; - _prevProps: SubCollectionViewProps; - @override _props: SubCollectionViewProps; - constructor(props: SubCollectionViewProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - componentWillUnmount() { this._dropDisposer?.(); this._widthDisposer?.(); diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index 037786abf..b951a4b17 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -1,7 +1,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; import { Button } from 'browndash-components'; -import { action, computed } from 'mobx'; +import { action, computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast } from '../../../../fields/Doc'; @@ -37,6 +37,11 @@ const resizerWidth = 8; @observer export class CollectionMulticolumnView extends CollectionSubView() { + constructor(props: any) { + super(props); + makeObservable(this); + } + /** * @returns the list of layout documents whose width unit is * *, denoting that it will be displayed with a ratio, not fixed pixel, value @@ -238,8 +243,8 @@ export class CollectionMulticolumnView extends CollectionSubView() { return this.props.isContentActive?.() === false || childDocsActive === false ? false // : this.props.isDocumentActive?.() && childDocsActive - ? true - : undefined; + ? true + : undefined; }; getDisplayDoc = (childLayout: Doc) => { const width = () => this.lookupPixels(childLayout); diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index bbf3481dd..f1c6c6e1e 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -1,4 +1,4 @@ -import { action, computed } from 'mobx'; +import { action, computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast } from '../../../../fields/Doc'; @@ -33,6 +33,11 @@ const resizerHeight = 8; @observer export class CollectionMultirowView extends CollectionSubView() { + constructor(props: any) { + super(props); + makeObservable(this); + } + /** * @returns the list of layout documents whose width unit is * *, denoting that it will be displayed with a ratio, not fixed pixel, value @@ -234,8 +239,8 @@ export class CollectionMultirowView extends CollectionSubView() { return this.props.isContentActive?.() === false || childDocsActive === false ? false // : this.props.isDocumentActive?.() && childDocsActive - ? true - : undefined; + ? true + : undefined; }; getDisplayDoc = (layout: Doc) => { const height = () => this.lookupPixels(layout); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 276415d56..2546f5b02 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -1,13 +1,13 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, makeObservable, observable, ObservableMap, observe, override } from 'mobx'; +import { action, computed, makeObservable, observable, ObservableMap, observe } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Doc, DocListCast, Field, NumListCast, Opt, StrListCast } from '../../../../fields/Doc'; import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; import { listSpec } from '../../../../fields/Schema'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types'; -import { copyProps, emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils'; import { Docs, DocumentOptions, DocUtils, FInfo } from '../../../documents/Documents'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from '../../../util/DragManager'; @@ -18,8 +18,9 @@ import { EditableView } from '../../EditableView'; import { Colors } from '../../global/globalEnums'; import { DocFocusOptions, DocumentView, DocumentViewProps } from '../../nodes/DocumentView'; import { KeyValueBox } from '../../nodes/KeyValueBox'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; import { DefaultStyleProvider, StyleProp } from '../../StyleProvider'; -import { CollectionSubView, SubCollectionViewProps } from '../CollectionSubView'; +import { CollectionSubView } from '../CollectionSubView'; import './CollectionSchemaView.scss'; import { SchemaColumnHeader } from './SchemaColumnHeader'; import { SchemaRowBox } from './SchemaRowBox'; @@ -57,6 +58,11 @@ export class CollectionSchemaView extends CollectionSubView() { private _tableContentRef: HTMLDivElement | null = null; private _menuTarget = React.createRef(); + constructor(props: any) { + super(props); + makeObservable(this); + } + static _rowHeight: number = 50; static _rowSingleLineHeight: number = 32; public static _minColWidth: number = 25; @@ -79,18 +85,6 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _filterSearchValue: string = ''; @observable _selectedCell: [Doc, number] | undefined = undefined; - _prevProps: SubCollectionViewProps; - @override _props: SubCollectionViewProps; - constructor(props: SubCollectionViewProps) { - super(props); - this._props = this._prevProps = props; - makeObservable(this); - } - - componentDidUpdate() { - copyProps(this); - } - // target HTMLelement portal for showing a popup menu to edit cell values. public get MenuTarget() { return this._menuTarget.current; @@ -959,17 +953,12 @@ interface CollectionSchemaViewDocProps { } @observer -class CollectionSchemaViewDoc extends React.Component { - _prevProps: CollectionSchemaViewDocProps; - @observable _props; - constructor(props: CollectionSchemaViewDocProps) { +class CollectionSchemaViewDoc extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } + tableWidthFunc = () => this._props.schema.tableWidth; screenToLocalXf = () => this._props.schema._props.ScreenToLocalTransform().translate(0, -this._props.rowHeight() - this._props.index * this._props.rowHeight()); noOpacityStyleProvider = (doc: Opt, props: Opt, property: string) => { diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 737d7e0f4..5a3be826b 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -1,13 +1,13 @@ -import * as React from 'react'; import { IconButton, Size } from 'browndash-components'; -import { computed, makeObservable, override } from 'mobx'; +import { computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; +import * as React from 'react'; import { CgClose } from 'react-icons/cg'; import { FaExternalLinkAlt } from 'react-icons/fa'; +import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils'; import { Doc } from '../../../../fields/Doc'; import { BoolCast } from '../../../../fields/Types'; -import { copyProps, emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils'; import { DragManager } from '../../../util/DragManager'; import { SnappingManager } from '../../../util/SnappingManager'; import { Transform } from '../../../util/Transform'; @@ -30,16 +30,10 @@ export class SchemaRowBox extends ViewBoxBaseComponent this._ref?.getBoundingClientRect(); diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index bcfe2c232..85269028b 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -1,27 +1,28 @@ -import * as React from 'react'; -import Select, { MenuPlacement } from 'react-select'; import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import { extname } from 'path'; +import * as React from 'react'; import DatePicker from 'react-datepicker'; +import Select from 'react-select'; +import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero } from '../../../../Utils'; import { DateField } from '../../../../fields/DateField'; import { Doc, DocListCast, Field } from '../../../../fields/Doc'; import { RichTextField } from '../../../../fields/RichTextField'; import { BoolCast, Cast, DateCast, DocCast, FieldValue, StrCast } from '../../../../fields/Types'; import { ImageField } from '../../../../fields/URLField'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero, Utils } from '../../../../Utils'; import { FInfo } from '../../../documents/Documents'; import { DocFocusOrOpen } from '../../../util/DocumentManager'; import { Transform } from '../../../util/Transform'; -import { undoable, undoBatch } from '../../../util/UndoManager'; +import { undoBatch, undoable } from '../../../util/UndoManager'; import { EditableView } from '../../EditableView'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; +import { DefaultStyleProvider } from '../../StyleProvider'; import { Colors } from '../../global/globalEnums'; import { OpenWhere } from '../../nodes/DocumentView'; -import { FieldView, FieldViewProps } from '../../nodes/FieldView'; -import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; +import { FieldViewProps } from '../../nodes/FieldView'; import { KeyValueBox } from '../../nodes/KeyValueBox'; -import { DefaultStyleProvider } from '../../StyleProvider'; -import { CollectionSchemaView, ColumnType, FInfotoColType } from './CollectionSchemaView'; +import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; +import { ColumnType, FInfotoColType } from './CollectionSchemaView'; import './CollectionSchemaView.scss'; export interface SchemaTableCellProps { @@ -47,7 +48,12 @@ export interface SchemaTableCellProps { } @observer -export class SchemaTableCell extends React.Component { +export class SchemaTableCell extends ObservableReactComponent { + constructor(props: any) { + super(props); + makeObservable(this); + } + static addFieldDoc = (doc: Doc, where: OpenWhere) => { DocFocusOrOpen(doc); return true; @@ -95,12 +101,6 @@ export class SchemaTableCell extends React.Component { return { color, textDecoration, fieldProps, cursor, pointerEvents }; } - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { - super(props); - this._props = props; - } - @computed get selected() { const selected: [Doc, number] | undefined = this._props.selectedCell(); return this._props.isRowActive() && selected?.[0] === this._props.Document && selected[1] === this._props.col; @@ -182,16 +182,14 @@ export class SchemaTableCell extends React.Component { // mj: most of this is adapted from old schema code so I'm not sure what it does tbh @observer -export class SchemaImageCell extends React.Component { - @observable _previewRef: HTMLImageElement | undefined = undefined; - - _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { +export class SchemaImageCell extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = props; makeObservable(this); } + @observable _previewRef: HTMLImageElement | undefined = undefined; + choosePath(url: URL) { if (url.protocol === 'data') return url.href; // if the url ises the data protocol, just return the href if (url.href.indexOf(window.location.origin) === -1) return Utils.CorsProxy(url.href); // otherwise, put it through the cors proxy erver @@ -251,16 +249,13 @@ export class SchemaImageCell extends React.Component { } @observer -export class SchemaDateCell extends React.Component { - @observable _pickingDate: boolean = false; - - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { +export class SchemaDateCell extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = props; makeObservable(this); } + @observable _pickingDate: boolean = false; @computed get date(): DateField { // if the cell is a date field, cast then contents to a date. Otherrwwise, make the contents undefined. return DateCast(this._props.Document[this._props.fieldKey]); @@ -282,11 +277,9 @@ export class SchemaDateCell extends React.Component { } } @observer -export class SchemaRTFCell extends React.Component { - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { +export class SchemaRTFCell extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = props; makeObservable(this); } @@ -306,11 +299,9 @@ export class SchemaRTFCell extends React.Component { } } @observer -export class SchemaBoolCell extends React.Component { - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { +export class SchemaBoolCell extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = props; makeObservable(this); } @@ -352,11 +343,9 @@ export class SchemaBoolCell extends React.Component { } } @observer -export class SchemaEnumerationCell extends React.Component { - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { +export class SchemaEnumerationCell extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = props; makeObservable(this); } diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index af22f41e1..b7376e901 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -1,13 +1,14 @@ import { action, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Doc } from '../../../fields/Doc'; import { LinkManager } from '../../util/LinkManager'; +import { SettingsManager } from '../../util/SettingsManager'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import { DocumentView } from '../nodes/DocumentView'; import { LinkInfo } from '../nodes/LinkDocPreview'; import './LinkMenu.scss'; import { LinkMenuGroup } from './LinkMenuGroup'; -import * as React from 'react'; -import { SettingsManager } from '../../util/SettingsManager'; interface Props { docView: DocumentView; @@ -20,10 +21,10 @@ interface Props { * the outermost component for the link menu of a node that contains a list of its linked nodes */ @observer -export class LinkMenu extends React.Component { +export class LinkMenu extends ObservableReactComponent { _editorRef = React.createRef(); @observable _linkMenuRef = React.createRef(); - constructor(props: Props) { + constructor(props: any) { super(props); makeObservable(this); } diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index d77525e04..06073b52c 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -1,23 +1,24 @@ -import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; -import { action, computed, observable, makeObservable } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils'; import { Doc } from '../../../fields/Doc'; import { Cast, DocCast, StrCast } from '../../../fields/Types'; import { WebField } from '../../../fields/URLField'; -import { emptyFunction, returnFalse, setupMoveUpEvents, copyProps } from '../../../Utils'; -import { DocumentType } from '../../documents/DocumentTypes'; import { DragManager } from '../../util/DragManager'; import { LinkFollower } from '../../util/LinkFollower'; import { LinkManager } from '../../util/LinkManager'; import { SelectionManager } from '../../util/SelectionManager'; import { SettingsManager } from '../../util/SettingsManager'; -import { undoBatch } from '../../util/UndoManager'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import { DocumentView, DocumentViewInternal, OpenWhere } from '../nodes/DocumentView'; -import { LinkDocPreview, LinkInfo } from '../nodes/LinkDocPreview'; +import { LinkInfo } from '../nodes/LinkDocPreview'; import './LinkMenuItem.scss'; -import * as React from 'react'; +import { undoBatch } from '../../util/UndoManager'; +import { IconProp } from '@fortawesome/fontawesome-svg-core'; +import { DocumentType } from '../../documents/DocumentTypes'; interface LinkMenuItemProps { groupType: string; @@ -50,20 +51,13 @@ export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: Docume } @observer -export class LinkMenuItem extends React.Component { +export class LinkMenuItem extends ObservableReactComponent { private _drag = React.createRef(); _editRef = React.createRef(); - - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } @observable private _showMore: boolean = false; @action toggleShowMore(e: React.PointerEvent) { diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 0c671f7e3..567cf193e 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -1,14 +1,14 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; -import { action, computed, IReactionDisposer, makeObservable, observable, override, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { DateField } from '../../../fields/DateField'; import { Doc } from '../../../fields/Doc'; import { ComputedField } from '../../../fields/ScriptField'; import { Cast, DateCast, NumCast } from '../../../fields/Types'; import { AudioField, nullAudio } from '../../../fields/URLField'; -import { copyProps, emptyFunction, formatTime, returnFalse, setupMoveUpEvents } from '../../../Utils'; +import { emptyFunction, formatTime, returnFalse, setupMoveUpEvents } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { Networking } from '../../Network'; import { DragManager } from '../../util/DragManager'; @@ -17,7 +17,7 @@ import { undoBatch } from '../../util/UndoManager'; import { CollectionStackedTimeline, TrimScope } from '../collections/CollectionStackedTimeline'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; -import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent'; +import { ViewBoxAnnotatableComponent } from '../DocComponent'; import './AudioBox.scss'; import { DocFocusOptions } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; @@ -54,19 +54,13 @@ export class AudioBox extends ViewBoxAnnotatableComponent() { return FieldView.LayoutString(AudioBox, fieldKey); } - _prevProps: React.PropsWithChildren; - @override _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + public static Enabled = false; + + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - public static Enabled = false; - static topControlsHeight = 30; // height of upper controls above timeline static bottomControlsHeight = 20; // height of lower controls below timeline diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 8e7a6914f..c97c879af 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -1,21 +1,21 @@ -import { action, computed, observable, makeObservable, reaction, runInAction, override } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { OmitKeys, numberRange } from '../../../Utils'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; import { ComputedField } from '../../../fields/ScriptField'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { copyProps, numberRange, OmitKeys } from '../../../Utils'; import { DocumentManager } from '../../util/DocumentManager'; +import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SelectionManager } from '../../util/SelectionManager'; -import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import { DocComponent } from '../DocComponent'; import { StyleProp } from '../StyleProvider'; +import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import './CollectionFreeFormDocumentView.scss'; import { DocumentView, DocumentViewProps, OpenWhere } from './DocumentView'; -import * as React from 'react'; -import { ScriptingGlobals } from '../../util/ScriptingGlobals'; export interface CollectionFreeFormDocumentViewWrapperProps extends DocumentViewProps { x: number; @@ -37,11 +37,8 @@ export interface CollectionFreeFormDocumentViewWrapperProps extends DocumentView } @observer export class CollectionFreeFormDocumentViewWrapper extends DocComponent() implements CollectionFreeFormDocumentViewProps { - _prevProps: React.PropsWithChildren; - @override _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } @observable X = this.props.x; @@ -79,7 +76,7 @@ export class CollectionFreeFormDocumentViewWrapper extends DocComponent this.Highlight; // prettier-ignore w_Width = () => this.Width; // prettier-ignore w_Height = () => this.Height; // prettier-ignore - w_AutoDim = () => this.AutoDim; + w_AutoDim = () => this.AutoDim; // prettier-ignore w_Transition = () => this.Transition; // prettier-ignore w_DataTransition = () => this.DataTransition; // prettier-ignore @@ -87,7 +84,6 @@ export class CollectionFreeFormDocumentViewWrapper extends DocComponent this._props.autoDim ? this._props.PanelHeight?.() : this.Height; // prettier-ignore componentDidUpdate() { - copyProps(this); this.WrapperKeys.forEach(action(keys => ((this as any)[keys.upper] = (this.props as any)[keys.lower]))); } render() { @@ -124,6 +120,10 @@ export interface CollectionFreeFormDocumentViewProps { @observer export class CollectionFreeFormDocumentView extends DocComponent() { + constructor(props: any) { + super(props); + makeObservable(this); + } get displayName() { // this makes mobx trace() statements more descriptive return 'CollectionFreeFormDocumentView(' + this.Document.title + ')'; } // prettier-ignore @@ -143,13 +143,6 @@ export class CollectionFreeFormDocumentView extends DocComponent (Doc.LayoutFieldKey(doc) ? [Doc.LayoutFieldKey(doc)] : []); // fields that are configured to be animatable using animation frames - _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { - super(props); - this._props = Object.assign({}, props); - makeObservable(this); - } - get CollectionFreeFormView() { return this._props.CollectionFreeFormView; } diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index 62523ba00..de382fca5 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -1,10 +1,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, makeObservable, observable, override } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { emptyFunction, returnFalse, returnNone, returnZero, setupMoveUpEvents } from '../../../Utils'; import { Doc, Opt } from '../../../fields/Doc'; import { DocCast, NumCast, StrCast } from '../../../fields/Types'; -import { copyProps, emptyFunction, returnFalse, returnNone, returnZero, setupMoveUpEvents } from '../../../Utils'; -import { Docs, DocUtils } from '../../documents/Documents'; +import { DocUtils, Docs } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent'; @@ -13,7 +14,6 @@ import './ComparisonBox.scss'; import { DocumentView, DocumentViewProps } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import { PinProps, PresBox } from './trails'; -import * as React from 'react'; @observer export class ComparisonBox extends ViewBoxAnnotatableComponent() { @@ -21,20 +21,12 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent { } @observer -export class DocumentContentsView extends React.Component< +export class DocumentContentsView extends ObservableReactComponent< DocumentViewProps & FieldViewProps & { setHeight?: (height: number) => void; layout_fieldKey: string; } > { - @observable _props!: DocumentViewProps & - FieldViewProps & { - setHeight?: (height: number) => void; - layout_fieldKey: string; - }; constructor(props: any) { super(props); - this._props = props; makeObservable(this); } - componentDidUpdate(prevProps: Readonly void) | undefined; layout_fieldKey: string }>, prevState: Readonly<{}>, snapshot?: any): void { - // untracked(() => (this._props = this.props)); - // Object.keys(prevProps).forEach(pkey => (prevProps as any)[pkey] !== (this._props as any)[pkey] && console.log(pkey + ' ' + (prevProps as any)[pkey] + ' ' + (this._props as any)[pkey])); - } - @computed get layout(): string { TraceMobx(); if (this._props.LayoutTemplateString) return this._props.LayoutTemplateString; diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx index 9ec4d8c13..dfd610581 100644 --- a/src/client/views/nodes/DocumentIcon.tsx +++ b/src/client/views/nodes/DocumentIcon.tsx @@ -1,34 +1,28 @@ +import { Tooltip } from '@mui/material'; +import { action, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { DocumentView } from './DocumentView'; -import { DocumentManager } from '../../util/DocumentManager'; -import { Transformer, ts } from '../../util/Scripting'; +import { factory } from 'typescript'; import { Field } from '../../../fields/Doc'; -import { Tooltip } from '@mui/material'; -import { action, makeObservable, observable } from 'mobx'; import { Id } from '../../../fields/FieldSymbols'; -import { factory } from 'typescript'; -import { LightboxView } from '../LightboxView'; +import { DocumentManager } from '../../util/DocumentManager'; +import { Transformer, ts } from '../../util/Scripting'; import { SettingsManager } from '../../util/SettingsManager'; -import { copyProps } from '../../../Utils'; +import { LightboxView } from '../LightboxView'; +import { ObservableReactComponent } from '../ObservableReactComponent'; +import { DocumentView } from './DocumentView'; interface DocumentIconProps { view: DocumentView; index: number; } @observer -export class DocumentIcon extends React.Component { +export class DocumentIcon extends ObservableReactComponent { @observable _hovered = false; - _prevProps: DocumentIconProps; - @observable _props: DocumentIconProps; - constructor(props: DocumentIconProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } static get DocViews() { return LightboxView.LightboxDoc ? DocumentManager.Instance.DocumentViews.filter(v => LightboxView.IsLightboxDocView(v._props.docViewPath())) : DocumentManager.Instance.DocumentViews; diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 19b43fd52..165057d21 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -2,20 +2,21 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; import { action, computed, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { StopEvent, emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils'; import { Doc } from '../../../fields/Doc'; import { StrCast } from '../../../fields/Types'; -import { copyProps, emptyFunction, returnFalse, setupMoveUpEvents, StopEvent } from '../../../Utils'; import { DocUtils } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; import { Hypothesis } from '../../util/HypothesisUtils'; import { LinkManager } from '../../util/LinkManager'; -import { undoBatch, UndoManager } from '../../util/UndoManager'; +import { UndoManager, undoBatch } from '../../util/UndoManager'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import './DocumentLinksButton.scss'; import { DocumentView } from './DocumentView'; import { LinkDescriptionPopup } from './LinkDescriptionPopup'; import { TaskCompletionBox } from './TaskCompletedBox'; import { PinProps } from './trails'; -import * as React from 'react'; interface DocumentLinksButtonProps { View: DocumentView; @@ -44,26 +45,18 @@ export class DocButtonState { } } @observer -export class DocumentLinksButton extends React.Component { +export class DocumentLinksButton extends ObservableReactComponent { private _linkButton = React.createRef(); public static get StartLink() { return DocButtonState.Instance.StartLink; } // prettier-ignore public static set StartLink(value) { runInAction(() => (DocButtonState.Instance.StartLink = value)); } // prettier-ignore @observable public static StartLinkView: DocumentView | undefined = undefined; @observable public static AnnotationId: string | undefined = undefined; @observable public static AnnotationUri: string | undefined = undefined; - - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - @undoBatch onLinkButtonMoved = (e: PointerEvent) => { if (this._props.InMenu && this._props.StartLink) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 08ee708f7..343f770d5 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,9 +1,11 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { Dropdown, DropdownType, Type } from 'browndash-components'; -import { action, computed, IReactionDisposer, makeObservable, observable, override, reaction, runInAction, untracked } from 'mobx'; +import { IReactionDisposer, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; // import { Bounce, Fade, Flip, LightSpeed, Roll, Rotate, Zoom } from 'react-reveal'; +import * as React from 'react'; +import { Utils, emptyFunction, isTargetChildOf as isParentOf, lightOrDark, returnEmptyString, returnFalse, returnTrue, returnVal, simulateMouseClick } from '../../../Utils'; import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../fields/Doc'; import { AclPrivate, Animation, AudioPlay, DocViews } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; @@ -15,12 +17,11 @@ import { ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, DocCast, ImageCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { AudioField } from '../../../fields/URLField'; import { GetEffectiveAcl, TraceMobx } from '../../../fields/util'; -import { copyProps, emptyFunction, isTargetChildOf as isParentOf, lightOrDark, returnEmptyString, returnFalse, returnTrue, returnVal, simulateMouseClick, Utils } from '../../../Utils'; -import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { DocServer } from '../../DocServer'; -import { DocOptions, Docs, DocUtils, FInfo } from '../../documents/Documents'; -import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; import { Networking } from '../../Network'; +import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; +import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; +import { DocOptions, DocUtils, Docs, FInfo } from '../../documents/Documents'; import { DictationManager } from '../../util/DictationManager'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType } from '../../util/DragManager'; @@ -32,13 +33,14 @@ import { SettingsManager } from '../../util/SettingsManager'; import { SharingManager } from '../../util/SharingManager'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; -import { undoBatch, UndoManager } from '../../util/UndoManager'; +import { UndoManager, undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { DocComponent } from '../DocComponent'; import { EditableView } from '../EditableView'; import { GestureOverlay } from '../GestureOverlay'; import { LightboxView } from '../LightboxView'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import { StyleProp } from '../StyleProvider'; import { UndoStack } from '../UndoStack'; import { CollectionFreeFormDocumentView } from './CollectionFreeFormDocumentView'; @@ -46,12 +48,11 @@ import { DocumentContentsView, ObserverJsxParser } from './DocumentContentsView' import { DocumentLinksButton } from './DocumentLinksButton'; import './DocumentView.scss'; import { FieldViewProps } from './FieldView'; -import { FormattedTextBox } from './formattedText/FormattedTextBox'; import { KeyValueBox } from './KeyValueBox'; import { LinkAnchorBox } from './LinkAnchorBox'; +import { FormattedTextBox } from './formattedText/FormattedTextBox'; import { PresEffect, PresEffectDirection } from './trails'; import { PinProps, PresBox } from './trails/PresBox'; -import * as React from 'react'; const { Howl } = require('howler'); interface Window { @@ -253,20 +254,11 @@ export class DocumentViewInternal extends DocComponent(); private _titleRef = React.createRef(); private _dropDisposer?: DragManager.DragDropDisposer; - - @override _props: DocumentViewInternalProps; - _prevProps: DocumentViewInternalProps; - - constructor(props: DocumentViewInternalProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - // untracked(() => (this._props = this._props)); - } - @observable _componentView: Opt; // needs to be accessed from DocumentView wrapper class @observable _animateScaleTime: Opt; // milliseconds for animating between views. defaults to 300 if not uset @observable _animateScalingTo = 0; @@ -1329,19 +1321,13 @@ export class DocumentViewInternal extends DocComponent { +export class DocumentView extends ObservableReactComponent { public static ROOT_DIV = 'documentView-effectsWrapper'; - @observable _props: DocumentViewProps; - _prevProps: DocumentViewProps; constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } @observable _selected = false; public get SELECTED() { diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx index 02ed56333..ff92c701f 100644 --- a/src/client/views/nodes/EquationBox.tsx +++ b/src/client/views/nodes/EquationBox.tsx @@ -1,5 +1,4 @@ -import EquationEditor from './formattedText/EquationEditor'; -import { action, makeObservable, override, reaction } from 'mobx'; +import { action, makeObservable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Id } from '../../../fields/FieldSymbols'; @@ -11,7 +10,7 @@ import { ViewBoxBaseComponent } from '../DocComponent'; import { LightboxView } from '../LightboxView'; import './EquationBox.scss'; import { FieldView, FieldViewProps } from './FieldView'; -import { copyProps } from '../../../Utils'; +import EquationEditor from './formattedText/EquationEditor'; @observer export class EquationBox extends ViewBoxBaseComponent() { @@ -21,18 +20,11 @@ export class EquationBox extends ViewBoxBaseComponent() { public static SelectOnLoad: string = ''; _ref: React.RefObject = React.createRef(); - _prevProps: React.PropsWithChildren; - @override _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - componentDidMount() { this._props.setContentView?.(this); if (EquationBox.SelectOnLoad === this.Document[Id] && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this._props.docViewPath()))) { diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index d8b1f125c..5a8665aaf 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -1,13 +1,13 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Button, ColorPicker, Dropdown, DropdownType, EditableText, IconButton, IListItemProps, MultiToggle, NumberDropdown, NumberDropdownType, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components'; -import { computed, makeObservable, observable, override } from 'mobx'; +import { computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc'; import { ScriptField } from '../../../../fields/ScriptField'; import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; -import { copyProps, emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; +import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; import { SelectionManager } from '../../../util/SelectionManager'; import { SettingsManager } from '../../../util/SettingsManager'; @@ -45,16 +45,11 @@ export class FontIconBox extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FontIconBox, fieldKey); } - _prevProps: React.PropsWithChildren; - @override _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } // // This controls whether fontIconButtons will display labels under their icons or not // @@ -64,6 +59,7 @@ export class FontIconBox extends ViewBoxBaseComponent() { public static set ShowIconLabels(show: boolean) { Doc.UserDoc()._showLabel = show; } + @observable noTooltip = false; showTemplate = (): void => { const dragFactory = Cast(this.layoutDoc.dragFactory, Doc, null); diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx index a04c27e01..29bffb583 100644 --- a/src/client/views/nodes/FunctionPlotBox.tsx +++ b/src/client/views/nodes/FunctionPlotBox.tsx @@ -1,15 +1,12 @@ import functionPlot from 'function-plot'; -import { action, computed, makeObservable, override, reaction } from 'mobx'; +import { computed, makeObservable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast } from '../../../fields/Doc'; -import { documentSchema } from '../../../fields/documentSchemas'; -import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; -import { createSchema, listSpec, makeInterface } from '../../../fields/Schema'; +import { listSpec } from '../../../fields/Schema'; import { Cast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { copyProps } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; @@ -27,19 +24,12 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent _plotId = ''; _plotEle: any; - _prevProps: React.PropsWithChildren; - @override _props: React.PropsWithChildren; constructor(props: React.PropsWithChildren) { super(props); - this._props = this._prevProps = props; makeObservable(this); this._plotId = 'graph' + FunctionPlotBox.GraphCount++; } - componentDidUpdate() { - copyProps(this); - } - componentDidMount() { this._props.setContentView?.(this); reaction( diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 091c1a32f..b1ccd38ba 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -1,6 +1,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, override, reaction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction } from 'mobx'; import { observer } from 'mobx-react'; import { extname } from 'path'; import * as React from 'react'; @@ -12,7 +12,7 @@ import { ObjectField } from '../../../fields/ObjectField'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { copyProps, DashColor, emptyFunction, returnEmptyString, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; +import { DashColor, emptyFunction, returnEmptyString, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; import { DocumentManager } from '../../util/DocumentManager'; @@ -55,19 +55,11 @@ export class ImageBox extends ViewBoxAnnotatableComponent(); @observable _curSuffix = ''; - _prevProps: ViewBoxAnnotatableProps & FieldViewProps; - @override _props: ViewBoxAnnotatableProps & FieldViewProps; constructor(props: ViewBoxAnnotatableProps & FieldViewProps) { super(props); - this._props = this._prevProps = props; - makeObservable(this); this._props.setContentView?.(this); } - componentDidUpdate() { - copyProps(this); - } - protected createDropTarget = (ele: HTMLDivElement) => { this._dropDisposer?.(); ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.Document)); diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 9aab53daf..73fdc3a23 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -1,26 +1,27 @@ import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { returnAlways, returnTrue } from '../../../Utils'; import { Doc, Field, FieldResult } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { RichTextField } from '../../../fields/RichTextField'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; import { DocCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; -import { copyProps, returnAll, returnAlways, returnTrue } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { SetupDrag } from '../../util/DragManager'; -import { CompiledScript, CompileScript, ScriptOptions } from '../../util/Scripting'; +import { CompileScript, CompiledScript, ScriptOptions } from '../../util/Scripting'; import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import { DocumentIconContainer } from './DocumentIcon'; import { OpenWhere } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; -import { FormattedTextBox } from './formattedText/FormattedTextBox'; import { ImageBox } from './ImageBox'; import './KeyValueBox.scss'; import { KeyValuePair } from './KeyValuePair'; -import * as React from 'react'; +import { FormattedTextBox } from './formattedText/FormattedTextBox'; export type KVPScript = { script: CompiledScript; @@ -28,28 +29,20 @@ export type KVPScript = { onDelegate: boolean; }; @observer -export class KeyValueBox extends React.Component { +export class KeyValueBox extends ObservableReactComponent { public static LayoutString() { return FieldView.LayoutString(KeyValueBox, 'data'); } + constructor(props: any) { + super(props); + makeObservable(this); + } private _mainCont = React.createRef(); private _keyHeader = React.createRef(); private _keyInput = React.createRef(); private _valInput = React.createRef(); - _prevProps: FieldViewProps; - @observable _props: FieldViewProps; - constructor(props: FieldViewProps) { - super(props); - this._props = this._prevProps = props; - makeObservable(this); - } - - componentDidUpdate() { - copyProps(this); - } - componentDidMount() { this._props.setContentView?.(this); } diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 40991f371..fd8d8ef56 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -1,21 +1,23 @@ -import { action, makeObservable, observable, toJS } from 'mobx'; +import { Tooltip } from '@mui/material'; +import { action, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; +import { ObservableGroupMap } from 'mobx-utils'; +import * as React from 'react'; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero } from '../../../Utils'; import { Doc, Field } from '../../../fields/Doc'; -import { copyProps, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero } from '../../../Utils'; +import { DocCast } from '../../../fields/Types'; +import { DocumentOptions, FInfo } from '../../documents/Documents'; import { Transform } from '../../util/Transform'; import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { EditableView } from '../EditableView'; import { DefaultStyleProvider } from '../StyleProvider'; -import { OpenWhere, OpenWhereMod } from './DocumentView'; -import { FieldView, FieldViewProps } from './FieldView'; +import { OpenWhere } from './DocumentView'; +import { FieldViewProps } from './FieldView'; import { KeyValueBox } from './KeyValueBox'; import './KeyValueBox.scss'; import './KeyValuePair.scss'; -import * as React from 'react'; -import { DocCast } from '../../../fields/Types'; -import { Tooltip } from '@mui/material'; -import { DocumentOptions, FInfo } from '../../documents/Documents'; +import { ObservableReactComponent } from '../ObservableReactComponent'; // Represents one row in a key value plane @@ -29,22 +31,15 @@ export interface KeyValuePairProps { addDocTab: (doc: Doc, where: OpenWhere) => boolean; } @observer -export class KeyValuePair extends React.Component { +export class KeyValuePair extends ObservableReactComponent { @observable private isPointerOver = false; @observable public isChecked = false; private checkbox = React.createRef(); - - _prevProps: KeyValuePairProps; - @observable _props: KeyValuePairProps; - constructor(props: KeyValuePairProps) { + constructor(props:any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } @action handleCheck = (e: React.ChangeEvent) => { diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx index 52ca8b5b1..934bce448 100644 --- a/src/client/views/nodes/LabelBox.tsx +++ b/src/client/views/nodes/LabelBox.tsx @@ -1,11 +1,10 @@ -import { action, computed, makeObservable, observable, override } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; -import { Cast, StrCast, NumCast, BoolCast } from '../../../fields/Types'; -import { copyProps } from '../../../Utils'; +import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types'; import { DragManager } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; @@ -31,16 +30,11 @@ export class LabelBox extends ViewBoxBaseComponent; - @override _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } + componentDidMount() { this._props.setContentView?.(this); } diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index a7e905fca..b86ba72a0 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -1,9 +1,9 @@ -import { action, computed, makeObservable, observable, override } from 'mobx'; -import { observer } from 'mobx-react'; +import { action, computed, makeObservable } from 'mobx'; +import * as React from 'react'; +import { Utils, emptyFunction, setupMoveUpEvents } from '../../../Utils'; import { Doc } from '../../../fields/Doc'; import { NumCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, setupMoveUpEvents, Utils } from '../../../Utils'; import { DragManager } from '../../util/DragManager'; import { LinkFollower } from '../../util/LinkFollower'; import { SelectionManager } from '../../util/SelectionManager'; @@ -12,11 +12,7 @@ import { StyleProp } from '../StyleProvider'; import { FieldView, FieldViewProps } from './FieldView'; import './LinkAnchorBox.scss'; import { LinkInfo } from './LinkDocPreview'; -import * as React from 'react'; -const { - default: { MEDIUM_GRAY }, -} = require('../global/globalCssVariables.module.scss'); -@observer +const { default: { MEDIUM_GRAY }, } = require('../global/globalCssVariables.module.scss'); // prettier-ignore export class LinkAnchorBox extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkAnchorBox, fieldKey); @@ -26,14 +22,9 @@ export class LinkAnchorBox extends ViewBoxBaseComponent() { _ref = React.createRef(); _isOpen = false; _timeout: NodeJS.Timeout | undefined; - @observable _x = 0; - @observable _y = 0; - _prevProps: FieldViewProps; - @override _props: FieldViewProps; - constructor(props: FieldViewProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index acafd6d09..134f2e14a 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -1,10 +1,10 @@ -import * as React from 'react'; import { Bezier } from 'bezier-js'; -import { computed, IReactionDisposer, makeObservable, observable, override, reaction } from 'mobx'; +import { computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Id } from '../../../fields/FieldSymbols'; import { DocCast, NumCast, StrCast } from '../../../fields/Types'; -import { aggregateBounds, copyProps, emptyFunction, returnAlways, returnFalse, Utils } from '../../../Utils'; +import { aggregateBounds, emptyFunction, returnAlways, returnFalse, Utils } from '../../../Utils'; import { DocumentManager } from '../../util/DocumentManager'; import { Transform } from '../../util/Transform'; import { CollectionFreeFormView } from '../collections/collectionFreeForm'; @@ -20,18 +20,11 @@ export class LinkBox extends ViewBoxBaseComponent() { return FieldView.LayoutString(LinkBox, fieldKey); } - _prevProps: FieldViewProps; - @override _props: FieldViewProps; - constructor(props: FieldViewProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - onClickScriptDisable = returnAlways; @computed get anchor1() { const anchor1 = DocCast(this.dataDoc.link_anchor_1); diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 108930ad9..fa7a55bc7 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -19,6 +19,7 @@ import { Transform } from '../../util/Transform'; import { DocumentView, DocumentViewSharedProps, OpenWhere } from './DocumentView'; import './LinkDocPreview.scss'; import * as React from 'react'; +import { ObservableReactComponent } from '../ObservableReactComponent'; export class LinkInfo { private static _instance: Opt; @@ -49,15 +50,7 @@ interface LinkDocPreviewProps { noPreview?: boolean; } @observer -export class LinkDocPreview extends React.Component { - _prevProps: LinkDocPreviewProps; - @observable _props: LinkDocPreviewProps; - constructor(props: LinkDocPreviewProps) { - super(props); - this._props = this._prevProps = props; - makeObservable(this); - } - +export class LinkDocPreview extends ObservableReactComponent { _infoRef = React.createRef(); _linkDocRef = React.createRef(); @observable _targetDoc: Opt = undefined; @@ -66,6 +59,10 @@ export class LinkDocPreview extends React.Component { @observable _linkSrc: Opt = undefined; @observable _toolTipText = ''; @observable _hrefInd = 0; + constructor(props: any) { + super(props); + makeObservable(this); + } @action init() { @@ -84,9 +81,9 @@ export class LinkDocPreview extends React.Component { this._toolTipText = ''; this.updateHref(); } - componentDidUpdate(props: any) { - copyProps(this); - if (props.linkSrc !== this._props.linkSrc || props.linkDoc !== this._props.linkDoc || props.hrefs !== this._props.hrefs) this.init(); + componentDidUpdate(prevProps: Readonly) { + copyProps(this, prevProps); + if (prevProps.linkSrc !== this._props.linkSrc || prevProps.linkDoc !== this._props.linkDoc || prevProps.hrefs !== this._props.hrefs) this.init(); } componentDidMount() { this.init(); diff --git a/src/client/views/nodes/MapBox/MapAnchorMenu.tsx b/src/client/views/nodes/MapBox/MapAnchorMenu.tsx index ee1ea3ceb..b458e5a28 100644 --- a/src/client/views/nodes/MapBox/MapAnchorMenu.tsx +++ b/src/client/views/nodes/MapBox/MapAnchorMenu.tsx @@ -1,9 +1,9 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { IReactionDisposer, ObservableMap, reaction } from 'mobx'; import { observer } from 'mobx-react'; -import { Doc, Opt } from '../../../../fields/Doc'; +import * as React from 'react'; import { returnFalse, setupMoveUpEvents, unimplementedFunction } from '../../../../Utils'; +import { Doc, Opt } from '../../../../fields/Doc'; import { SelectionManager } from '../../../util/SelectionManager'; import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu'; // import { GPTPopup, GPTPopupMode } from './../../GPTPopup/GPTPopup'; @@ -36,7 +36,6 @@ export class MapAnchorMenu extends AntimodeMenu { constructor(props: Readonly<{}>) { super(props); - MapAnchorMenu.Instance = this; MapAnchorMenu.Instance._canFade = false; } diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 98a302834..a420e0101 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -1,24 +1,24 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import BingMapsReact from 'bingmaps-react'; import { Button, EditableText, IconButton, Type } from 'browndash-components'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, override, reaction, runInAction } from 'mobx'; +import { IReactionDisposer, ObservableMap, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, setupMoveUpEvents } from '../../../../Utils'; import { Doc, DocListCast, Field, LinkedTo, Opt } from '../../../../fields/Doc'; import { DocCss, Highlight } from '../../../../fields/DocSymbols'; import { DocCast, NumCast, StrCast } from '../../../../fields/Types'; -import { copyProps, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, setupMoveUpEvents, Utils } from '../../../../Utils'; -import { Docs, DocUtils } from '../../../documents/Documents'; import { DocumentType } from '../../../documents/DocumentTypes'; +import { DocUtils, Docs } from '../../../documents/Documents'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from '../../../util/DragManager'; import { LinkManager } from '../../../util/LinkManager'; import { Transform } from '../../../util/Transform'; -import { undoable, UndoManager } from '../../../util/UndoManager'; -import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm'; +import { UndoManager, undoable } from '../../../util/UndoManager'; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocComponent'; -import { Colors } from '../../global/globalEnums'; import { SidebarAnnos } from '../../SidebarAnnos'; +import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm'; +import { Colors } from '../../global/globalEnums'; import { DocumentView } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; import { FormattedTextBox } from '../formattedText/FormattedTextBox'; @@ -67,18 +67,12 @@ export class MapBox extends ViewBoxAnnotatableComponent = React.createRef(); private _disposers: { [key: string]: IReactionDisposer } = {}; - _unmounting = false; - _prevProps: ViewBoxAnnotatableProps & FieldViewProps; - @override _props: ViewBoxAnnotatableProps & FieldViewProps; - constructor(props: ViewBoxAnnotatableProps & FieldViewProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } + _unmounting = false; @observable private _savedAnnotations = new ObservableMap(); @computed get allSidebarDocs() { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index a453210eb..213f88177 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -1,8 +1,9 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, IReactionDisposer, makeObservable, observable, override, reaction, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as Pdfjs from 'pdfjs-dist'; import 'pdfjs-dist/web/pdf_viewer.css'; +import * as React from 'react'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; @@ -10,7 +11,7 @@ import { ComputedField } from '../../../fields/ScriptField'; import { Cast, FieldValue, ImageCast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField, PdfField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { copyProps, emptyFunction, returnFalse, setupMoveUpEvents, Utils } from '../../../Utils'; +import { emptyFunction, returnFalse, setupMoveUpEvents, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; import { DocumentManager } from '../../util/DocumentManager'; @@ -31,7 +32,6 @@ import { FieldView, FieldViewProps } from './FieldView'; import { ImageBox } from './ImageBox'; import './PDFBox.scss'; import { PinProps, PresBox } from './trails'; -import * as React from 'react'; @observer export class PDFBox extends ViewBoxAnnotatableComponent() { @@ -58,11 +58,8 @@ export class PDFBox extends ViewBoxAnnotatableComponent (this._pdf = pdf))); } } - componentDidUpdate() { - copyProps(this); - } replaceCanvases = (oldDiv: HTMLElement, newDiv: HTMLElement) => { if (oldDiv.childNodes) { diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index a4f4897ba..ebe86318d 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -1,15 +1,15 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, override, reaction, runInAction, untracked } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction, untracked } from 'mobx'; import { observer } from 'mobx-react'; import { basename } from 'path'; +import * as React from 'react'; import { Doc, StrListCast } from '../../../fields/Doc'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; import { ObjectField } from '../../../fields/ObjectField'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { AudioField, ImageField, VideoField } from '../../../fields/URLField'; -import { copyProps, emptyFunction, formatTime, returnEmptyString, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; +import { emptyFunction, formatTime, returnEmptyString, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; import { Networking } from '../../Network'; @@ -68,19 +68,12 @@ export class VideoBox extends ViewBoxAnnotatableComponent(); diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 995f9f6e0..2f92f1edb 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, override, reaction, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import * as WebRequest from 'web-request'; @@ -13,7 +13,7 @@ import { listSpec } from '../../../fields/Schema'; import { Cast, NumCast, StrCast, WebCast } from '../../../fields/Types'; import { ImageField, WebField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, copyProps, emptyFunction, getWordAtPoint, lightOrDark, returnFalse, returnOne, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, getWordAtPoint, lightOrDark, returnFalse, returnOne, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; @@ -98,19 +98,12 @@ export class WebBox extends ViewBoxAnnotatableComponent { if (!this._searching && !clear) { diff --git a/src/client/views/nodes/audio/AudioWaveform.tsx b/src/client/views/nodes/audio/AudioWaveform.tsx index 1b1a85800..01392c4a5 100644 --- a/src/client/views/nodes/audio/AudioWaveform.tsx +++ b/src/client/views/nodes/audio/AudioWaveform.tsx @@ -1,15 +1,16 @@ import axios from 'axios'; -import { computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; +import { computed, IReactionDisposer, makeObservable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, NumListCast } from '../../../../fields/Doc'; import { List } from '../../../../fields/List'; import { listSpec } from '../../../../fields/Schema'; import { Cast } from '../../../../fields/Types'; -import { copyProps, numberRange } from '../../../../Utils'; +import { numberRange } from '../../../../Utils'; import { Colors } from './../../global/globalEnums'; import './AudioWaveform.scss'; import { WaveCanvas } from './WaveCanvas'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; /** * AudioWaveform @@ -35,21 +36,15 @@ export interface AudioWaveformProps { } @observer -export class AudioWaveform extends React.Component { +export class AudioWaveform extends ObservableReactComponent { public static NUMBER_OF_BUCKETS = 100; // number of buckets data is divided into to draw waveform lines _disposer: IReactionDisposer | undefined; - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - get waveHeight() { return Math.max(50, this._props.PanelHeight); } diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index e2cceb906..555b752f0 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -2,22 +2,23 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; import { action, computed, IReactionDisposer, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import { Doc } from '../../../../fields/Doc'; import { List } from '../../../../fields/List'; import { listSpec } from '../../../../fields/Schema'; import { SchemaHeaderField } from '../../../../fields/SchemaHeaderField'; -import { Cast, StrCast } from '../../../../fields/Types'; -import { copyProps, emptyFunction, returnFalse, returnZero, setupMoveUpEvents } from '../../../../Utils'; +import { Cast } from '../../../../fields/Types'; +import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents } from '../../../../Utils'; import { DocServer } from '../../../DocServer'; import { CollectionViewType } from '../../../documents/DocumentTypes'; +import { Transform } from '../../../util/Transform'; import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu'; import { SchemaTableCell } from '../../collections/collectionSchema/SchemaTableCell'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; import { OpenWhere } from '../DocumentView'; import './DashFieldView.scss'; import { FormattedTextBox } from './FormattedTextBox'; -import * as React from 'react'; -import { Transform } from '../../../util/Transform'; export class DashFieldView { dom: HTMLDivElement; // container for label and value @@ -92,7 +93,7 @@ interface IDashFieldViewInternal { } @observer -export class DashFieldViewInternal extends React.Component { +export class DashFieldViewInternal extends ObservableReactComponent { _reactionDisposer: IReactionDisposer | undefined; _textBoxDoc: Doc; _fieldKey: string; @@ -100,11 +101,8 @@ export class DashFieldViewInternal extends React.Component, prevState: Readonly<{}>, snapshot?: any): void { - copyProps(this); - } + componentWillUnmount() { this._reactionDisposer?.(); } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 56bf15b09..997c3f86d 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -2,7 +2,7 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; import { isEqual } from 'lodash'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableSet, override, reaction, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, ObservableSet, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { baseKeymap, selectAll } from 'prosemirror-commands'; import { history } from 'prosemirror-history'; @@ -14,7 +14,7 @@ import { EditorView } from 'prosemirror-view'; import { BsMarkdownFill } from 'react-icons/bs'; import { DateField } from '../../../../fields/DateField'; import { Doc, DocListCast, Field, Opt } from '../../../../fields/Doc'; -import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DocCss, DocData, ForceServerWrite, UpdatingFromServer } from '../../../../fields/DocSymbols'; +import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DocCss, ForceServerWrite, UpdatingFromServer } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { InkTool } from '../../../../fields/InkField'; import { List } from '../../../../fields/List'; @@ -24,7 +24,7 @@ import { RichTextUtils } from '../../../../fields/RichTextUtils'; import { ComputedField } from '../../../../fields/ScriptField'; import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, copyProps, emptyFunction, numberRange, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils'; import { GoogleApiClientUtils, Pulls, Pushes } from '../../../apis/google_docs/GoogleApiClientUtils'; import { gptAPICall, GPTCallType } from '../../../apis/gpt/GPT'; import { DocServer } from '../../../DocServer'; @@ -55,7 +55,7 @@ import { StyleProp } from '../../StyleProvider'; import { media_state } from '../AudioBox'; import { DocFocusOptions, DocumentView, DocumentViewInternal, OpenWhere } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; -import { LinkDocPreview, LinkInfo } from '../LinkDocPreview'; +import { LinkInfo } from '../LinkDocPreview'; import { PinProps, PresBox } from '../trails'; import { DashDocCommentView } from './DashDocCommentView'; import { DashDocView } from './DashDocView'; @@ -208,20 +208,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent; - @override _props: React.PropsWithChildren; constructor(props: React.PropsWithChildren) { super(props); - this._props = this._prevProps = props; makeObservable(this); FormattedTextBox.Instance = this; this._recordingStart = Date.now(); } - componentDidUpdate() { - copyProps(this); - } - // removes all hyperlink anchors for the removed linkDoc // TODO: bcz: Argh... if a section of text has multiple anchors, this should just remove the intended one. // but since removing one anchor from the list of attr anchors isn't implemented, this will end up removing nothing. diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 7de1eb717..4881070fd 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -1,21 +1,22 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; -import { action, computed, IReactionDisposer, makeObservable, observable, override, reaction, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import { lift, wrapIn } from 'prosemirror-commands'; import { Mark, MarkType, Node as ProsNode, ResolvedPos } from 'prosemirror-model'; import { wrapInList } from 'prosemirror-schema-list'; import { EditorState, NodeSelection, TextSelection } from 'prosemirror-state'; import { EditorView } from 'prosemirror-view'; +import * as React from 'react'; import { Doc } from '../../../../fields/Doc'; import { BoolCast, Cast, StrCast } from '../../../../fields/Types'; -import { copyProps, numberRange } from '../../../../Utils'; +import { numberRange } from '../../../../Utils'; import { DocServer } from '../../../DocServer'; import { LinkManager } from '../../../util/LinkManager'; import { SelectionManager } from '../../../util/SelectionManager'; import { undoBatch, UndoManager } from '../../../util/UndoManager'; import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; import { EquationBox } from '../EquationBox'; import { FieldViewProps } from '../FieldView'; import { FormattedTextBox } from './FormattedTextBox'; @@ -63,18 +64,13 @@ export class RichTextMenu extends AntimodeMenu { @observable private showLinkDropdown: boolean = false; _reaction: IReactionDisposer | undefined; - _prevProps: AntimodeMenuProps; - @override _props: AntimodeMenuProps; constructor(props: AntimodeMenuProps) { super(props); - this._props = this._prevProps = props; makeObservable(this); - runInAction(() => { - RichTextMenu.Instance = this; - this.updateMenu(undefined, undefined, props, this.layoutDoc); - this._canFade = false; - this.Pinned = true; - }); + RichTextMenu.Instance = this; + this.updateMenu(undefined, undefined, props, this.layoutDoc); + this._canFade = false; + this.Pinned = true; } @computed get noAutoLink() { @@ -111,9 +107,6 @@ export class RichTextMenu extends AntimodeMenu { return BoolCast(this.layoutDoc?.layout_centered); } _disposer: IReactionDisposer | undefined; - componentDidUpdate() { - copyProps(this); - } componentDidMount() { this._disposer = reaction( () => SelectionManager.Views.slice(), @@ -368,7 +361,7 @@ export class RichTextMenu extends AntimodeMenu { } else if (SelectionManager.Views.some(dv => dv.ComponentView instanceof EquationBox)) { SelectionManager.Views.forEach(dv => (dv.Document._text_fontSize = fontSize)); } else Doc.UserDoc().fontSize = fontSize; - this.updateMenu(this.view, undefined, this._props, this.layoutDoc); + this.updateMenu(this.view, undefined, this.props, this.layoutDoc); }; setFontFamily = (family: string) => { @@ -377,7 +370,7 @@ export class RichTextMenu extends AntimodeMenu { this.setMark(fmark, this.view.state, (tx: any) => this.view!.dispatch(tx.addStoredMark(fmark)), true); this.view.focus(); } else Doc.UserDoc().fontFamily = family; - this.updateMenu(this.view, undefined, this._props, this.layoutDoc); + this.updateMenu(this.view, undefined, this.props, this.layoutDoc); }; setHighlight(color: string) { @@ -386,7 +379,7 @@ export class RichTextMenu extends AntimodeMenu { this.setMark(highlightMark, this.view.state, (tx: any) => this.view!.dispatch(tx.addStoredMark(highlightMark)), true); this.view.focus(); } else Doc.UserDoc()._fontHighlight = color; - this.updateMenu(this.view, undefined, this._props, this.layoutDoc); + this.updateMenu(this.view, undefined, this.props, this.layoutDoc); } setColor(color: string) { @@ -395,7 +388,7 @@ export class RichTextMenu extends AntimodeMenu { this.setMark(colorMark, this.view.state, (tx: any) => this.view!.dispatch(tx.addStoredMark(colorMark)), true); this.view.focus(); } else Doc.UserDoc().fontColor = color; - this.updateMenu(this.view, undefined, this._props, this.layoutDoc); + this.updateMenu(this.view, undefined, this.props, this.layoutDoc); } // TODO: remove doesn't work @@ -436,7 +429,7 @@ export class RichTextMenu extends AntimodeMenu { } } this.view.focus(); - this.updateMenu(this.view, undefined, this._props, this.layoutDoc); + this.updateMenu(this.view, undefined, this.props, this.layoutDoc); }; insertSummarizer(state: EditorState, dispatch: any) { @@ -818,22 +811,15 @@ interface ButtonDropdownProps { } @observer -export class ButtonDropdown extends React.Component { +export class ButtonDropdown extends ObservableReactComponent { @observable private showDropdown: boolean = false; private ref: HTMLDivElement | null = null; - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - componentDidMount() { document.addEventListener('pointerdown', this.onBlur); } diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 9fcb496b8..ec5d090dd 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -1,12 +1,13 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; -import { action, computed, IReactionDisposer, makeObservable, observable, override, reaction, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Doc, DocListCast, Opt } from '../../../../fields/Doc'; import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types'; -import { copyProps, emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils'; import { Docs } from '../../../documents/Documents'; import { CollectionViewType } from '../../../documents/DocumentTypes'; import { DocumentManager } from '../../../util/DocumentManager'; @@ -24,7 +25,6 @@ import { StyleProp } from '../../StyleProvider'; import { PresBox } from './PresBox'; import './PresElementBox.scss'; import { PresMovement } from './PresEnums'; -import * as React from 'react'; /** * This class models the view a document added to presentation will have in the presentation. * It involves some functionality for its buttons and options. @@ -41,19 +41,12 @@ export class PresElementBox extends ViewBoxBaseComponent() { readonly expandViewHeight = 100; readonly collapsedHeight = 35; - @observable _dragging = false; - - _prevProps: FieldViewProps; - @override _props: FieldViewProps; - constructor(props: FieldViewProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } + @observable _dragging = false; // the presentation view that renders this slide @computed get presBoxView() { diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index 0627876fa..a8c83ded6 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -1,12 +1,12 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { ColorPicker, Group, IconButton, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, override, reaction } from 'mobx'; +import { IReactionDisposer, ObservableMap, action, computed, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { ColorResult } from 'react-color'; +import { Utils, returnFalse, setupMoveUpEvents, unimplementedFunction } from '../../../Utils'; import { Doc, Opt } from '../../../fields/Doc'; -import { copyProps, returnFalse, setupMoveUpEvents, unimplementedFunction, Utils } from '../../../Utils'; -import { gptAPICall, GPTCallType } from '../../apis/gpt/GPT'; +import { GPTCallType, gptAPICall } from '../../apis/gpt/GPT'; import { DocumentType } from '../../documents/DocumentTypes'; import { SelectionManager } from '../../util/SelectionManager'; import { SettingsManager } from '../../util/SettingsManager'; @@ -23,18 +23,12 @@ export class AnchorMenu extends AntimodeMenu { private _commentRef = React.createRef(); private _cropRef = React.createRef(); - _prevProps: AntimodeMenuProps; - @override _props: AntimodeMenuProps; constructor(props: AntimodeMenuProps) { super(props); - this._props = this._prevProps = props; makeObservable(this); AnchorMenu.Instance = this; AnchorMenu.Instance._canFade = false; } - componentDidUpdate() { - copyProps(this); - } @observable private highlightColor: string = 'rgba(245, 230, 95, 0.616)'; diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index a581e9df6..e342c25b3 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -1,13 +1,16 @@ import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as Pdfjs from 'pdfjs-dist'; import 'pdfjs-dist/web/pdf_viewer.css'; +import * as PDFJSViewer from 'pdfjs-dist/web/pdf_viewer.mjs'; +import * as React from 'react'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { Height } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, copyProps, emptyFunction, returnAll, returnFalse, returnNone, returnZero, smoothScroll, Utils } from '../../../Utils'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, returnAll, returnFalse, returnNone, returnZero, smoothScroll, Utils } from '../../../Utils'; import { DocUtils } from '../../documents/Documents'; import { SelectionManager } from '../../util/SelectionManager'; import { SnappingManager } from '../../util/SnappingManager'; @@ -16,15 +19,13 @@ import { CollectionFreeFormView } from '../collections/collectionFreeForm/Collec import { MarqueeAnnotator } from '../MarqueeAnnotator'; import { DocFocusOptions, DocumentViewProps } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; -import { LinkDocPreview, LinkInfo } from '../nodes/LinkDocPreview'; +import { LinkInfo } from '../nodes/LinkDocPreview'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import { StyleProp } from '../StyleProvider'; import { AnchorMenu } from './AnchorMenu'; import { Annotation } from './Annotation'; import { GPTPopup } from './GPTPopup/GPTPopup'; import './PDFViewer.scss'; -import * as React from 'react'; -import * as Pdfjs from 'pdfjs-dist'; -import * as PDFJSViewer from 'pdfjs-dist/web/pdf_viewer.mjs'; const _global = (window /* browser */ || global) /* node */ as any; //pdfjsLib.GlobalWorkerOptions.workerSrc = `/assets/pdf.worker.js`; @@ -49,14 +50,11 @@ interface IViewerProps extends FieldViewProps { * Handles rendering and virtualization of the pdf */ @observer -export class PDFViewer extends React.Component { +export class PDFViewer extends ObservableReactComponent { static _annotationStyle: any = addStyleSheet(); - _prevProps: IViewerProps; - @observable _props: IViewerProps; - constructor(props: IViewerProps) { + constructor(props: any) { super(props); - this._prevProps = this._props = props; makeObservable(this); } @@ -66,10 +64,6 @@ export class PDFViewer extends React.Component { @observable _showWaiting = true; @observable Index: number = -1; - componentDidUpdate() { - copyProps(this); - } - private _pdfViewer: any; private _styleRule: any; // stylesheet rule for making hyperlinks clickable private _retries = 0; // number of times tried to create the PDF viewer -- cgit v1.2.3-70-g09d2