aboutsummaryrefslogtreecommitdiff
path: root/src/client/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util')
-rw-r--r--src/client/util/BranchingTrailManager.tsx12
-rw-r--r--src/client/util/CaptureManager.scss7
-rw-r--r--src/client/util/CaptureManager.tsx5
-rw-r--r--src/client/util/CurrentUserUtils.ts14
-rw-r--r--src/client/util/DictationManager.ts2
-rw-r--r--src/client/util/DocumentManager.ts44
-rw-r--r--src/client/util/DragManager.ts55
-rw-r--r--src/client/util/GroupManager.tsx13
-rw-r--r--src/client/util/History.ts2
-rw-r--r--src/client/util/HypothesisUtils.ts2
-rw-r--r--src/client/util/Import & Export/DirectoryImportBox.tsx819
-rw-r--r--src/client/util/Import & Export/ImportMetadataEntry.tsx84
-rw-r--r--src/client/util/InteractionUtils.tsx2
-rw-r--r--src/client/util/LinkManager.ts26
-rw-r--r--src/client/util/PingManager.ts3
-rw-r--r--src/client/util/RTFMarkup.tsx5
-rw-r--r--src/client/util/ReplayMovements.ts3
-rw-r--r--src/client/util/Scripting.ts7
-rw-r--r--src/client/util/ScrollBox.tsx2
-rw-r--r--src/client/util/SearchUtil.ts6
-rw-r--r--src/client/util/SelectionManager.ts128
-rw-r--r--src/client/util/SerializationHelper.ts1
-rw-r--r--src/client/util/ServerStats.tsx9
-rw-r--r--src/client/util/SettingsManager.scss4
-rw-r--r--src/client/util/SettingsManager.tsx8
-rw-r--r--src/client/util/SharingManager.tsx17
-rw-r--r--src/client/util/SnappingManager.ts95
-rw-r--r--src/client/util/TrackMovements.ts4
-rw-r--r--src/client/util/reportManager/ReportManager.scss7
-rw-r--r--src/client/util/reportManager/ReportManager.tsx11
-rw-r--r--src/client/util/reportManager/ReportManagerComponents.tsx2
31 files changed, 669 insertions, 730 deletions
diff --git a/src/client/util/BranchingTrailManager.tsx b/src/client/util/BranchingTrailManager.tsx
index a224b84f4..11f16493f 100644
--- a/src/client/util/BranchingTrailManager.tsx
+++ b/src/client/util/BranchingTrailManager.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable } from 'mobx';
+import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc } from '../../fields/Doc';
@@ -15,13 +15,14 @@ export class BranchingTrailManager extends React.Component {
constructor(props: any) {
super(props);
+ makeObservable(this);
if (!BranchingTrailManager.Instance) {
BranchingTrailManager.Instance = this;
}
}
setupUi = () => {
- OverlayView.Instance.addWindow(<BranchingTrailManager></BranchingTrailManager>, { x: 100, y: 150, width: 1000, title: 'Branching Trail'});
+ OverlayView.Instance.addWindow(<BranchingTrailManager></BranchingTrailManager>, { x: 100, y: 150, width: 1000, title: 'Branching Trail' });
// OverlayView.Instance.forceUpdate();
console.log(OverlayView.Instance);
// let hi = Docs.Create.TextDocument("beee", {
@@ -30,11 +31,10 @@ export class BranchingTrailManager extends React.Component {
// })
// hi.overlayX = 100;
// hi.overlayY = 100;
-
+
// Doc.AddToMyOverlay(hi);
console.log(DocumentManager._overlayViews);
};
-
// stack of the history
@observable private slideHistoryStack: String[] = [];
@@ -69,7 +69,7 @@ export class BranchingTrailManager extends React.Component {
if (this.prevPresId === null || this.prevPresId !== presId) {
Doc.UserDoc().isBranchingMode = true;
this.setPrevPres(presId);
-
+
// REVERT THE SET
const stringified = [presId, targetDocId].toString();
if (this.containsSet.has([presId, targetDocId].toString())) {
@@ -98,7 +98,7 @@ export class BranchingTrailManager extends React.Component {
const newStack = this.slideHistoryStack.slice(0, removeIndex);
const removed = this.slideHistoryStack.slice(removeIndex);
-
+
this.setSlideHistoryStack(newStack);
removed.forEach(info => this.containsSet.delete(info.toString()));
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/CaptureManager.tsx b/src/client/util/CaptureManager.tsx
index 8a4f37121..071fc1ee9 100644
--- a/src/client/util/CaptureManager.tsx
+++ b/src/client/util/CaptureManager.tsx
@@ -1,5 +1,5 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable } from 'mobx';
+import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc } from '../../fields/Doc';
@@ -20,6 +20,7 @@ export class CaptureManager extends React.Component<{}> {
constructor(props: {}) {
super(props);
+ makeObservable(this);
CaptureManager.Instance = this;
}
@@ -81,7 +82,7 @@ export class CaptureManager extends React.Component<{}> {
<div
className="cancel"
onClick={() => {
- const selected = SelectionManager.Views().slice();
+ const selected = SelectionManager.Views.slice();
SelectionManager.DeselectAll();
selected.map(dv => dv.props.removeDocument?.(dv.props.Document));
this.close();
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index aba466d55..61a9fa7c2 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -110,7 +110,7 @@ export class CurrentUserUtils {
const tempClicks = DocCast(doc[field]);
const reqdClickOpts:DocumentOptions = {_width: 300, _height:200, isSystem: true};
const reqdTempOpts:{opts:DocumentOptions, script: string}[] = [
- { opts: { title: "Open In Target", targetScriptKey: "onChildClick"}, script: "docCastAsync(documentView?.props.docViewPath().lastElement()?.rootDoc.target).then((target) => target && (target.proto.data = new List([self])))"},
+ { opts: { title: "Open In Target", targetScriptKey: "onChildClick"}, script: "docCastAsync(documentView?.props.docViewPath().lastElement()?.Document.target).then((target) => target && (target.proto.data = new List([self])))"},
{ opts: { title: "Open Detail On Right", targetScriptKey: "onChildDoubleClick"}, script: `openDoc(this.doubleClickView.${OpenWhere.addRight})`}];
const reqdClickList = reqdTempOpts.map(opts => {
const allOpts = {...reqdClickOpts, ...opts.opts};
@@ -278,7 +278,7 @@ export class CurrentUserUtils {
{key: "Script", creator: opts => Docs.Create.ScriptingDocument(null, opts), opts: { _width: 200, _height: 250, }},
{key: "DataViz", creator: opts => Docs.Create.DataVizDocument("/users/rz/Downloads/addresses.csv", opts), opts: { _width: 300, _height: 300 }},
{key: "Header", creator: headerTemplate, opts: { _width: 300, _height: 70, _headerPointerEvents: "all", _headerHeight: 12, _headerFontSize: 9, _layout_autoHeight: true, treeView_HideUnrendered: true}},
- {key: "Trail", creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 30, _type_collection: CollectionViewType.Stacking, dropAction: "embed" as dropActionType, treeView_HideTitle: true, _layout_fitWidth:true, _chromeHidden: true, layout_boxShadow: "0 0" }},
+ {key: "Trail", creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 30, _type_collection: CollectionViewType.Stacking, dropAction: "embed" as dropActionType, treeView_HideTitle: true, _layout_fitWidth:true, layout_boxShadow: "0 0" }},
{key: "Tab", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 500, _height: 800, _layout_fitWidth: true, _freeform_backgroundGrid: true, }},
{key: "Slide", creator: opts => Docs.Create.TreeDocument([], opts), opts: { _width: 300, _height: 200, _type_collection: CollectionViewType.Tree,
treeView_HasOverlay: true, _text_fontSize: "20px", _layout_autoHeight: true,
@@ -480,7 +480,7 @@ export class CurrentUserUtils {
const newDashboard = `createNewDashboard()`;
const reqdBtnOpts:DocumentOptions = { _forceActive: true, _width: 30, _height: 30, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true,
- title: "new dashboard", btnType: ButtonType.ClickButton, toolTip: "Create new dashboard", buttonText: "New trail", icon: "plus", isSystem: true };
+ title: "new Dash", btnType: ButtonType.ClickButton, toolTip: "Create new dashboard", buttonText: "New trail", icon: "plus", isSystem: true };
const reqdBtnScript = {onClick: newDashboard,}
const newDashboardButton = DocUtils.AssignScripts(DocUtils.AssignOpts(DocCast(myDashboards?.layout_headerButton), reqdBtnOpts) ?? Docs.Create.FontIconDocument(reqdBtnOpts), reqdBtnScript);
@@ -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>([ScriptField.MakeScript(clearAll("self"))!])
}
return recentlyClosed;
@@ -816,7 +816,7 @@ export class CurrentUserUtils {
// When the user views one of these documents, it will be added to the sharing documents 'viewed' list field
// The sharing document also stores the user's color value which helps distinguish shared documents from personal documents
static setupSharedDocs(doc: Doc, sharingDocumentId: string) {
- const dblClkScript = "{scriptContext.openLevel(documentView); addDocToList(documentView.props.treeViewDoc, 'viewed', documentView.rootDoc);}";
+ const dblClkScript = "{scriptContext.openLevel(documentView); addDocToList(documentView.props.treeViewDoc, 'viewed', documentView.Document);}";
const sharedScripts = { treeView_ChildDoubleClick: dblClkScript, }
const sharedDocOpts:DocumentOptions = {
@@ -946,12 +946,12 @@ 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(";");
const batch = 30000;
- for (let i = 0; i < ids.length; i = Math.min(ids.length, i+batch)) {
+ for (let i = 0; i < ids.length; i += batch) {
await DocServer.GetRefFields(ids.slice(i, i+batch));
}
}
diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts
index 0fd7e840c..039bb360e 100644
--- a/src/client/util/DictationManager.ts
+++ b/src/client/util/DictationManager.ts
@@ -236,7 +236,7 @@ export namespace DictationManager {
export const execute = async (phrase: string) => {
return UndoManager.RunInBatch(async () => {
console.log('PHRASE: ' + phrase);
- const targets = SelectionManager.Views();
+ const targets = SelectionManager.Views;
if (!targets || !targets.length) {
return;
}
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index ad5a1654d..4816f3317 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,4 +1,4 @@
-import { action, computed, observable, ObservableSet, observe } 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,17 +13,22 @@ 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';
const { Howl } = require('howler');
export class DocumentManager {
+ private static _instance: DocumentManager;
+ public static get Instance(): DocumentManager {
+ return this._instance || (this._instance = new this());
+ }
+
//global holds all of the nodes (regardless of which collection they're in)
@observable _documentViews = new Set<DocumentView>();
- @observable public LinkAnchorBoxViews: DocumentView[] = [];
- @observable public LinkedDocumentViews: { a: DocumentView; b: DocumentView; l: Doc }[] = [];
+ @observable.shallow public CurrentlyLoading: Doc[] = [];
+ @observable.shallow public LinkAnchorBoxViews: DocumentView[] = [];
+ @observable.shallow public LinkedDocumentViews: { a: DocumentView; b: DocumentView; l: Doc }[] = [];
@computed public get DocumentViews() {
return Array.from(this._documentViews).filter(view => !(view.ComponentView instanceof KeyValueBox) && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(view.docViewPath)));
}
@@ -34,15 +39,10 @@ export class DocumentManager {
this._documentViews.delete(dv);
}
- private static _instance: DocumentManager;
- public static get Instance(): DocumentManager {
- return this._instance || (this._instance = new this());
- }
-
//private constructor so no other class can create a nodemanager
private constructor() {
- if (!LoadingBox.CurrentlyLoading) LoadingBox.CurrentlyLoading = [];
- observe(LoadingBox.CurrentlyLoading, change => {
+ makeObservable(this);
+ observe(this.CurrentlyLoading, change => {
// watch CurrentlyLoading-- when something is loaded, it's removed from the list and we have to update its icon if it were iconified since LoadingBox icons are different than the media they become
switch (change.type as any) {
case 'update':
@@ -89,11 +89,11 @@ export class DocumentManager {
@action
public AddView = (view: DocumentView) => {
- if (view.props.LayoutTemplateString?.includes(KeyValueBox.name)) return;
- if (view.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
- const viewAnchorIndex = view.props.LayoutTemplateString.includes('link_anchor_2') ? 'link_anchor_2' : 'link_anchor_1';
+ if (view._props.LayoutTemplateString?.includes(KeyValueBox.name)) return;
+ if (view._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
+ const viewAnchorIndex = view._props.LayoutTemplateString.includes('link_anchor_2') ? 'link_anchor_2' : 'link_anchor_1';
const link = view.Document;
- this.LinkAnchorBoxViews?.filter(dv => Doc.AreProtosEqual(dv.Document, link) && !dv.props.LayoutTemplateString?.includes(viewAnchorIndex)).forEach(otherView =>
+ this.LinkAnchorBoxViews?.filter(dv => Doc.AreProtosEqual(dv.Document, link) && !dv._props.LayoutTemplateString?.includes(viewAnchorIndex)).forEach(otherView =>
this.LinkedDocumentViews.push({
a: viewAnchorIndex === 'link_anchor_2' ? otherView : view,
b: viewAnchorIndex === 'link_anchor_2' ? view : otherView,
@@ -116,7 +116,7 @@ export class DocumentManager {
})
);
- if (view.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
+ if (view._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
const index = this.LinkAnchorBoxViews.indexOf(view);
this.LinkAnchorBoxViews.splice(index, 1);
} else {
@@ -153,8 +153,8 @@ export class DocumentManager {
return passes.reduce(
(toReturn, pass) =>
toReturn ??
- docViewArray.filter(view => view.Document === target).find(view => !pass || view.props.docViewPath().lastElement() === preferredCollection) ??
- docViewArray.filter(view => Doc.AreProtosEqual(view.Document, target)).find(view => !pass || view.props.docViewPath().lastElement() === preferredCollection),
+ docViewArray.filter(view => view.Document === target).find(view => !pass || view._props.docViewPath().lastElement() === preferredCollection) ??
+ docViewArray.filter(view => Doc.AreProtosEqual(view.Document, target)).find(view => !pass || view._props.docViewPath().lastElement() === preferredCollection),
undefined as Opt<DocumentView>
);
}
@@ -162,12 +162,12 @@ export class DocumentManager {
public getLightboxDocumentView = (toFind: Doc, originatingDoc: Opt<Doc> = undefined): DocumentView | undefined => {
const views: DocumentView[] = [];
DocumentManager.Instance.DocumentViews.forEach(view => LightboxView.IsLightboxDocView(view.docViewPath) && Doc.AreProtosEqual(view.Document, toFind) && views.push(view));
- return views?.find(view => view.ContentDiv?.getBoundingClientRect().width /*&& view.props.focus !== returnFalse) || views?.find(view => view.props.focus !== returnFalse*/) || (views.length ? views[0] : undefined);
+ return views?.find(view => view.ContentDiv?.getBoundingClientRect().width /*&& view._props.focus !== returnFalse) || views?.find(view => view._props.focus !== returnFalse*/) || (views.length ? views[0] : undefined);
};
public getFirstDocumentView = (toFind: Doc, originatingDoc: Opt<Doc> = undefined): DocumentView | undefined => {
if (LightboxView.LightboxDoc) return DocumentManager.Instance.getLightboxDocumentView(toFind, originatingDoc);
const views = this.getDocumentViews(toFind); //.filter(view => view.Document !== originatingDoc);
- return views?.find(view => view.ContentDiv?.getBoundingClientRect().width /*&& view.props.focus !== returnFalse) || views?.find(view => view.props.focus !== returnFalse*/) || (views.length ? views[0] : undefined);
+ return views?.find(view => view.ContentDiv?.getBoundingClientRect().width /*&& view._props.focus !== returnFalse) || views?.find(view => view._props.focus !== returnFalse*/) || (views.length ? views[0] : undefined);
};
public getDocumentViews(toFindIn: Doc): DocumentView[] {
const toFind =
@@ -303,7 +303,7 @@ export class DocumentManager {
await new Promise<void>(res => docView.iconify(res));
options.didMove = true;
}
- const nextFocus = docView.props.focus(docView.Document, options); // focus the view within its container
+ const nextFocus = docView._props.focus(docView.Document, options); // focus the view within its container
focused = focused || (nextFocus === undefined ? false : true); // keep track of whether focusing on a view needed to actually change anything
const { childDocView, viewSpec } = await iterator(docView);
if (!childDocView) return { viewSpec: options.anchorDoc ?? viewSpec ?? docView.Document, docView, contextView, focused };
@@ -344,7 +344,7 @@ export function DocFocusOrOpen(doc: Doc, options: DocFocusOptions = { willZoomCe
const func = () => {
const cv = DocumentManager.Instance.getDocumentView(containingDoc);
const dv = DocumentManager.Instance.getDocumentView(doc, cv);
- if (dv && (!containingDoc || dv.props.docViewPath().lastElement()?.Document === containingDoc)) {
+ if (dv && (!containingDoc || dv._props.docViewPath().lastElement()?.Document === containingDoc)) {
DocumentManager.Instance.showDocumentView(dv, options).then(() => dv && Doc.linkFollowHighlight(dv.Document));
} else {
const container = DocCast(containingDoc ?? doc.embedContainer ?? Doc.BestEmbedding(doc));
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 6e4de252d..c711db31a 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -7,13 +7,13 @@ 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';
+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
@@ -85,7 +85,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 +218,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);
@@ -261,7 +268,7 @@ export namespace DragManager {
// drags a linker button and creates a link on drop
export function StartLinkDrag(ele: HTMLElement, sourceView: DocumentView, sourceDocGetAnchor: undefined | ((addAsAnnotation: boolean) => Doc), downX: number, downY: number, options?: DragOptions) {
- StartDrag([ele], new DragManager.LinkDragData(sourceView, () => sourceDocGetAnchor?.(true) ?? sourceView.rootDoc), downX, downY, options);
+ StartDrag([ele], new DragManager.LinkDragData(sourceView, () => sourceDocGetAnchor?.(true) ?? sourceView.Document), downX, downY, options);
}
// drags a column from a schema view
@@ -287,14 +294,14 @@ export namespace DragManager {
const dist = Math.sqrt((dragx - x) * (dragx - x) + (dragy - y) * (dragy - y));
return { pt: [x, y], dist };
};
- SnappingManager.vertSnapLines().forEach((xCoord, i) => {
+ SnappingManager.VertSnapLines.forEach((xCoord, i) => {
const pt = intersect(dragPt[0], dragPt[1], dragPt[0] + snapAspect, dragPt[1] + 1, xCoord, -1, xCoord, 1, dragPt[0], dragPt[1]);
if (pt && pt.dist < closest) {
closest = pt.dist;
near = pt.pt;
}
});
- SnappingManager.horizSnapLines().forEach((yCoord, i) => {
+ SnappingManager.HorizSnapLines.forEach((yCoord, i) => {
const pt = intersect(dragPt[0], dragPt[1], dragPt[0] + snapAspect, dragPt[1] + 1, -1, yCoord, 1, yCoord, dragPt[0], dragPt[1]);
if (pt && pt.dist < closest) {
closest = pt.dist;
@@ -318,11 +325,11 @@ export namespace DragManager {
return drag;
};
return {
- x: snapVal([xFromLeft, xFromRight], e.pageX, SnappingManager.vertSnapLines()),
- y: snapVal([yFromTop, yFromBottom], e.pageY, SnappingManager.horizSnapLines()),
+ x: snapVal([xFromLeft, xFromRight], e.pageX, SnappingManager.VertSnapLines),
+ y: snapVal([yFromTop, yFromBottom], e.pageY, SnappingManager.HorizSnapLines),
};
}
- export let docsBeingDragged: Doc[] = observable([] as Doc[]);
+ export let docsBeingDragged: Doc[] = observable([]);
export let CanEmbed = false;
export let DocDragData: DocumentDragData | undefined;
export function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: DragCompleteEvent) => void, dragUndoName?: string) {
@@ -428,7 +435,7 @@ export namespace DragManager {
color: 'black',
transition: 'none',
borderRadius: getComputedStyle(ele).borderRadius,
- zIndex: globalCssVariables.contextMenuZindex,
+ zIndex: contextMenuZindex,
transformOrigin: '0 0',
width,
height,
@@ -463,7 +470,7 @@ export namespace DragManager {
runInAction(() => docsBeingDragged.push(...docsToDrag));
const hideDragShowOriginalElements = (hide: boolean) => {
- dragLabel.style.display = hide && !SnappingManager.GetCanEmbed() ? '' : 'none';
+ dragLabel.style.display = hide && !SnappingManager.CanEmbed ? '' : 'none';
!hide && dragElements.map(dragElement => dragElement.parentNode === dragDiv && dragDiv.removeChild(dragElement));
setTimeout(() => eles.forEach(ele => (ele.hidden = hide)));
};
@@ -564,7 +571,7 @@ export namespace DragManager {
);
scrollAwaiter && clearTimeout(scrollAwaiter);
- SnappingManager.GetIsDragging() && (scrollAwaiter = setTimeout(autoScrollHandler, 25));
+ SnappingManager.IsDragging && (scrollAwaiter = setTimeout(autoScrollHandler, 25));
};
scrollAwaiter && clearTimeout(scrollAwaiter);
scrollAwaiter = setTimeout(autoScrollHandler, 250);
@@ -597,7 +604,7 @@ export namespace DragManager {
altKey: e.altKey,
metaKey: e.metaKey,
ctrlKey: e.ctrlKey,
- embedKey: SnappingManager.GetCanEmbed(),
+ embedKey: SnappingManager.CanEmbed,
},
};
target.dispatchEvent(new CustomEvent<DropEvent>('dashPreDrop', dropArgs));
@@ -611,7 +618,7 @@ export namespace DragManager {
ScriptingGlobals.add(function toggleRaiseOnDrag(readOnly?: boolean) {
if (readOnly) {
- return SelectionManager.Views().some(dv => dv.rootDoc.keepZWhenDragged);
+ return SelectionManager.Views.some(dv => dv.Document.keepZWhenDragged);
}
- SelectionManager.Views().map(dv => (dv.rootDoc.keepZWhenDragged = !dv.rootDoc.keepZWhenDragged));
+ SelectionManager.Views.map(dv => (dv.Document.keepZWhenDragged = !dv.Document.keepZWhenDragged));
});
diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx
index 8973306bf..90f65b648 100644
--- a/src/client/util/GroupManager.tsx
+++ b/src/client/util/GroupManager.tsx
@@ -1,6 +1,6 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Button, IconButton, Size, Type } from 'browndash-components';
-import { action, computed, observable } from 'mobx';
+import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import Select from 'react-select';
@@ -17,6 +17,7 @@ import './GroupManager.scss';
import { GroupMemberView } from './GroupMemberView';
import { SettingsManager } from './SettingsManager';
import { SharingManager, User } from './SharingManager';
+import { ObservableReactComponent } from '../views/ObservableReactComponent';
/**
* Interface for options for the react-select component
@@ -27,7 +28,7 @@ export interface UserOptions {
}
@observer
-export class GroupManager extends React.Component<{}> {
+export class GroupManager extends ObservableReactComponent<{}> {
static Instance: GroupManager;
@observable isOpen: boolean = false; // whether the GroupManager is to be displayed or not.
@observable private users: string[] = []; // list of users populated from the database.
@@ -41,6 +42,7 @@ export class GroupManager extends React.Component<{}> {
constructor(props: Readonly<{}>) {
super(props);
+ makeObservable(this);
GroupManager.Instance = this;
}
@@ -52,7 +54,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 +260,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/History.ts b/src/client/util/History.ts
index 18aee6444..2f1a336cc 100644
--- a/src/client/util/History.ts
+++ b/src/client/util/History.ts
@@ -85,7 +85,7 @@ export namespace HistoryUtil {
};
function addParser(type: string, requiredFields: Parser, optionalFields: Parser, customParser?: (pathname: string[], opts: qs.ParsedQuery, current: ParsedUrl) => ParsedUrl | null | undefined) {
- function parse(parser: ParserValue, value: string | string[] | null | undefined) {
+ function parse(parser: ParserValue, value: string | (string | null)[] | null | undefined) {
if (value === undefined || value === null) {
return value;
}
diff --git a/src/client/util/HypothesisUtils.ts b/src/client/util/HypothesisUtils.ts
index 151f18d6f..990798ed3 100644
--- a/src/client/util/HypothesisUtils.ts
+++ b/src/client/util/HypothesisUtils.ts
@@ -27,7 +27,7 @@ export namespace Hypothesis {
* Search for a WebDocument whose url field matches the given uri, return undefined if not found
*/
export const findWebDoc = async (uri: string) => {
- const currentDoc = SelectionManager.Docs().lastElement();
+ const currentDoc = SelectionManager.Docs.lastElement();
if (currentDoc && Cast(currentDoc.data, WebField)?.url.href === uri) return currentDoc; // always check first whether the currently selected doc is the annotation's source, only use Search otherwise
const results: Doc[] = [];
diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx
index 1a4c2450e..b6dbea33a 100644
--- a/src/client/util/Import & Export/DirectoryImportBox.tsx
+++ b/src/client/util/Import & Export/DirectoryImportBox.tsx
@@ -1,440 +1,439 @@
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { BatchedArray } from 'array-batcher';
-import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
-import { observer } from 'mobx-react';
-import { extname } from 'path';
-import Measure, { ContentRect } from 'react-measure';
-import { Doc, DocListCast, DocListCastAsync, Opt } from '../../../fields/Doc';
-import { Id } from '../../../fields/FieldSymbols';
-import { List } from '../../../fields/List';
-import { listSpec } from '../../../fields/Schema';
-import { SchemaHeaderField } from '../../../fields/SchemaHeaderField';
-import { BoolCast, Cast, NumCast } from '../../../fields/Types';
-import { AcceptableMedia, Upload } from '../../../server/SharedMediaTypes';
-import { Utils } from '../../../Utils';
-import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils';
-import { Docs, DocumentOptions, DocUtils } from '../../documents/Documents';
-import { DocumentType } from '../../documents/DocumentTypes';
-import { Networking } from '../../Network';
-import { FieldView, FieldViewProps } from '../../views/nodes/FieldView';
-import { DocumentManager } from '../DocumentManager';
-import './DirectoryImportBox.scss';
-import ImportMetadataEntry, { keyPlaceholder, valuePlaceholder } from './ImportMetadataEntry';
-import React = require('react');
-import _ = require('lodash');
+// import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+// import { BatchedArray } from 'array-batcher';
+// import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
+// import { observer } from 'mobx-react';
+// import { extname } from 'path';
+// import Measure, { ContentRect } from 'react-measure';
+// import { Doc, DocListCast, DocListCastAsync, Opt } from '../../../fields/Doc';
+// import { Id } from '../../../fields/FieldSymbols';
+// import { List } from '../../../fields/List';
+// import { listSpec } from '../../../fields/Schema';
+// import { SchemaHeaderField } from '../../../fields/SchemaHeaderField';
+// import { BoolCast, Cast, NumCast } from '../../../fields/Types';
+// import { AcceptableMedia, Upload } from '../../../server/SharedMediaTypes';
+// import { Utils } from '../../../Utils';
+// import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils';
+// import { Docs, DocumentOptions, DocUtils } from '../../documents/Documents';
+// import { DocumentType } from '../../documents/DocumentTypes';
+// import { Networking } from '../../Network';
+// import { FieldView, FieldViewProps } from '../../views/nodes/FieldView';
+// import { DocumentManager } from '../DocumentManager';
+// import './DirectoryImportBox.scss';
+// import ImportMetadataEntry, { keyPlaceholder, valuePlaceholder } from './ImportMetadataEntry';
+// import * as React from 'react';
-const unsupported = ['text/html', 'text/plain'];
+// const unsupported = ['text/html', 'text/plain'];
-@observer
-export class DirectoryImportBox extends React.Component<FieldViewProps> {
- private selector = React.createRef<HTMLInputElement>();
- @observable private top = 0;
- @observable private left = 0;
- private dimensions = 50;
- @observable private phase = '';
- private disposer: Opt<IReactionDisposer>;
+// @observer
+// export class DirectoryImportBox extends React.Component<FieldViewProps> {
+// private selector = React.createRef<HTMLInputElement>();
+// @observable private top = 0;
+// @observable private left = 0;
+// private dimensions = 50;
+// @observable private phase = '';
+// private disposer: Opt<IReactionDisposer>;
- @observable private entries: ImportMetadataEntry[] = [];
+// @observable private entries: ImportMetadataEntry[] = [];
- @observable private quota = 1;
- @observable private completed = 0;
+// @observable private quota = 1;
+// @observable private completed = 0;
- @observable private uploading = false;
- @observable private removeHover = false;
+// @observable private uploading = false;
+// @observable private removeHover = false;
- public static LayoutString(fieldKey: string) {
- return FieldView.LayoutString(DirectoryImportBox, fieldKey);
- }
+// public static LayoutString(fieldKey: string) {
+// return FieldView.LayoutString(DirectoryImportBox, fieldKey);
+// }
- constructor(props: FieldViewProps) {
- super(props);
- const doc = this.props.Document;
- this.editingMetadata = this.editingMetadata || false;
- this.persistent = this.persistent || false;
- !Cast(doc.data, listSpec(Doc)) && (doc.data = new List<Doc>());
- }
+// constructor(props: FieldViewProps) {
+// super(props);
+// const doc = this.props.Document;
+// this.editingMetadata = this.editingMetadata || false;
+// this.persistent = this.persistent || false;
+// !Cast(doc.data, listSpec(Doc)) && (doc.data = new List<Doc>());
+// }
- @computed
- private get editingMetadata() {
- return BoolCast(this.props.Document.editingMetadata);
- }
+// @computed
+// private get editingMetadata() {
+// return BoolCast(this.props.Document.editingMetadata);
+// }
- private set editingMetadata(value: boolean) {
- this.props.Document.editingMetadata = value;
- }
+// private set editingMetadata(value: boolean) {
+// this.props.Document.editingMetadata = value;
+// }
- @computed
- private get persistent() {
- return BoolCast(this.props.Document.persistent);
- }
+// @computed
+// private get persistent() {
+// return BoolCast(this.props.Document.persistent);
+// }
- private set persistent(value: boolean) {
- this.props.Document.persistent = value;
- }
+// private set persistent(value: boolean) {
+// this.props.Document.persistent = value;
+// }
- handleSelection = async (e: React.ChangeEvent<HTMLInputElement>) => {
- runInAction(() => {
- this.uploading = true;
- this.phase = 'Initializing download...';
- });
+// handleSelection = async (e: React.ChangeEvent<HTMLInputElement>) => {
+// runInAction(() => {
+// this.uploading = true;
+// this.phase = 'Initializing download...';
+// });
- const docs: Doc[] = [];
+// const docs: Doc[] = [];
- const files = e.target.files;
- if (!files || files.length === 0) return;
+// const files = e.target.files;
+// if (!files || files.length === 0) return;
- const directory = (files.item(0) as any).webkitRelativePath.split('/', 1)[0];
+// const directory = (files.item(0) as any).webkitRelativePath.split('/', 1)[0];
- const validated: File[] = [];
- for (let i = 0; i < files.length; i++) {
- const file = files.item(i);
- if (file && !unsupported.includes(file.type)) {
- const ext = extname(file.name).toLowerCase();
- if (AcceptableMedia.imageFormats.includes(ext)) {
- validated.push(file);
- }
- }
- }
+// const validated: File[] = [];
+// for (let i = 0; i < files.length; i++) {
+// const file = files.item(i);
+// if (file && !unsupported.includes(file.type)) {
+// const ext = extname(file.name).toLowerCase();
+// if (AcceptableMedia.imageFormats.includes(ext)) {
+// validated.push(file);
+// }
+// }
+// }
- runInAction(() => {
- this.quota = validated.length;
- this.completed = 0;
- });
+// runInAction(() => {
+// this.quota = validated.length;
+// this.completed = 0;
+// });
- const sizes: number[] = [];
- const modifiedDates: number[] = [];
+// const sizes: number[] = [];
+// const modifiedDates: number[] = [];
- runInAction(() => (this.phase = `Internal: uploading ${this.quota - this.completed} files to Dash...`));
+// runInAction(() => (this.phase = `Internal: uploading ${this.quota - this.completed} files to Dash...`));
- const batched = BatchedArray.from(validated, { batchSize: 15 });
- const uploads = await batched.batchedMapAsync<Upload.FileResponse<Upload.ImageInformation>>(async (batch, collector) => {
- batch.forEach(file => {
- sizes.push(file.size);
- modifiedDates.push(file.lastModified);
- });
- collector.push(...(await Networking.UploadFilesToServer<Upload.ImageInformation>(batch.map(file =>({file})))));
- runInAction(() => (this.completed += batch.length));
- });
+// const batched = BatchedArray.from(validated, { batchSize: 15 });
+// const uploads = await batched.batchedMapAsync<Upload.FileResponse<Upload.ImageInformation>>(async (batch, collector) => {
+// batch.forEach(file => {
+// sizes.push(file.size);
+// modifiedDates.push(file.lastModified);
+// });
+// collector.push(...(await Networking.UploadFilesToServer<Upload.ImageInformation>(batch.map(file => ({ file })))));
+// runInAction(() => (this.completed += batch.length));
+// });
- await Promise.all(
- uploads.map(async response => {
- const {
- source: { type },
- result,
- } = response;
- if (result instanceof Error) {
- return;
- }
- const { accessPaths, exifData } = result;
- const path = Utils.prepend(accessPaths.agnostic.client);
- const document = type && (await DocUtils.DocumentFromType(type, path, { _width: 300 }));
- const { data, error } = exifData;
- if (document) {
- Doc.GetProto(document).exif = error || Doc.Get.FromJson({ data });
- docs.push(document);
- }
- })
- );
+// await Promise.all(
+// uploads.map(async response => {
+// const {
+// source: { mimetype },
+// result,
+// } = response;
+// if (result instanceof Error) {
+// return;
+// }
+// const { accessPaths, exifData } = result;
+// const path = Utils.prepend(accessPaths.agnostic.client);
+// const document = mimetype && (await DocUtils.DocumentFromType(mimetype, path, { _width: 300 }));
+// const { data, error } = exifData;
+// if (document) {
+// Doc.GetProto(document).exif = error || Doc.Get.FromJson({ data });
+// docs.push(document);
+// }
+// })
+// );
- for (let i = 0; i < docs.length; i++) {
- const doc = docs[i];
- doc.size = sizes[i];
- doc.modified = modifiedDates[i];
- this.entries.forEach(entry => {
- const target = entry.onDataDoc ? Doc.GetProto(doc) : doc;
- target[entry.key] = entry.value;
- });
- }
+// for (let i = 0; i < docs.length; i++) {
+// const doc = docs[i];
+// doc.size = sizes[i];
+// doc.modified = modifiedDates[i];
+// this.entries.forEach(entry => {
+// const target = entry.onDataDoc ? Doc.GetProto(doc) : doc;
+// target[entry.key] = entry.value;
+// });
+// }
- const doc = this.props.Document;
- const height: number = NumCast(doc.height) || 0;
- const offset: number = this.persistent ? (height === 0 ? 0 : height + 30) : 0;
- const options: DocumentOptions = {
- title: `Import of ${directory}`,
- _width: 1105,
- _height: 500,
- _chromeHidden: true,
- x: NumCast(doc.x),
- y: NumCast(doc.y) + offset,
- };
- const parent = this.props.DocumentView?.().props.docViewPath().lastElement();
- if (parent?.rootDoc.type === DocumentType.COL) {
- let importContainer: Doc;
- if (docs.length < 50) {
- importContainer = Docs.Create.MasonryDocument(docs, options);
- } else {
- const headers = [new SchemaHeaderField('title'), new SchemaHeaderField('size')];
- importContainer = Docs.Create.SchemaDocument(headers, docs, options);
- }
- runInAction(() => (this.phase = 'External: uploading files to Google Photos...'));
- await GooglePhotos.Export.CollectionToAlbum({ collection: importContainer });
- Doc.AddDocToList(Doc.GetProto(parent.props.Document), 'data', importContainer);
- !this.persistent && this.props.removeDocument && this.props.removeDocument(doc);
- DocumentManager.Instance.showDocument(importContainer, { willZoomCentered: true });
- }
+// const doc = this.props.Document;
+// const height: number = NumCast(doc.height) || 0;
+// const offset: number = this.persistent ? (height === 0 ? 0 : height + 30) : 0;
+// const options: DocumentOptions = {
+// title: `Import of ${directory}`,
+// _width: 1105,
+// _height: 500,
+// _chromeHidden: true,
+// x: NumCast(doc.x),
+// y: NumCast(doc.y) + offset,
+// };
+// const parent = this.props.DocumentView?.()._props.docViewPath().lastElement();
+// if (parent?.Document.type === DocumentType.COL) {
+// let importContainer: Doc;
+// if (docs.length < 50) {
+// importContainer = Docs.Create.MasonryDocument(docs, options);
+// } else {
+// const headers = [new SchemaHeaderField('title'), new SchemaHeaderField('size')];
+// importContainer = Docs.Create.SchemaDocument(headers, docs, options);
+// }
+// runInAction(() => (this.phase = 'External: uploading files to Google Photos...'));
+// await GooglePhotos.Export.CollectionToAlbum({ collection: importContainer });
+// Doc.AddDocToList(Doc.GetProto(parent.props.Document), 'data', importContainer);
+// !this.persistent && this.props.removeDocument && this.props.removeDocument(doc);
+// DocumentManager.Instance.showDocument(importContainer, { willZoomCentered: true });
+// }
- runInAction(() => {
- this.uploading = false;
- this.quota = 1;
- this.completed = 0;
- });
- };
+// runInAction(() => {
+// this.uploading = false;
+// this.quota = 1;
+// this.completed = 0;
+// });
+// };
- componentDidMount() {
- this.selector.current!.setAttribute('directory', '');
- this.selector.current!.setAttribute('webkitdirectory', '');
- this.disposer = reaction(
- () => this.completed,
- completed => runInAction(() => (this.phase = `Internal: uploading ${this.quota - completed} files to Dash...`))
- );
- }
+// componentDidMount() {
+// this.selector.current!.setAttribute('directory', '');
+// this.selector.current!.setAttribute('webkitdirectory', '');
+// this.disposer = reaction(
+// () => this.completed,
+// completed => runInAction(() => (this.phase = `Internal: uploading ${this.quota - completed} files to Dash...`))
+// );
+// }
- componentWillUnmount() {
- this.disposer && this.disposer();
- }
+// componentWillUnmount() {
+// this.disposer && this.disposer();
+// }
- @action
- preserveCentering = (rect: ContentRect) => {
- const bounds = rect.offset!;
- if (bounds.width === 0 || bounds.height === 0) {
- return;
- }
- const offset = this.dimensions / 2;
- this.left = bounds.width / 2 - offset;
- this.top = bounds.height / 2 - offset;
- };
+// @action
+// preserveCentering = (rect: ContentRect) => {
+// const bounds = rect.offset!;
+// if (bounds.width === 0 || bounds.height === 0) {
+// return;
+// }
+// const offset = this.dimensions / 2;
+// this.left = bounds.width / 2 - offset;
+// this.top = bounds.height / 2 - offset;
+// };
- @action
- addMetadataEntry = async () => {
- const entryDoc = new Doc();
- entryDoc.checked = false;
- entryDoc.key = keyPlaceholder;
- entryDoc.value = valuePlaceholder;
- Doc.AddDocToList(this.props.Document, 'data', entryDoc);
- };
+// @action
+// addMetadataEntry = async () => {
+// const entryDoc = new Doc();
+// entryDoc.checked = false;
+// entryDoc.key = keyPlaceholder;
+// entryDoc.value = valuePlaceholder;
+// Doc.AddDocToList(this.props.Document, 'data', entryDoc);
+// };
- @action
- remove = async (entry: ImportMetadataEntry) => {
- const metadata = await DocListCastAsync(this.props.Document.data);
- if (metadata) {
- let index = this.entries.indexOf(entry);
- if (index !== -1) {
- runInAction(() => this.entries.splice(index, 1));
- index = metadata.indexOf(entry.props.Document);
- if (index !== -1) {
- metadata.splice(index, 1);
- }
- }
- }
- };
+// @action
+// remove = async (entry: ImportMetadataEntry) => {
+// const metadata = await DocListCastAsync(this.props.Document.data);
+// if (metadata) {
+// let index = this.entries.indexOf(entry);
+// if (index !== -1) {
+// runInAction(() => this.entries.splice(index, 1));
+// index = metadata.indexOf(entry.props.Document);
+// if (index !== -1) {
+// metadata.splice(index, 1);
+// }
+// }
+// }
+// };
- render() {
- const dimensions = 50;
- const entries = DocListCast(this.props.Document.data);
- const isEditing = this.editingMetadata;
- const completed = this.completed;
- const quota = this.quota;
- const uploading = this.uploading;
- const showRemoveLabel = this.removeHover;
- const persistent = this.persistent;
- let percent = `${(completed / quota) * 100}`;
- percent = percent.split('.')[0];
- percent = percent.startsWith('100') ? '99' : percent;
- const marginOffset = (percent.length === 1 ? 5 : 0) - 1.6;
- const message = <span className={'phase'}>{this.phase}</span>;
- const centerPiece = this.phase.includes('Google Photos') ? (
- <img
- src={'/assets/google_photos.png'}
- style={{
- transition: '0.4s opacity ease',
- width: 30,
- height: 30,
- opacity: uploading ? 1 : 0,
- pointerEvents: 'none',
- position: 'absolute',
- left: 12,
- top: this.top + 10,
- fontSize: 18,
- color: 'white',
- marginLeft: this.left + marginOffset,
- }}
- />
- ) : (
- <div
- style={{
- transition: '0.4s opacity ease',
- opacity: uploading ? 1 : 0,
- pointerEvents: 'none',
- position: 'absolute',
- left: 10,
- top: this.top + 12.3,
- fontSize: 18,
- color: 'white',
- marginLeft: this.left + marginOffset,
- }}>
- {percent}%
- </div>
- );
- return (
- <Measure offset onResize={this.preserveCentering}>
- {({ measureRef }) => (
- <div ref={measureRef} style={{ width: '100%', height: '100%', pointerEvents: 'all' }}>
- {message}
- <input
- id={'selector'}
- ref={this.selector}
- onChange={this.handleSelection}
- type="file"
- style={{
- position: 'absolute',
- display: 'none',
- }}
- />
- <label
- htmlFor={'selector'}
- style={{
- opacity: isEditing ? 0 : 1,
- pointerEvents: isEditing ? 'none' : 'all',
- transition: '0.4s ease opacity',
- }}>
- <div
- style={{
- width: dimensions,
- height: dimensions,
- borderRadius: '50%',
- background: 'black',
- position: 'absolute',
- left: this.left,
- top: this.top,
- }}
- />
- <div
- style={{
- position: 'absolute',
- left: this.left + 8,
- top: this.top + 10,
- opacity: uploading ? 0 : 1,
- transition: '0.4s opacity ease',
- }}>
- <FontAwesomeIcon icon={'cloud-upload-alt'} color="#FFFFFF" size={'2x'} />
- </div>
- <img
- style={{
- width: 80,
- height: 80,
- transition: '0.4s opacity ease',
- opacity: uploading ? 0.7 : 0,
- position: 'absolute',
- top: this.top - 15,
- left: this.left - 15,
- }}
- src={'/assets/loading.gif'}></img>
- </label>
- <input
- type={'checkbox'}
- onChange={e => runInAction(() => (this.persistent = e.target.checked))}
- style={{
- margin: 0,
- position: 'absolute',
- left: 10,
- bottom: 10,
- opacity: isEditing || uploading ? 0 : 1,
- transition: '0.4s opacity ease',
- pointerEvents: isEditing || uploading ? 'none' : 'all',
- }}
- checked={this.persistent}
- onPointerEnter={action(() => (this.removeHover = true))}
- onPointerLeave={action(() => (this.removeHover = false))}
- />
- <p
- style={{
- position: 'absolute',
- left: 27,
- bottom: 8.4,
- fontSize: 12,
- opacity: showRemoveLabel ? 1 : 0,
- transition: '0.4s opacity ease',
- }}>
- Template will be <span style={{ textDecoration: 'underline', textDecorationColor: persistent ? 'green' : 'red', color: persistent ? 'green' : 'red' }}>{persistent ? 'kept' : 'removed'}</span> after upload
- </p>
- {centerPiece}
- <div
- style={{
- position: 'absolute',
- top: 10,
- right: 10,
- borderRadius: '50%',
- width: 25,
- height: 25,
- background: 'black',
- pointerEvents: uploading ? 'none' : 'all',
- opacity: uploading ? 0 : 1,
- transition: '0.4s opacity ease',
- }}
- title={isEditing ? 'Back to Upload' : 'Add Metadata'}
- onClick={action(() => (this.editingMetadata = !this.editingMetadata))}
- />
- <FontAwesomeIcon
- style={{
- pointerEvents: 'none',
- position: 'absolute',
- right: isEditing ? 14 : 15,
- top: isEditing ? 15.4 : 16,
- opacity: uploading ? 0 : 1,
- transition: '0.4s opacity ease',
- }}
- icon={isEditing ? 'cloud-upload-alt' : 'tag'}
- color="#FFFFFF"
- size={'1x'}
- />
- <div
- style={{
- transition: '0.4s ease opacity',
- width: '100%',
- height: '100%',
- pointerEvents: isEditing ? 'all' : 'none',
- opacity: isEditing ? 1 : 0,
- overflowY: 'scroll',
- }}>
- <div
- style={{
- borderRadius: '50%',
- width: 25,
- height: 25,
- marginLeft: 10,
- position: 'absolute',
- right: 41,
- top: 10,
- }}
- title={'Add Metadata Entry'}
- onClick={this.addMetadataEntry}>
- <FontAwesomeIcon
- style={{
- pointerEvents: 'none',
- marginLeft: 6.4,
- marginTop: 5.2,
- }}
- icon={'plus'}
- size={'1x'}
- />
- </div>
- <p style={{ paddingLeft: 10, paddingTop: 8, paddingBottom: 7 }}>Add metadata to your import...</p>
- <hr style={{ margin: '6px 10px 12px 10px' }} />
- {entries.map(doc => (
- <ImportMetadataEntry
- Document={doc}
- key={doc[Id]}
- remove={this.remove}
- ref={el => {
- if (el) this.entries.push(el);
- }}
- next={this.addMetadataEntry}
- />
- ))}
- </div>
- </div>
- )}
- </Measure>
- );
- }
-}
+// render() {
+// const dimensions = 50;
+// const entries = DocListCast(this.props.Document.data);
+// const isEditing = this.editingMetadata;
+// const completed = this.completed;
+// const quota = this.quota;
+// const uploading = this.uploading;
+// const showRemoveLabel = this.removeHover;
+// const persistent = this.persistent;
+// let percent = `${(completed / quota) * 100}`;
+// percent = percent.split('.')[0];
+// percent = percent.startsWith('100') ? '99' : percent;
+// const marginOffset = (percent.length === 1 ? 5 : 0) - 1.6;
+// const message = <span className={'phase'}>{this.phase}</span>;
+// const centerPiece = this.phase.includes('Google Photos') ? (
+// <img
+// src={'/assets/google_photos.png'}
+// style={{
+// transition: '0.4s opacity ease',
+// width: 30,
+// height: 30,
+// opacity: uploading ? 1 : 0,
+// pointerEvents: 'none',
+// position: 'absolute',
+// left: 12,
+// top: this.top + 10,
+// fontSize: 18,
+// color: 'white',
+// marginLeft: this.left + marginOffset,
+// }}
+// />
+// ) : (
+// <div
+// style={{
+// transition: '0.4s opacity ease',
+// opacity: uploading ? 1 : 0,
+// pointerEvents: 'none',
+// position: 'absolute',
+// left: 10,
+// top: this.top + 12.3,
+// fontSize: 18,
+// color: 'white',
+// marginLeft: this.left + marginOffset,
+// }}>
+// {percent}%
+// </div>
+// );
+// return (
+// <Measure offset onResize={this.preserveCentering}>
+// {({ measureRef }) => (
+// <div ref={measureRef} style={{ width: '100%', height: '100%', pointerEvents: 'all' }}>
+// {message}
+// <input
+// id={'selector'}
+// ref={this.selector}
+// onChange={this.handleSelection}
+// type="file"
+// style={{
+// position: 'absolute',
+// display: 'none',
+// }}
+// />
+// <label
+// htmlFor={'selector'}
+// style={{
+// opacity: isEditing ? 0 : 1,
+// pointerEvents: isEditing ? 'none' : 'all',
+// transition: '0.4s ease opacity',
+// }}>
+// <div
+// style={{
+// width: dimensions,
+// height: dimensions,
+// borderRadius: '50%',
+// background: 'black',
+// position: 'absolute',
+// left: this.left,
+// top: this.top,
+// }}
+// />
+// <div
+// style={{
+// position: 'absolute',
+// left: this.left + 8,
+// top: this.top + 10,
+// opacity: uploading ? 0 : 1,
+// transition: '0.4s opacity ease',
+// }}>
+// <FontAwesomeIcon icon={'cloud-upload-alt'} color="#FFFFFF" size={'2x'} />
+// </div>
+// <img
+// style={{
+// width: 80,
+// height: 80,
+// transition: '0.4s opacity ease',
+// opacity: uploading ? 0.7 : 0,
+// position: 'absolute',
+// top: this.top - 15,
+// left: this.left - 15,
+// }}
+// src={'/assets/loading.gif'}></img>
+// </label>
+// <input
+// type={'checkbox'}
+// onChange={e => runInAction(() => (this.persistent = e.target.checked))}
+// style={{
+// margin: 0,
+// position: 'absolute',
+// left: 10,
+// bottom: 10,
+// opacity: isEditing || uploading ? 0 : 1,
+// transition: '0.4s opacity ease',
+// pointerEvents: isEditing || uploading ? 'none' : 'all',
+// }}
+// checked={this.persistent}
+// onPointerEnter={action(() => (this.removeHover = true))}
+// onPointerLeave={action(() => (this.removeHover = false))}
+// />
+// <p
+// style={{
+// position: 'absolute',
+// left: 27,
+// bottom: 8.4,
+// fontSize: 12,
+// opacity: showRemoveLabel ? 1 : 0,
+// transition: '0.4s opacity ease',
+// }}>
+// Template will be <span style={{ textDecoration: 'underline', textDecorationColor: persistent ? 'green' : 'red', color: persistent ? 'green' : 'red' }}>{persistent ? 'kept' : 'removed'}</span> after upload
+// </p>
+// {centerPiece}
+// <div
+// style={{
+// position: 'absolute',
+// top: 10,
+// right: 10,
+// borderRadius: '50%',
+// width: 25,
+// height: 25,
+// background: 'black',
+// pointerEvents: uploading ? 'none' : 'all',
+// opacity: uploading ? 0 : 1,
+// transition: '0.4s opacity ease',
+// }}
+// title={isEditing ? 'Back to Upload' : 'Add Metadata'}
+// onClick={action(() => (this.editingMetadata = !this.editingMetadata))}
+// />
+// <FontAwesomeIcon
+// style={{
+// pointerEvents: 'none',
+// position: 'absolute',
+// right: isEditing ? 14 : 15,
+// top: isEditing ? 15.4 : 16,
+// opacity: uploading ? 0 : 1,
+// transition: '0.4s opacity ease',
+// }}
+// icon={isEditing ? 'cloud-upload-alt' : 'tag'}
+// color="#FFFFFF"
+// size={'1x'}
+// />
+// <div
+// style={{
+// transition: '0.4s ease opacity',
+// width: '100%',
+// height: '100%',
+// pointerEvents: isEditing ? 'all' : 'none',
+// opacity: isEditing ? 1 : 0,
+// overflowY: 'scroll',
+// }}>
+// <div
+// style={{
+// borderRadius: '50%',
+// width: 25,
+// height: 25,
+// marginLeft: 10,
+// position: 'absolute',
+// right: 41,
+// top: 10,
+// }}
+// title={'Add Metadata Entry'}
+// onClick={this.addMetadataEntry}>
+// <FontAwesomeIcon
+// style={{
+// pointerEvents: 'none',
+// marginLeft: 6.4,
+// marginTop: 5.2,
+// }}
+// icon={'plus'}
+// size={'1x'}
+// />
+// </div>
+// <p style={{ paddingLeft: 10, paddingTop: 8, paddingBottom: 7 }}>Add metadata to your import...</p>
+// <hr style={{ margin: '6px 10px 12px 10px' }} />
+// {entries.map(doc => (
+// <ImportMetadataEntry
+// Document={doc}
+// key={doc[Id]}
+// remove={this.remove}
+// ref={el => {
+// if (el) this.entries.push(el);
+// }}
+// next={this.addMetadataEntry}
+// />
+// ))}
+// </div>
+// </div>
+// )}
+// </Measure>
+// );
+// }
+// }
diff --git a/src/client/util/Import & Export/ImportMetadataEntry.tsx b/src/client/util/Import & Export/ImportMetadataEntry.tsx
index 45d8c0c63..58a09b9c9 100644
--- a/src/client/util/Import & Export/ImportMetadataEntry.tsx
+++ b/src/client/util/Import & Export/ImportMetadataEntry.tsx
@@ -1,10 +1,10 @@
-import React = require("react");
-import { observer } from "mobx-react";
-import { EditableView } from "../../views/EditableView";
-import { action, computed } from "mobx";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Doc } from "../../../fields/Doc";
-import { StrCast, BoolCast } from "../../../fields/Types";
+import * as React from 'react';
+import { observer } from 'mobx-react';
+import { EditableView } from '../../views/EditableView';
+import { action, computed } from 'mobx';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Doc } from '../../../fields/Doc';
+import { StrCast, BoolCast } from '../../../fields/Types';
interface KeyValueProps {
Document: Doc;
@@ -12,19 +12,18 @@ interface KeyValueProps {
next: () => void;
}
-export const keyPlaceholder = "Key";
-export const valuePlaceholder = "Value";
+export const keyPlaceholder = 'Key';
+export const valuePlaceholder = 'Value';
@observer
export default class ImportMetadataEntry extends React.Component<KeyValueProps> {
-
private keyRef = React.createRef<EditableView>();
private valueRef = React.createRef<EditableView>();
private checkRef = React.createRef<HTMLInputElement>();
@computed
public get valid() {
- return (this.key.length > 0 && this.key !== keyPlaceholder) && (this.value.length > 0 && this.value !== valuePlaceholder);
+ return this.key.length > 0 && this.key !== keyPlaceholder && this.value.length > 0 && this.value !== valuePlaceholder;
}
@computed
@@ -66,7 +65,7 @@ export default class ImportMetadataEntry extends React.Component<KeyValueProps>
this.valueRef.current && this.valueRef.current.setIsFocused(true);
this.key.length === 0 && (this.key = keyPlaceholder);
return true;
- }
+ };
@action
updateValue = (newValue: string, shiftDown: boolean) => {
@@ -75,68 +74,45 @@ export default class ImportMetadataEntry extends React.Component<KeyValueProps>
this.value.length > 0 && shiftDown && this.props.next();
this.value.length === 0 && (this.value = valuePlaceholder);
return true;
- }
+ };
render() {
const keyValueStyle: React.CSSProperties = {
paddingLeft: 10,
- width: "50%",
+ width: '50%',
opacity: this.valid ? 1 : 0.5,
};
return (
<div
style={{
- display: "flex",
- flexDirection: "row",
+ display: 'flex',
+ flexDirection: 'row',
paddingBottom: 5,
paddingRight: 5,
- justifyContent: "center",
- alignItems: "center",
- alignContent: "center"
- }}
- >
- <input
- onChange={e => this.onDataDoc = e.target.checked}
- ref={this.checkRef}
- style={{ margin: "0 10px 0 15px" }}
- type="checkbox"
- title={"Add to Data Document?"}
- checked={this.onDataDoc}
- />
- <div className={"key_container"} style={keyValueStyle}>
- <EditableView
- ref={this.keyRef}
- contents={this.key}
- SetValue={this.updateKey}
- GetValue={() => ""}
- oneLine={true}
- />
+ justifyContent: 'center',
+ alignItems: 'center',
+ alignContent: 'center',
+ }}>
+ <input onChange={e => (this.onDataDoc = e.target.checked)} ref={this.checkRef} style={{ margin: '0 10px 0 15px' }} type="checkbox" title={'Add to Data Document?'} checked={this.onDataDoc} />
+ <div className={'key_container'} style={keyValueStyle}>
+ <EditableView ref={this.keyRef} contents={this.key} SetValue={this.updateKey} GetValue={() => ''} oneLine={true} />
</div>
- <div
- className={"value_container"}
- style={keyValueStyle}>
- <EditableView
- ref={this.valueRef}
- contents={this.value}
- SetValue={this.updateValue}
- GetValue={() => ""}
- oneLine={true}
- />
+ <div className={'value_container'} style={keyValueStyle}>
+ <EditableView ref={this.valueRef} contents={this.value} SetValue={this.updateValue} GetValue={() => ''} oneLine={true} />
</div>
- <div onClick={() => this.props.remove(this)} title={"Delete Entry"}>
+ <div onClick={() => this.props.remove(this)} title={'Delete Entry'}>
<FontAwesomeIcon
- icon={"plus"}
- color={"red"}
- size={"1x"}
+ icon={'plus'}
+ color={'red'}
+ size={'1x'}
style={{
marginLeft: 15,
marginRight: 15,
- transform: "rotate(45deg)"
+ transform: 'rotate(45deg)',
}}
/>
</div>
</div>
);
}
-
-} \ No newline at end of file
+}
diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx
index be885312d..a2f5826fe 100644
--- a/src/client/util/InteractionUtils.tsx
+++ b/src/client/util/InteractionUtils.tsx
@@ -1,4 +1,4 @@
-import React = require('react');
+import * as React from 'react';
import { GestureUtils } from '../../pen-gestures/GestureUtils';
import { Utils } from '../../Utils';
import './InteractionUtils.scss';
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 608184596..ccb3c6b98 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -1,4 +1,4 @@
-import { action, observable, observe, runInAction } from 'mobx';
+import { action, makeObservable, observable, observe, runInAction } from 'mobx';
import { computedFn } from 'mobx-utils';
import { Doc, DocListCast, DocListCastAsync, Field, Opt } from '../../fields/Doc';
import { DirectLinks } from '../../fields/DocSymbols';
@@ -22,9 +22,9 @@ import { ScriptingGlobals } from './ScriptingGlobals';
*/
export class LinkManager {
@observable static _instance: LinkManager;
- @observable static userLinkDBs: Doc[] = [];
- @observable public static currentLink: Opt<Doc>;
- @observable public static currentLinkAnchor: Opt<Doc>;
+ @observable.shallow userLinkDBs: Doc[] = [];
+ @observable public static currentLink: Opt<Doc> = undefined;
+ @observable public static currentLinkAnchor: Opt<Doc> = undefined;
public static get Instance() {
return LinkManager._instance;
}
@@ -32,21 +32,20 @@ export class LinkManager {
public static Links(doc: Doc | undefined) {
return doc ? LinkManager.Instance.getAllRelatedLinks(doc) : [];
}
- public static addLinkDB = async (linkDb: any) => {
+ public addLinkDB = async (linkDb: any) => {
await Promise.all(
((await DocListCastAsync(linkDb.data)) ?? []).map(link =>
// makes sure link anchors are loaded to avoid incremental updates to computedFns in LinkManager
[PromiseValue(link?.link_anchor_1), PromiseValue(link?.link_anchor_2)]
)
);
- LinkManager.userLinkDBs.push(linkDb);
+ this.userLinkDBs.push(linkDb);
};
public static AutoKeywords = 'keywords:Usages';
- static _links: Doc[] = [];
constructor() {
+ makeObservable(this);
LinkManager._instance = this;
this.createlink_relationshipLists();
- LinkManager.userLinkDBs = [];
// since this is an action, not a reaction, we get only one shot to add this link to the Anchor docs
// Thus make sure all promised values are resolved from link -> link.proto -> link.link_anchor_[1,2] -> link.link_anchor_[1,2].proto
// Then add the link to the anchor protos.
@@ -85,7 +84,6 @@ export class LinkManager {
);
const watchUserLinkDB = (userLinkDBDoc: Doc) => {
- LinkManager._links.push(...DocListCast(userLinkDBDoc.data));
const toRealField = (field: Field) => (field instanceof ProxyField ? field.value : field); // see List.ts. data structure is not a simple list of Docs, but a list of ProxyField/Fields
if (userLinkDBDoc.data) {
observe(
@@ -124,7 +122,7 @@ export class LinkManager {
}
};
observe(
- LinkManager.userLinkDBs,
+ this.userLinkDBs,
change => {
switch (change.type as any) {
case 'splice':
@@ -135,8 +133,8 @@ export class LinkManager {
},
true
);
- runInAction(() => (FieldLoader.ServerLoadStatus.message = 'links'));
- LinkManager.addLinkDB(Doc.LinkDBDoc());
+ FieldLoader.ServerLoadStatus.message = 'links';
+ this.addLinkDB(Doc.LinkDBDoc());
}
public createlink_relationshipLists = () => {
@@ -163,8 +161,8 @@ export class LinkManager {
public getAllRelatedLinks(anchor: Doc) {
return this.relatedLinker(anchor);
} // finds all links that contain the given anchor
- public getAllDirectLinks(anchor: Doc): Doc[] {
- return Array.from(Doc.GetProto(anchor)[DirectLinks]);
+ public getAllDirectLinks(anchor?: Doc): Doc[] {
+ return anchor ? Array.from(Doc.GetProto(anchor)[DirectLinks]) : [];
} // finds all links that contain the given anchor
relatedLinker = computedFn(function relatedLinker(this: any, anchor: Doc): Doc[] {
diff --git a/src/client/util/PingManager.ts b/src/client/util/PingManager.ts
index 4dd2fcd35..865f8bc02 100644
--- a/src/client/util/PingManager.ts
+++ b/src/client/util/PingManager.ts
@@ -1,4 +1,4 @@
-import { action, observable, runInAction } from 'mobx';
+import { action, makeObservable, observable, runInAction } from 'mobx';
import { Networking } from '../Network';
import { CurrentUserUtils } from './CurrentUserUtils';
export class PingManager {
@@ -33,6 +33,7 @@ export class PingManager {
private _interval: NodeJS.Timeout | null = null;
INTERVAL_SECONDS = 1;
constructor() {
+ makeObservable(this);
PingManager._instance = this;
this._interval = setInterval(this.sendPing, this.INTERVAL_SECONDS * 1000);
}
diff --git a/src/client/util/RTFMarkup.tsx b/src/client/util/RTFMarkup.tsx
index c8940194c..f96d8a5df 100644
--- a/src/client/util/RTFMarkup.tsx
+++ b/src/client/util/RTFMarkup.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable } from 'mobx';
+import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { MainViewModal } from '../views/MainViewModal';
@@ -23,10 +23,11 @@ export class RTFMarkup extends React.Component<{}> {
constructor(props: {}) {
super(props);
+ makeObservable(this);
RTFMarkup.Instance = this;
}
- @observable _stats: { [key: string]: any } | undefined;
+ @observable _stats: { [key: string]: any } | undefined = undefined;
/**
* @returns the main interface of the SharingManager.
diff --git a/src/client/util/ReplayMovements.ts b/src/client/util/ReplayMovements.ts
index d99630f82..b881f18b4 100644
--- a/src/client/util/ReplayMovements.ts
+++ b/src/client/util/ReplayMovements.ts
@@ -1,4 +1,4 @@
-import { IReactionDisposer, observable, reaction } from 'mobx';
+import { IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { Doc, IdToDoc } from '../../fields/Doc';
import { CollectionDockingView } from '../views/collections/CollectionDockingView';
import { CollectionFreeFormView } from '../views/collections/collectionFreeForm';
@@ -19,6 +19,7 @@ export class ReplayMovements {
return ReplayMovements._instance;
}
constructor() {
+ makeObservable(this);
// init the global instance
ReplayMovements._instance = this;
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index 400b63a1c..dbb994dbd 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -120,6 +120,7 @@ class ScriptingCompilerHost {
}
return undefined;
}
+
// getDefaultLibFileName(options: ts.CompilerOptions): string {
getDefaultLibFileName(options: any): string {
return 'node_modules/typescript/lib/lib.d.ts'; // No idea what this means...
@@ -159,7 +160,7 @@ class ScriptingCompilerHost {
export type Traverser = (node: ts.Node, indentation: string) => boolean | void;
export type TraverserParam = Traverser | { onEnter: Traverser; onLeave: Traverser };
export type Transformer = {
- transformer: ts.TransformerFactory<ts.SourceFile>;
+ transformer: ts.TransformerFactory<ts.Node>;
getVars?: () => { [name: string]: Field };
};
export interface ScriptOptions {
@@ -219,7 +220,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp
const printer = ts.createPrinter({
newLine: ts.NewLineKind.LineFeed,
});
- script = printer.printFile(transformed[0]);
+ script = printer.printFile(transformed[0].getSourceFile());
}
result.dispose();
}
@@ -247,7 +248,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/ScrollBox.tsx b/src/client/util/ScrollBox.tsx
index d4620ae3f..785526ab3 100644
--- a/src/client/util/ScrollBox.tsx
+++ b/src/client/util/ScrollBox.tsx
@@ -1,4 +1,4 @@
-import React = require('react');
+import * as React from 'react';
export class ScrollBox extends React.Component<React.PropsWithChildren<{}>> {
onWheel = (e: React.WheelEvent) => {
diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts
index 560d6b30f..e51770c25 100644
--- a/src/client/util/SearchUtil.ts
+++ b/src/client/util/SearchUtil.ts
@@ -9,7 +9,7 @@ import { StrCast } from '../../fields/Types';
export namespace SearchUtil {
export type HighlightingResult = { [id: string]: { [key: string]: string[] } };
- export function SearchCollection(rootDoc: Opt<Doc>, query: string) {
+ export function SearchCollection(collectionDoc: Opt<Doc>, query: string) {
const blockedTypes = [DocumentType.PRESELEMENT, DocumentType.CONFIG, DocumentType.KVP, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING];
const blockedKeys = [
'x',
@@ -48,8 +48,8 @@ export namespace SearchUtil {
query = query.toLowerCase();
const results = new Map<Doc, string[]>();
- if (rootDoc) {
- const docs = DocListCast(rootDoc[Doc.LayoutFieldKey(rootDoc)]);
+ if (collectionDoc) {
+ const docs = DocListCast(collectionDoc[Doc.LayoutFieldKey(collectionDoc)]);
const docIDs: String[] = [];
SearchUtil.foreachRecursiveDoc(docs, (depth: number, doc: Doc) => {
const dtype = StrCast(doc.type) as DocumentType;
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index f7e6fa2dc..07bbde36c 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -1,4 +1,4 @@
-import { action, 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';
@@ -10,86 +10,70 @@ import { LinkManager } from './LinkManager';
import { ScriptingGlobals } from './ScriptingGlobals';
import { UndoManager } from './UndoManager';
-export namespace SelectionManager {
- class Manager {
- @observable SelectedViews: DocumentView[] = [];
- @observable IsDragging: boolean = false;
- @observable SelectedSchemaDocument: Doc | undefined;
-
- @action
- SelectSchemaViewDoc(doc: Opt<Doc>) {
- manager.SelectedSchemaDocument = doc;
- }
- @action
- SelectView(docView: DocumentView, extendSelection: boolean): void {
- if (!docView.SELECTED) {
- if (!extendSelection) this.DeselectAll();
- manager.SelectedViews.push(docView);
- docView.SELECTED = true;
- docView.props.whenChildContentsActiveChanged(true);
- }
- }
- @action
- DeselectView(docView?: DocumentView): void {
- if (docView && manager.SelectedViews.includes(docView)) {
- docView.SELECTED = false;
- manager.SelectedViews.splice(manager.SelectedViews.indexOf(docView), 1);
- docView.props.whenChildContentsActiveChanged(false);
- }
- }
- @action
- DeselectAll(): void {
- LinkManager.currentLink = undefined;
- LinkManager.currentLinkAnchor = undefined;
- manager.SelectedSchemaDocument = undefined;
- manager.SelectedViews.forEach(dv => {
- dv.SELECTED = false;
- dv.props.whenChildContentsActiveChanged(false);
- });
- manager.SelectedViews.length = 0;
- }
+export class SelectionManager {
+ private static _manager: SelectionManager;
+ private static get Instance() {
+ return SelectionManager._manager ?? new SelectionManager();
}
- const manager = new Manager();
+ @observable.shallow SelectedViews: DocumentView[] = [];
+ @observable IsDragging: boolean = false;
+ @observable SelectedSchemaDocument: Doc | undefined = undefined;
- export function DeselectView(docView?: DocumentView): void {
- manager.DeselectView(docView);
- }
- export function SelectView(docView: DocumentView | undefined, ctrlPressed: boolean): void {
- if (!docView) DeselectAll();
- else manager.SelectView(docView, ctrlPressed);
- }
- export function SelectSchemaViewDoc(document: Opt<Doc>, deselectAllFirst?: boolean): void {
- if (deselectAllFirst) manager.DeselectAll();
- manager.SelectSchemaViewDoc(document);
+ private constructor() {
+ SelectionManager._manager = this;
+ makeObservable(this);
}
- export function IsSelected(doc?: Doc): boolean {
- return Array.from(doc?.[DocViews] ?? []).some(dv => dv?.SELECTED);
- }
+ @action
+ public static SelectSchemaViewDoc = (doc: Opt<Doc>, deselectAllFirst?: boolean) => {
+ if (deselectAllFirst) this.DeselectAll();
+ this.Instance.SelectedSchemaDocument = doc;
+ };
- export function DeselectAll(except?: Doc): void {
- const found = manager.SelectedViews.find(dv => dv.Document === except);
- manager.DeselectAll();
- if (found) manager.SelectView(found, false);
- }
+ public static SelectView = action((docView: DocumentView | undefined, extendSelection: boolean): void => {
+ if (!docView) this.DeselectAll();
+ else if (!docView.SELECTED) {
+ if (!extendSelection) this.DeselectAll();
+ this.Instance.SelectedViews.push(docView);
+ docView.SELECTED = true;
+ docView._props.whenChildContentsActiveChanged(true);
+ }
+ });
- export function Views(): Array<DocumentView> {
- return manager.SelectedViews;
- }
- export function SelectedSchemaDoc(): Doc | undefined {
- return manager.SelectedSchemaDocument;
- }
- export function Docs(): Doc[] {
- return manager.SelectedViews.map(dv => dv.rootDoc).filter(doc => doc?._type_collection !== CollectionViewType.Docking);
- }
+ public static DeselectView = action((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);
+ }
+ });
+
+ public static DeselectAll = (except?: Doc): void => {
+ const found = this.Instance.SelectedViews.find(dv => dv.Document === except);
+ LinkManager.currentLink = undefined;
+ LinkManager.currentLinkAnchor = 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
+ public static get SelectedSchemaDoc() { return this.Instance.SelectedSchemaDocument; } // prettier-ignore
+ public static get Docs() { return this.Instance.SelectedViews.map(dv => dv.Document).filter(doc => doc?._type_collection !== CollectionViewType.Docking); } // prettier-ignore
}
+
ScriptingGlobals.add(function SelectionManager_selectedDocType(type: string, expertMode: boolean, checkContext?: boolean) {
if (Doc.noviceMode && expertMode) return false;
if (type === 'tab') {
- return SelectionManager.Views().lastElement()?.props.renderDepth === 0;
+ return SelectionManager.Views.lastElement()?._props.renderDepth === 0;
}
- let selected = (sel => (checkContext ? DocCast(sel?.embedContainer) : sel))(SelectionManager.SelectedSchemaDoc() ?? SelectionManager.Docs().lastElement());
+ let selected = (sel => (checkContext ? DocCast(sel?.embedContainer) : sel))(SelectionManager.SelectedSchemaDoc ?? SelectionManager.Docs.lastElement());
return selected?.type === type || selected?.type_collection === type || !type;
});
ScriptingGlobals.add(function deselectAll() {
@@ -114,8 +98,8 @@ ScriptingGlobals.add(function redo() {
return UndoManager.Redo();
});
ScriptingGlobals.add(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) {
- const docs = SelectionManager.Views()
- .map(dv => dv.props.Document)
- .filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.KVP && (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null)));
+ const docs = SelectionManager.Views.map(dv => dv.Document).filter(
+ d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.KVP && (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null))
+ );
return docs.length ? new List(docs) : prevValue;
});
diff --git a/src/client/util/SerializationHelper.ts b/src/client/util/SerializationHelper.ts
index 76037a7e9..8daa69890 100644
--- a/src/client/util/SerializationHelper.ts
+++ b/src/client/util/SerializationHelper.ts
@@ -1,6 +1,5 @@
import { PropSchema, serialize, deserialize, custom, setDefaultModelSchema, getDefaultModelSchema } from 'serializr';
import { Field } from '../../fields/Doc';
-import { ClientUtils } from './ClientUtils';
let serializing = 0;
export function afterDocDeserialize(cb: (err: any, val: any) => void, err: any, newValue: any) {
diff --git a/src/client/util/ServerStats.tsx b/src/client/util/ServerStats.tsx
index 08dbaac5d..c8df9182d 100644
--- a/src/client/util/ServerStats.tsx
+++ b/src/client/util/ServerStats.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable } from 'mobx';
+import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { MainViewModal } from '../views/MainViewModal';
@@ -33,10 +33,11 @@ export class ServerStats extends React.Component<{}> {
constructor(props: {}) {
super(props);
+ makeObservable(this);
ServerStats.Instance = this;
}
- @observable _stats: { [key: string]: any } | undefined;
+ @observable _stats: { [key: string]: any } | undefined = undefined;
/**
* @returns the main interface of the SharingManager.
@@ -56,9 +57,7 @@ export class ServerStats extends React.Component<{}> {
<br />
<span>Active users:{this._stats?.socketMap.length}</span>
- {this._stats?.socketMap.map((user: any) => (
- <p>{user.username}</p>
- ))}
+ {this._stats?.socketMap.map((user: any) => <p>{user.username}</p>)}
</div>
</div>
);
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/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index 39c471970..ccf6fb820 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -1,6 +1,6 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Button, ColorPicker, Dropdown, DropdownType, EditableText, Group, NumberDropdown, Size, Toggle, ToggleType, Type } from 'browndash-components';
-import { action, computed, observable, runInAction } from 'mobx';
+import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { BsGoogle } from 'react-icons/bs';
@@ -45,11 +45,12 @@ export class SettingsManager extends React.Component<{}> {
@observable private new_confirm = '';
@observable activeTab = 'Accounts';
- @observable public static propertiesWidth: number = 0;
- @observable public static headerBarHeight: number = 0;
+ @observable public propertiesWidth: number = 0;
+ @observable public headerBarHeight: number = 0;
constructor(props: {}) {
super(props);
+ makeObservable(this);
SettingsManager.Instance = this;
this.matchSystem();
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
@@ -116,7 +117,6 @@ export class SettingsManager extends React.Component<{}> {
});
@undoBatch
- @action
changeColorScheme = action((scheme: string) => {
Doc.UserDoc().userTheme = scheme;
switch (scheme) {
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 8d59426ec..ac7de9872 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -1,7 +1,7 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Button, IconButton, Size, Type } from 'browndash-components';
import { concat, intersection } from 'lodash';
-import { action, computed, observable, runInAction } from 'mobx';
+import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import Select from 'react-select';
@@ -67,8 +67,8 @@ export class SharingManager extends React.Component<{}> {
public static Instance: SharingManager;
@observable private isOpen = false; // whether the SharingManager modal is open or not
@observable public users: ValidatedUser[] = []; // the list of users with sharing docs
- @observable private targetDoc: Doc | undefined; // the document being shared
- @observable private targetDocView: DocumentView | undefined; // the DocumentView of the document being shared
+ @observable private targetDoc: Doc | undefined = undefined; // the document being shared
+ @observable private targetDocView: DocumentView | undefined = undefined; // the DocumentView of the document being shared
// @observable private copied = false;
@observable private dialogueBoxOpacity = 1; // for the modal
@observable private overlayOpacity = 0.4; // for the modal
@@ -119,6 +119,7 @@ export class SharingManager extends React.Component<{}> {
constructor(props: {}) {
super(props);
+ makeObservable(this);
SharingManager.Instance = this;
}
@@ -133,7 +134,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);
@@ -162,7 +163,7 @@ export class SharingManager extends React.Component<{}> {
const { user, sharingDoc } = recipient;
const target = targetDoc || this.targetDoc!;
const acl = `acl-${normalizeEmail(user.email)}`;
- const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.rootDoc);
+ const docs = SelectionManager.Views.length < 2 ? [target] : SelectionManager.Views.map(docView => docView.Document);
docs.map(doc => (this.layoutDocAcls || doc.dockingConfig ? doc : Doc.GetProto(doc))).forEach(doc => {
distributeAcls(acl, permission as SharingPermissions, doc, undefined, this.upgradeNested ? true : undefined);
if (permission !== SharingPermissions.None) {
@@ -180,7 +181,7 @@ export class SharingManager extends React.Component<{}> {
const target = targetDoc || this.targetDoc!;
const acl = `acl-${normalizeEmail(StrCast(group.title))}`;
- const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.rootDoc);
+ const docs = SelectionManager.Views.length < 2 ? [target] : SelectionManager.Views.map(docView => docView.Document);
docs.map(doc => (this.layoutDocAcls || doc.dockingConfig ? doc : Doc.GetProto(doc))).forEach(doc => {
distributeAcls(acl, permission as SharingPermissions, doc, undefined, this.upgradeNested ? true : undefined);
@@ -317,7 +318,7 @@ export class SharingManager extends React.Component<{}> {
private focusOn = (contents: string) => {
const title = this.targetDoc ? StrCast(this.targetDoc.title) : '';
- const docs = SelectionManager.Views().length > 1 ? SelectionManager.Views().map(docView => docView.props.Document) : [this.targetDoc];
+ const docs = SelectionManager.Views.length > 1 ? SelectionManager.Views.map(docView => docView.props.Document) : [this.targetDoc];
return (
<span
className="focus-span"
@@ -444,7 +445,7 @@ export class SharingManager extends React.Component<{}> {
const users = this.individualSort === 'ascending' ? this.users.slice().sort(this.sortUsers) : this.individualSort === 'descending' ? this.users.slice().sort(this.sortUsers).reverse() : this.users;
const groups = this.groupSort === 'ascending' ? groupList.slice().sort(this.sortGroups) : this.groupSort === 'descending' ? groupList.slice().sort(this.sortGroups).reverse() : groupList;
- let docs = SelectionManager.Views().length < 2 ? [this.targetDoc] : SelectionManager.Views().map(docView => docView.rootDoc);
+ let docs = SelectionManager.Views.length < 2 ? [this.targetDoc] : SelectionManager.Views.map(docView => docView.Document);
if (this.myDocAcls) {
const newDocs: Doc[] = [];
diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts
index fce43eef6..b8bd90983 100644
--- a/src/client/util/SnappingManager.ts
+++ b/src/client/util/SnappingManager.ts
@@ -1,68 +1,41 @@
-import { observable, action, runInAction } from 'mobx';
-import { Doc } from '../../fields/Doc';
+import { observable, action, runInAction, reaction, makeObservable } from 'mobx';
+import { Doc, Opt } from '../../fields/Doc';
-export namespace SnappingManager {
- class Manager {
- @observable ShiftKey = false;
- @observable CtrlKey = false;
- @observable IsDragging: boolean = false;
- @observable IsResizing: Doc | undefined;
- @observable CanEmbed: boolean = false;
- @observable public horizSnapLines: number[] = [];
- @observable public vertSnapLines: number[] = [];
- @action public clearSnapLines() {
- this.vertSnapLines = [];
- this.horizSnapLines = [];
- }
- @action public addSnapLines(horizLines: number[], vertLines: number[]) {
- this.horizSnapLines.push(...horizLines);
- this.vertSnapLines.push(...vertLines);
- }
+export class SnappingManager {
+ private static _manager: SnappingManager;
+ private static get Instance() {
+ return SnappingManager._manager ?? new SnappingManager();
}
- const manager = new Manager();
+ @observable _shiftKey = false;
+ @observable _ctrlKey = false;
+ @observable _isDragging: boolean = false;
+ @observable _isResizing: Doc | undefined = undefined;
+ @observable _canEmbed: boolean = false;
+ @observable _horizSnapLines: number[] = [];
+ @observable _vertSnapLines: number[] = [];
- export function clearSnapLines() {
- manager.clearSnapLines();
- }
- export function addSnapLines(horizLines: number[], vertLines: number[]) {
- manager.addSnapLines(horizLines, vertLines);
- }
- export function horizSnapLines() {
- return manager.horizSnapLines;
- }
- export function vertSnapLines() {
- return manager.vertSnapLines;
+ private constructor() {
+ SnappingManager._manager = this;
+ makeObservable(this);
}
- export function SetShiftKey(down: boolean) {
- runInAction(() => (manager.ShiftKey = down));
- }
- export function SetCtrlKey(down: boolean) {
- runInAction(() => (manager.CtrlKey = down));
- }
- export function SetIsDragging(dragging: boolean) {
- runInAction(() => (manager.IsDragging = dragging));
- }
- export function SetIsResizing(doc: Doc | undefined) {
- runInAction(() => (manager.IsResizing = doc));
- }
- export function SetCanEmbed(canEmbed: boolean) {
- runInAction(() => (manager.CanEmbed = canEmbed));
- }
- export function GetShiftKey() {
- return manager.ShiftKey;
- }
- export function GetCtrlKey() {
- return manager.CtrlKey;
- }
- export function GetIsDragging() {
- return manager.IsDragging;
- }
- export function GetIsResizing() {
- return manager.IsResizing;
- }
- export function GetCanEmbed() {
- return manager.CanEmbed;
- }
+ @action public static clearSnapLines = () => (this.Instance._vertSnapLines.length = this.Instance._horizSnapLines.length = 0);
+ @action public static addSnapLines = (horizLines: number[], vertLines: number[]) => {
+ this.Instance._horizSnapLines.push(...horizLines);
+ this.Instance._vertSnapLines.push(...vertLines);
+ };
+
+ public static get HorizSnapLines() { return this.Instance._horizSnapLines; } // prettier-ignore
+ public static get VertSnapLines() { return this.Instance._vertSnapLines; } // prettier-ignore
+ public static get ShiftKey() { return this.Instance._shiftKey; } // prettier-ignore
+ public static get CtrlKey() { return this.Instance._ctrlKey; } // prettier-ignore
+ public static get IsDragging() { return this.Instance._isDragging; } // prettier-ignore
+ public static get IsResizing() { return this.Instance._isResizing; } // prettier-ignore
+ public static get CanEmbed() { return this.Instance._canEmbed; } // prettier-ignore
+ public static SetShiftKey = (down: boolean) => runInAction(() => (this.Instance._shiftKey = down)); // prettier-ignore
+ public static SetCtrlKey = (down: boolean) => runInAction(() => (this.Instance._ctrlKey = down)); // prettier-ignore
+ public static SetIsDragging = (drag: boolean) => runInAction(() => (this.Instance._isDragging = drag)); // prettier-ignore
+ public static SetIsResizing = (doc: Opt<Doc>) => runInAction(() => (this.Instance._isResizing = doc)); // prettier-ignore
+ public static SetCanEmbed = (embed:boolean) => runInAction(() => (this.Instance._canEmbed = embed)); // prettier-ignore
}
diff --git a/src/client/util/TrackMovements.ts b/src/client/util/TrackMovements.ts
index 0e56ee1bc..0b197cf9a 100644
--- a/src/client/util/TrackMovements.ts
+++ b/src/client/util/TrackMovements.ts
@@ -1,4 +1,4 @@
-import { IReactionDisposer, observable, observe, reaction } from 'mobx';
+import { IReactionDisposer, makeObservable, observable, observe, reaction } from 'mobx';
import { NumCast } from '../../fields/Types';
import { Doc, DocListCast } from '../../fields/Doc';
import { CollectionDockingView } from '../views/collections/CollectionDockingView';
@@ -40,7 +40,7 @@ export class TrackMovements {
constructor() {
// init the global instance
TrackMovements._instance = this;
-
+ makeObservable(this);
// init the instance variables
this.currentPresentation = TrackMovements.NULL_PRESENTATION;
this.tracking = false;
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/util/reportManager/ReportManager.tsx b/src/client/util/reportManager/ReportManager.tsx
index b25d51b41..0c49aeed4 100644
--- a/src/client/util/reportManager/ReportManager.tsx
+++ b/src/client/util/reportManager/ReportManager.tsx
@@ -1,13 +1,11 @@
import * as React from 'react';
-import v4 = require('uuid/v4');
+import * as uuid from 'uuid';
import '.././SettingsManager.scss';
import './ReportManager.scss';
-import Dropzone from 'react-dropzone';
import ReactLoading from 'react-loading';
-import { action, observable } from 'mobx';
+import { action, makeObservable, observable } from 'mobx';
import { BsX, BsArrowsAngleExpand, BsArrowsAngleContract } from 'react-icons/bs';
import { CgClose } from 'react-icons/cg';
-import { AiOutlineUpload } from 'react-icons/ai';
import { HiOutlineArrowLeft } from 'react-icons/hi';
import { Issue } from './reportManagerSchema';
import { observer } from 'mobx-react';
@@ -105,6 +103,7 @@ export class ReportManager extends React.Component<{}> {
constructor(props: {}) {
super(props);
+ makeObservable(this);
ReportManager.Instance = this;
// initializing Github connection
@@ -156,7 +155,7 @@ export class ReportManager extends React.Component<{}> {
* @param files uploaded files
*/
private onDrop = (files: File[]) => {
- this.setFormData({ ...this.formData, mediaFiles: [...this.formData.mediaFiles, ...files.map(file => ({ _id: v4(), file }))] });
+ this.setFormData({ ...this.formData, mediaFiles: [...this.formData.mediaFiles, ...files.map(file => ({ _id: uuid.v4(), file }))] });
};
/**
@@ -338,7 +337,7 @@ export class ReportManager extends React.Component<{}> {
multiple
onChange={e => {
if (!e.target.files) return;
- this.setFormData({ ...this.formData, mediaFiles: [...this.formData.mediaFiles, ...Array.from(e.target.files).map(file => ({ _id: v4(), file }))] });
+ this.setFormData({ ...this.formData, mediaFiles: [...this.formData.mediaFiles, ...Array.from(e.target.files).map(file => ({ _id: uuid.v4(), file }))] });
}}
/>
{this.formData.mediaFiles.length > 0 && <ul className="file-list">{this.formData.mediaFiles.map(file => this.getMediaPreview(file))}</ul>}
diff --git a/src/client/util/reportManager/ReportManagerComponents.tsx b/src/client/util/reportManager/ReportManagerComponents.tsx
index e870c073d..1e226bf6d 100644
--- a/src/client/util/reportManager/ReportManagerComponents.tsx
+++ b/src/client/util/reportManager/ReportManagerComponents.tsx
@@ -289,7 +289,7 @@ export const IssueView = ({ issue }: IssueViewProps) => {
</div>
</div>
)}
- <ReactMarkdown children={issueBody} className="issue-content" linkTarget={'_blank'} remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]} />
+ <ReactMarkdown children={issueBody} className="issue-content" remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]} />
</div>
);
};