aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/util/CurrentUserUtils.ts89
-rw-r--r--src/client/util/History.ts4
-rw-r--r--src/client/views/MainView.tsx89
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx8
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx4
-rw-r--r--src/client/views/search/SearchBox.scss50
-rw-r--r--src/client/views/search/SearchBox.tsx28
7 files changed, 171 insertions, 101 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 435944a74..a76aa0dee 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1,4 +1,4 @@
-import { computed, observable, reaction } from "mobx";
+import { computed, observable, reaction, action } from "mobx";
import * as rp from 'request-promise';
import { Utils } from "../../Utils";
import { DocServer } from "../DocServer";
@@ -24,6 +24,8 @@ import { DimUnit } from "../views/collections/collectionMulticolumn/CollectionMu
import { LabelBox } from "../views/nodes/LabelBox";
import { LinkManager } from "./LinkManager";
import { Id } from "../../fields/FieldSymbols";
+import { HistoryUtil } from "./History";
+import { CollectionDockingView } from "../views/collections/CollectionDockingView";
export class CurrentUserUtils {
private static curr_id: string;
@@ -730,7 +732,7 @@ export class CurrentUserUtils {
treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false,
lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true
}));
- const newDashboard = ScriptField.MakeScript(`createNewDashboard()`);
+ const newDashboard = ScriptField.MakeScript(`createNewDashboard(Doc.UserDoc())`);
(doc.myDashboards as any as Doc).contextMenuScripts = new List<ScriptField>([newDashboard!]);
(doc.myDashboards as any as Doc).contextMenuLabels = new List<string>(["Create New Dashboard"]);
}
@@ -976,9 +978,90 @@ export class CurrentUserUtils {
}
});
}
+
+ public static _urlState: HistoryUtil.DocUrl;
+
+ public static openDashboard = (userDoc: Doc, doc: Doc, fromHistory = false) => {
+ CurrentUserUtils.MainDocId = doc[Id];
+
+ if (doc) { // this has the side-effect of setting the main container since we're assigning the active/guest dashboard
+ !("presentationView" in doc) && (doc.presentationView = new List<Doc>([Docs.Create.TreeDocument([], { title: "Presentation" })]));
+ userDoc ? (userDoc.activeDashboard = doc) : (CurrentUserUtils.GuestDashboard = doc);
+ }
+ const state = CurrentUserUtils._urlState;
+ if (state.sharing === true && !userDoc) {
+ DocServer.Control.makeReadOnly();
+ } else {
+ fromHistory || HistoryUtil.pushState({
+ type: "doc",
+ docId: doc[Id],
+ readonly: state.readonly,
+ nro: state.nro,
+ sharing: false,
+ });
+ if (state.readonly === true || state.readonly === null) {
+ DocServer.Control.makeReadOnly();
+ } else if (state.safe) {
+ if (!state.nro) {
+ DocServer.Control.makeReadOnly();
+ }
+ CollectionView.SetSafeMode(true);
+ } else if (state.nro || state.nro === null || state.readonly === false) {
+ } else if (doc.readOnly) {
+ DocServer.Control.makeReadOnly();
+ } else {
+ DocServer.Control.makeEditable();
+ }
+ }
+
+ return true;
+ }
+
+ public static snapshotDashboard = (userDoc: Doc) => {
+ const activeDashboard = Cast(userDoc.activeDashboard, Doc, null);
+ CollectionDockingView.Copy(activeDashboard).then(copy => {
+ Doc.AddDocToList(Cast(userDoc.myDashboards, Doc, null), "data", copy);
+ // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
+ setTimeout(() => CurrentUserUtils.openDashboard(userDoc, copy), 0);
+ });
+ }
+
+ public static createNewDashboard = async (userDoc: Doc, id?: string) => {
+ const myPresentations = userDoc.myPresentations as Doc;
+ const presentation = Doc.MakeCopy(userDoc.emptyPresentation as Doc, true);
+ const dashboards = Cast(userDoc.myDashboards, Doc) as Doc;
+ const dashboardCount = DocListCast(dashboards.data).length + 1;
+ const emptyPane = Cast(userDoc.emptyPane, Doc, null);
+ emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1;
+ const freeformOptions: DocumentOptions = {
+ x: 0,
+ y: 400,
+ _width: 1500,
+ _height: 1000,
+ title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`,
+ };
+ const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
+ const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: `Dashboard ${dashboardCount}` }, id, "row");
+ Doc.AddDocToList(myPresentations, "data", presentation);
+ userDoc.activePresentation = presentation;
+ const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`);
+ const toggleComic = ScriptField.MakeScript(`toggleComicMode()`);
+ const snapshotDashboard = ScriptField.MakeScript(`snapshotDashboard()`);
+ const createDashboard = ScriptField.MakeScript(`createNewDashboard()`);
+ dashboardDoc.contextMenuScripts = new List<ScriptField>([toggleTheme!, toggleComic!, snapshotDashboard!, createDashboard!]);
+ dashboardDoc.contextMenuLabels = new List<string>(["Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Dashboard", "Create Dashboard"]);
+
+ Doc.AddDocToList(dashboards, "data", dashboardDoc);
+ // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
+ setTimeout(() => {
+ CurrentUserUtils.openDashboard(userDoc, dashboardDoc);
+ }, 0);
+ }
}
-Scripting.addGlobal(function createNewDashboard() { return MainView.Instance.createNewDashboard(); },
+Scripting.addGlobal(function snapshotDashboard() { CurrentUserUtils.snapshotDashboard(Doc.UserDoc()); },
+ "creates a snapshot copy of a dashboard");
+Scripting.addGlobal(function createNewDashboard() { return CurrentUserUtils.createNewDashboard(Doc.UserDoc()); },
"creates a new dashboard when called");
Scripting.addGlobal(function createNewPresentation() { return MainView.Instance.createNewPresentation(); },
"creates a new presentation when called");
diff --git a/src/client/util/History.ts b/src/client/util/History.ts
index cab682ac7..cbe36b401 100644
--- a/src/client/util/History.ts
+++ b/src/client/util/History.ts
@@ -1,8 +1,8 @@
import { Doc } from "../../fields/Doc";
import { DocServer } from "../DocServer";
-import { MainView } from "../views/MainView";
import * as qs from 'query-string';
import { Utils, OmitKeys } from "../../Utils";
+import { CurrentUserUtils } from "./CurrentUserUtils";
export namespace HistoryUtil {
export interface DocInitializerList {
@@ -197,7 +197,7 @@ export namespace HistoryUtil {
await Promise.all(Object.keys(init).map(id => initDoc(id, init[id])));
}
if (field instanceof Doc) {
- MainView.Instance.openDashboard(field, true);
+ CurrentUserUtils.openDashboard(Doc.UserDoc(), field, true);
}
}
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index cfa2534c9..d107b74f0 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -70,7 +70,6 @@ import "./MainView.scss";
export class MainView extends React.Component {
public static Instance: MainView;
private _buttonBarHeight = 36;
- private _urlState: HistoryUtil.DocUrl;
private _docBtnRef = React.createRef<HTMLDivElement>();
private _mainViewRef = React.createRef<HTMLDivElement>();
@@ -145,7 +144,7 @@ export class MainView extends React.Component {
super(props);
MainView.Instance = this;
this.sidebarContent.proto = undefined;
- this._urlState = HistoryUtil.parseUrl(window.location) || {} as any;
+ CurrentUserUtils._urlState = HistoryUtil.parseUrl(window.location) || {} as any;
// causes errors to be generated when modifying an observable outside of an action
CurrentUserUtils.propertiesWidth = 0;
@@ -233,11 +232,11 @@ export class MainView extends React.Component {
if (received && !this.userDoc) {
reaction(
() => CurrentUserUtils.GuestTarget,
- target => target && this.createNewDashboard(),
+ target => target && CurrentUserUtils.createNewDashboard(Doc.UserDoc()),
{ fireImmediately: true }
);
} else {
- if (received && this._urlState.sharing) {
+ if (received && CurrentUserUtils._urlState.sharing) {
reaction(() => CollectionDockingView.Instance && CollectionDockingView.Instance.initialized,
initialized => initialized && received && DocServer.GetRefField(received).then(docField => {
if (docField instanceof Doc && docField._viewType !== CollectionViewType.Docking) {
@@ -248,9 +247,9 @@ export class MainView extends React.Component {
}
const doc = this.userDoc && await Cast(this.userDoc.activeDashboard, Doc);
if (doc) {
- this.openDashboard(doc);
+ CurrentUserUtils.openDashboard(Doc.UserDoc(), doc);
} else {
- this.createNewDashboard();
+ CurrentUserUtils.createNewDashboard(Doc.UserDoc());
}
}
}
@@ -271,73 +270,6 @@ export class MainView extends React.Component {
Doc.AddDocToList(myPresentations, "data", pres);
}
- @action
- createNewDashboard = async (id?: string) => {
- const myPresentations = Doc.UserDoc().myPresentations as Doc;
- const presentation = Doc.MakeCopy(Doc.UserDoc().emptyPresentation as Doc, true);
- const dashboards = Cast(this.userDoc.myDashboards, Doc) as Doc;
- const dashboardCount = DocListCast(dashboards.data).length + 1;
- const emptyPane = Cast(this.userDoc.emptyPane, Doc, null);
- emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1;
- const freeformOptions: DocumentOptions = {
- x: 0,
- y: 400,
- _width: this._panelWidth * .7 - this.propertiesWidth() * 0.7,
- _height: this._panelHeight,
- title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`,
- };
- const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
- const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: `Dashboard ${dashboardCount}` }, id, "row");
- Doc.AddDocToList(myPresentations, "data", presentation);
- Doc.UserDoc().activePresentation = presentation;
- const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`);
- const toggleComic = ScriptField.MakeScript(`toggleComicMode()`);
- const copyDashboard = ScriptField.MakeScript(`copyDashboard()`);
- const createDashboard = ScriptField.MakeScript(`createDashboard()`);
- dashboardDoc.contextMenuScripts = new List<ScriptField>([toggleTheme!, toggleComic!, copyDashboard!, createDashboard!]);
- dashboardDoc.contextMenuLabels = new List<string>(["Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Dashboard", "Create Dashboard"]);
-
- Doc.AddDocToList(dashboards, "data", dashboardDoc);
- // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
- setTimeout(() => this.openDashboard(dashboardDoc), 0);
- }
-
- @action
- openDashboard = (doc: Doc, fromHistory = false) => {
- CurrentUserUtils.MainDocId = doc[Id];
-
- if (doc) { // this has the side-effect of setting the main container since we're assigning the active/guest dashboard
- !("presentationView" in doc) && (doc.presentationView = new List<Doc>([Docs.Create.TreeDocument([], { title: "Presentation" })]));
- this.userDoc ? (this.userDoc.activeDashboard = doc) : (CurrentUserUtils.GuestDashboard = doc);
- }
- const state = this._urlState;
- if (state.sharing === true && !this.userDoc) {
- DocServer.Control.makeReadOnly();
- } else {
- fromHistory || HistoryUtil.pushState({
- type: "doc",
- docId: doc[Id],
- readonly: state.readonly,
- nro: state.nro,
- sharing: false,
- });
- if (state.readonly === true || state.readonly === null) {
- DocServer.Control.makeReadOnly();
- } else if (state.safe) {
- if (!state.nro) {
- DocServer.Control.makeReadOnly();
- }
- CollectionView.SetSafeMode(true);
- } else if (state.nro || state.nro === null || state.readonly === false) {
- } else if (doc.readOnly) {
- DocServer.Control.makeReadOnly();
- } else {
- DocServer.Control.makeEditable();
- }
- }
-
- return true;
- }
onDrop = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
@@ -454,7 +386,7 @@ export class MainView extends React.Component {
flyoutWidthFunc = () => this.flyoutWidth;
addDocTabFunc = (doc: Doc, where: string, libraryPath?: Doc[]): boolean => {
return where === "close" ? CollectionDockingView.CloseRightSplit(doc) :
- doc.dockingConfig ? this.openDashboard(doc) :
+ doc.dockingConfig ? CurrentUserUtils.openDashboard(Doc.UserDoc(), doc) :
CollectionDockingView.AddRightSplit(doc, libraryPath);
}
sidebarScreenToLocal = () => new Transform(0, (CollectionMenu.Instance.Pinned ? -35 : 0) - Number(SEARCH_PANEL_HEIGHT.replace("px", "")), 1);
@@ -998,14 +930,5 @@ export class MainView extends React.Component {
}
Scripting.addGlobal(function selectMainMenu(doc: Doc, title: string) { MainView.Instance.selectMenu(doc); });
Scripting.addGlobal(function toggleComicMode() { Doc.UserDoc().fontFamily = "Comic Sans MS"; Doc.UserDoc().renderStyle = Doc.UserDoc().renderStyle === "comic" ? undefined : "comic"; });
-Scripting.addGlobal(function copyDashboard() {
- const activeDashboard = Cast(Doc.UserDoc().activeDashboard, Doc, null);
- CollectionDockingView.Copy(activeDashboard).then(copy => {
- Doc.AddDocToList(Cast(Doc.UserDoc().myDashboards, Doc, null), "data", copy);
- // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
- setTimeout(() => MainView.Instance.openDashboard(copy), 0);
- });
-});
-Scripting.addGlobal(function createDashboard() { MainView.Instance.createNewDashboard(); });
Scripting.addGlobal(function importDocument() { return MainView.Instance.importDocument(); },
"imports files from device directly into the import sidebar");
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index e7f54ff86..dfefd645a 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -25,7 +25,6 @@ import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { undoBatch } from "../../util/UndoManager";
-import { MainView } from '../MainView';
import { DocumentView } from "../nodes/DocumentView";
import { PresBox } from '../nodes/PresBox';
import "./CollectionDockingView.scss";
@@ -34,6 +33,7 @@ import { SubCollectionViewProps, CollectionSubView } from "./CollectionSubView";
import { CollectionViewType } from './CollectionView';
import { DockingViewButtonSelector } from './ParentDocumentSelector';
import React = require("react");
+import { CurrentUserUtils } from '../../util/CurrentUserUtils';
const _global = (window /* browser */ || global /* node */) as any;
@observer
@@ -87,7 +87,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
@action
public OpenFullScreen(docView: DocumentView, libraryPath?: Doc[]) {
if (docView.props.Document._viewType === CollectionViewType.Docking && docView.props.Document.layoutKey === "layout") {
- return MainView.Instance.openDashboard(docView.props.Document);
+ return CurrentUserUtils.openDashboard(Doc.UserDoc(), docView.props.Document);
}
const document = Doc.MakeAlias(docView.props.Document);
const newItemStackConfig = {
@@ -188,7 +188,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
@action
public static AddRightSplit(document: Doc, libraryPath?: Doc[]) {
if (!CollectionDockingView.Instance) return false;
- if (document._viewType === CollectionViewType.Docking) return MainView.Instance.openDashboard(document);
+ if (document._viewType === CollectionViewType.Docking) return CurrentUserUtils.openDashboard(Doc.UserDoc(), document);
const instance = CollectionDockingView.Instance;
const newItemStackConfig = {
type: 'stack',
@@ -864,7 +864,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
addDocTab = (doc: Doc, location: string, libraryPath?: Doc[]) => {
SelectionManager.DeselectAll();
if (doc._viewType === CollectionViewType.Docking) {
- return MainView.Instance.openDashboard(doc);
+ return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc);
} else if (location === "onRight") {
return CollectionDockingView.AddRightSplit(doc, libraryPath);
} else if (location === "close") {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 5099f0022..d7f0f8e14 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -20,7 +20,6 @@ import { undoBatch, UndoManager } from '../../util/UndoManager';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { EditableView } from "../EditableView";
-import { MainView } from '../MainView';
import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView';
import { DocumentView } from '../nodes/DocumentView';
import { ImageBox } from '../nodes/ImageBox';
@@ -32,6 +31,7 @@ import { CollectionViewType } from './CollectionView';
import React = require("react");
import { makeTemplate } from '../../util/DropConverter';
import { TraceMobx } from '../../../fields/util';
+import { CurrentUserUtils } from '../../util/CurrentUserUtils';
export interface TreeViewProps {
document: Doc;
@@ -739,7 +739,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
onContextMenu = (e: React.MouseEvent): void => {
// need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
if (!e.isPropagationStopped() && this.doc === Doc.UserDoc().myDashboards) {
- ContextMenu.Instance.addItem({ description: "Create Dashboard", event: () => MainView.Instance.createNewDashboard(), icon: "plus" });
+ ContextMenu.Instance.addItem({ description: "Create Dashboard", event: () => CurrentUserUtils.createNewDashboard(Doc.UserDoc()), icon: "plus" });
ContextMenu.Instance.addItem({ description: "Delete Dashboard", event: () => this.remove(this.doc), icon: "minus" });
e.stopPropagation();
e.preventDefault();
diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss
index b5557e0d9..aa5180c96 100644
--- a/src/client/views/search/SearchBox.scss
+++ b/src/client/views/search/SearchBox.scss
@@ -6,23 +6,69 @@
flex-direction: column;
width: 100%;
height: 100%;
- position: absolute;
+ position: relative;
font-size: 10px;
line-height: 1;
overflow-y: auto;
overflow-x: visible;
background: lightgrey;
+ overflow: visible;
+ z-index: 10000;
+ .searchBox-lozenge-user,
+ .searchBox-lozenge-dashboard,
.searchBox-lozenge {
background-color: #313131;
border-radius: 5px;
- height: 15px;
+ height: 18px;
padding: 4px;
box-shadow: lightgrey 0.15em 0.15em 0.1em;
margin: 2px;
margin-bottom: 4px;
border-top: dimgrey 1px solid;
border-left: dimgrey 1px solid;
+ display: flex;
+ .searchBox-logoff,
+ .searchBox-dashboards {
+ border-radius: 3px;
+ background: olivedrab;
+ color: white;
+ position: relative;
+ display: none;
+ margin-left: 3px;
+ padding-left: 2px;
+ padding-right: 2px;
+ padding-bottom: 11px;
+ cursor: default;
+ }
+ .searchBox-logoff {
+ background: red;
+ }
+
+ .searchBox-dashSelect{
+ background-color: black;
+ color: white;
+ font-size: 9;
+ margin-right: 6;
+ border-radius: 5px;
+ position: relative;
+ height: 15px;
+ transform: translate(0,-3px);
+
+ &:hover {
+ cursor: pointer;
+ }
+ }
+ }
+ .searchBox-lozenge-user:hover {
+ .searchBox-logoff {
+ display:inline-block;
+ }
+ }
+ .searchBox-lozenge-dashboard:hover {
+ .searchBox-dashboards {
+ display:inline-block;
+ }
}
}
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 5739c2a67..7e233ecbb 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -5,14 +5,15 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, DocListCast, Field, Opt } from '../../../fields/Doc';
import { documentSchema } from "../../../fields/documentSchemas";
-import { Id, Copy } from '../../../fields/FieldSymbols';
+import { Copy, Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
import { createSchema, listSpec, makeInterface } from '../../../fields/Schema';
import { SchemaHeaderField } from '../../../fields/SchemaHeaderField';
import { Cast, NumCast, StrCast } from '../../../fields/Types';
-import { returnFalse, returnZero, setupMoveUpEvents, emptyFunction } from '../../../Utils';
+import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents, Utils } from '../../../Utils';
import { Docs } from '../../documents/Documents';
import { DocumentType } from "../../documents/DocumentTypes";
+import { CurrentUserUtils } from "../../util/CurrentUserUtils";
import { SetupDrag } from '../../util/DragManager';
import { SearchUtil } from '../../util/SearchUtil';
import { Transform } from '../../util/Transform';
@@ -22,6 +23,7 @@ import { CollectionViewType } from '../collections/CollectionView';
import { ViewBoxBaseComponent } from "../DocComponent";
import { FieldView, FieldViewProps } from '../nodes/FieldView';
import "./SearchBox.scss";
+import { undoBatch } from "../../util/UndoManager";
export const searchSchema = createSchema({ Document: Doc });
@@ -486,18 +488,34 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
collectionView.props.Document._docFilters = docsForFilter?.length && docFilters?.length ? new List<string>(docFilters) : undefined;
}
}
+ showLogout = () => {
+
+ }
render() {
+ const myDashboards = DocListCast(Cast(Doc.UserDoc().myDashboards, Doc, null).data);
return (
<div style={{ pointerEvents: "all" }} className="searchBox-container">
<div style={{ position: "absolute", left: 15, height: 32, alignItems: "center", display: "flex" }}>
- <div className="searchBox-lozenge">
+ <div className="searchBox-lozenge-user">
{`${Doc.CurrentUserEmail}`}
+ <div className="searchBox-logoff" onClick={() => window.location.assign(Utils.prepend("/logout"))}>
+ Logoff
+ </div>
</div>
<div className="searchBox-lozenge">
{`UI project`}
</div>
- <div className="searchBox-lozenge" >
- {`➱ ${Cast(Doc.UserDoc().activeDashboard, Doc, null)?.title}`}
+ <div className="searchBox-lozenge-dashboard" >
+ <select className="searchBox-dashSelect" onChange={e => CurrentUserUtils.openDashboard(Doc.UserDoc(), myDashboards[Number(e.target.value)])}
+ value={myDashboards.indexOf(Cast(Doc.UserDoc().activeDashboard, Doc, null)!)}>
+ {myDashboards.map((dash, i) => <option key={dash[Id]} value={i}> {StrCast(dash.title)} </option>)}
+ </select>
+ <div className="searchBox-dashboards" onClick={undoBatch(() => CurrentUserUtils.createNewDashboard(Doc.UserDoc()))}>
+ New
+ </div>
+ <div className="searchBox-dashboards" onClick={undoBatch(() => CurrentUserUtils.snapshotDashboard(Doc.UserDoc()))}>
+ Snapshot
+ </div>
</div>
</div>
<div className="searchBox-bar">