aboutsummaryrefslogtreecommitdiff
path: root/src/client/views
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views')
-rw-r--r--src/client/views/DocComponent.tsx16
-rw-r--r--src/client/views/Main.tsx1
-rw-r--r--src/client/views/MainView.tsx6
-rw-r--r--src/client/views/SidebarAnnos.tsx29
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx54
-rw-r--r--src/client/views/collections/TreeView.tsx4
-rw-r--r--src/client/views/nodes/DocumentView.tsx5
-rw-r--r--src/client/views/search/SearchBox.tsx2
8 files changed, 73 insertions, 44 deletions
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 0b70ce68d..fc36c7e43 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -7,7 +7,7 @@ import { InteractionUtils } from '../util/InteractionUtils';
import { List } from '../../fields/List';
import { DateField } from '../../fields/DateField';
import { ScriptField } from '../../fields/ScriptField';
-import { GetEffectiveAcl, SharingPermissions, distributeAcls, denormalizeEmail } from '../../fields/util';
+import { GetEffectiveAcl, SharingPermissions, distributeAcls, denormalizeEmail, inheritParentAcls } from '../../fields/util';
import { CurrentUserUtils } from '../util/CurrentUserUtils';
import { DocUtils } from '../documents/Documents';
import { returnFalse } from '../../Utils';
@@ -107,13 +107,6 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
// key where data is stored
@computed get fieldKey() { return this.props.fieldKey; }
- private AclMap = new Map<symbol, string>([
- [AclPrivate, SharingPermissions.None],
- [AclReadonly, SharingPermissions.View],
- [AclAddonly, SharingPermissions.Add],
- [AclEdit, SharingPermissions.Edit],
- [AclAdmin, SharingPermissions.Admin]
- ]);
lookupField = (field: string) => ScriptCast((this.layoutDoc as any).lookupField)?.script.run({ self: this.layoutDoc, data: this.rootDoc, field: field }).result;
@@ -201,15 +194,14 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
if (this.props.Document[AclSym] && Object.keys(this.props.Document[AclSym]).length) {
added.forEach(d => {
for (const [key, value] of Object.entries(this.props.Document[AclSym])) {
- if (d.author === denormalizeEmail(key.substring(4)) && !d.aliasOf) distributeAcls(key, SharingPermissions.Admin, d, true);
- //else if (this.props.Document[key] === SharingPermissions.Admin) distributeAcls(key, SharingPermissions.Add, d, true);
- // else distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d, true);
+ if (d.author === denormalizeEmail(key.substring(4)) && !d.aliasOf) distributeAcls(key, SharingPermissions.Admin, d);
}
});
}
if (effectiveAcl === AclAddonly) {
added.map(doc => {
+ if ([AclAdmin, AclEdit].includes(GetEffectiveAcl(doc))) inheritParentAcls(CurrentUserUtils.ActiveDashboard, doc);
doc.context = this.props.Document;
if (annotationKey ?? this._annotationKey) Doc.GetProto(doc).annotationOn = this.props.Document;
this.props.layerProvider?.(doc, true);
@@ -223,6 +215,8 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
doc._stayInCollection = undefined;
doc.context = this.props.Document;
if (annotationKey ?? this._annotationKey) Doc.GetProto(doc).annotationOn = this.props.Document;
+
+ inheritParentAcls(CurrentUserUtils.ActiveDashboard, doc);
});
const annoDocs = targetDataDoc[annotationKey ?? this.annotationKey] as List<Doc>;
if (annoDocs) annoDocs.push(...added);
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 60327f1bf..7553c8118 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -12,6 +12,7 @@ import { LinkManager } from "../util/LinkManager";
AssignAllExtensions();
(async () => {
+ MainView.Live = window.location.search.includes("live");
window.location.search.includes("safe") && CollectionView.SetSafeMode(true);
const info = await CurrentUserUtils.loadCurrentUser();
if (info.id !== "__guest__") {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 49f4f7a6e..005e46836 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -70,6 +70,7 @@ const _global = (window /* browser */ || global /* node */) as any;
@observer
export class MainView extends React.Component {
public static Instance: MainView;
+ public static Live: boolean = false;
private _docBtnRef = React.createRef<HTMLDivElement>();
@observable public LastButton: Opt<Doc>;
@observable private _windowWidth: number = 0;
@@ -105,8 +106,9 @@ export class MainView extends React.Component {
}
new InkStrokeProperties();
this._sidebarContent.proto = undefined;
- DocServer.setPlaygroundFields(["x", "y", "dataTransition", "_autoHeight", "_showSidebar", "_sidebarWidthPercent", "_width", "_height", "_viewTransition", "_panX", "_panY", "_viewScale", "_scrollTop", "hidden", "_curPage", "_viewType", "_chromeHidden"]); // can play with these fields on someone else's
-
+ if (!MainView.Live) {
+ DocServer.setPlaygroundFields(["x", "y", "dataTransition", "_autoHeight", "_showSidebar", "showSidebar", "_sidebarWidthPercent", "_width", "_height", "width", "height", "_viewTransition", "_panX", "_panY", "_viewScale", "_scrollTop", "hidden", "_curPage", "_viewType", "_chromeHidden", "nativeWidth", "_nativeWidth"]); // can play with these fields on someone else's
+ }
DocServer.GetRefField("rtfProto").then(proto => (proto instanceof Doc) && reaction(() => StrCast(proto.BROADCAST_MESSAGE), msg => msg && alert(msg)));
const tag = document.createElement('script');
diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index c5ae82c61..010418be5 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -31,18 +31,22 @@ interface ExtraProps {
}
@observer
export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
+ constructor(props: Readonly<FieldViewProps & ExtraProps>) {
+ super(props);
+ this.props.dataDoc[this.sidebarKey] = new List<Doc>();
+ }
_stackRef = React.createRef<CollectionStackingView>();
@computed get allHashtags() {
const keys = new Set<string>();
- DocListCast(this.props.rootDoc[this.sidebarKey()]).forEach(doc => SearchBox.documentKeys(doc).forEach(key => keys.add(key)));
+ DocListCast(this.props.rootDoc[this.sidebarKey]).forEach(doc => SearchBox.documentKeys(doc).forEach(key => keys.add(key)));
return Array.from(keys.keys()).filter(key => key[0]).filter(key => !key.startsWith("_") && (key[0] === "#" || key[0] === key[0].toUpperCase())).sort();
}
@computed get allUsers() {
const keys = new Set<string>();
- DocListCast(this.props.rootDoc[this.sidebarKey()]).forEach(doc => keys.add(StrCast(doc.author)));
+ DocListCast(this.props.rootDoc[this.sidebarKey]).forEach(doc => keys.add(StrCast(doc.author)));
return Array.from(keys.keys()).sort();
}
- get filtersKey() { return "_" + this.sidebarKey() + "-docFilters"; }
+ get filtersKey() { return "_" + this.sidebarKey + "-docFilters"; }
anchorMenuClick = (anchor: Doc) => {
const startup = StrListCast(this.props.rootDoc.docFilters).map(filter => filter.split(":")[0]).join(" ");
@@ -59,7 +63,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
this._stackRef.current?.focusDocument(target);
}
makeDocUnfiltered = (doc: Doc) => {
- if (DocListCast(this.props.rootDoc[this.sidebarKey()]).includes(doc)) {
+ if (DocListCast(this.props.rootDoc[this.sidebarKey]).includes(doc)) {
if (this.props.layoutDoc[this.filtersKey]) {
this.props.layoutDoc[this.filtersKey] = new List<string>();
return true;
@@ -67,14 +71,15 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
}
return false;
}
- sidebarKey = () => this.props.fieldKey + "-sidebar";
+
+ get sidebarKey() { return this.props.fieldKey + "-sidebar"; }
filtersHeight = () => 38;
screenToLocalTransform = () => this.props.ScreenToLocalTransform().translate(Doc.NativeWidth(this.props.dataDoc), 0).scale(this.props.scaling?.() || 1);
panelWidth = () => !this.props.layoutDoc._showSidebar ? 0 : this.props.layoutDoc.type === DocumentType.RTF ? this.props.PanelWidth() : (NumCast(this.props.layoutDoc.nativeWidth) - Doc.NativeWidth(this.props.dataDoc)) * this.props.PanelWidth() / NumCast(this.props.layoutDoc.nativeWidth);
panelHeight = () => this.props.PanelHeight() - this.filtersHeight();
- addDocument = (doc: Doc | Doc[]) => this.props.sidebarAddDocument(doc, this.sidebarKey());
- moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument(doc, targetCollection, addDocument, this.sidebarKey());
- removeDocument = (doc: Doc | Doc[]) => this.props.removeDocument(doc, this.sidebarKey());
+ addDocument = (doc: Doc | Doc[]) => this.props.sidebarAddDocument(doc, this.sidebarKey);
+ moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument(doc, targetCollection, addDocument, this.sidebarKey);
+ removeDocument = (doc: Doc | Doc[]) => this.props.removeDocument(doc, this.sidebarKey);
docFilters = () => [...StrListCast(this.props.layoutDoc._docFilters), ...StrListCast(this.props.layoutDoc[this.filtersKey])];
sidebarStyleProvider = (doc: Opt<Doc>, props: Opt<FieldViewProps | DocumentViewProps>, property: string) => {
@@ -87,14 +92,14 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
const renderTag = (tag: string) => {
const active = StrListCast(this.props.rootDoc[this.filtersKey]).includes(`${tag}:${tag}:check`);
return <div key={tag} className={`sidebarAnnos-filterTag${active ? "-active" : ""}`}
- onClick={e => Doc.setDocFilter(this.props.rootDoc, tag, tag, "check", true, this.sidebarKey(), e.shiftKey)}>
+ onClick={e => Doc.setDocFilter(this.props.rootDoc, tag, tag, "check", true, this.sidebarKey, e.shiftKey)}>
{tag}
</div>;
};
const renderUsers = (user: string) => {
const active = StrListCast(this.props.rootDoc[this.filtersKey]).includes(`author:${user}:check`);
return <div key={user} className={`sidebarAnnos-filterUser${active ? "-active" : ""}`}
- onClick={e => Doc.setDocFilter(this.props.rootDoc, "author", user, "check", true, this.sidebarKey(), e.shiftKey)}>
+ onClick={e => Doc.setDocFilter(this.props.rootDoc, "author", user, "check", true, this.sidebarKey, e.shiftKey)}>
{user}
</div>;
};
@@ -118,7 +123,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
PanelWidth={this.panelWidth}
styleProvider={this.sidebarStyleProvider}
docFilters={this.docFilters}
- scaleField={this.sidebarKey() + "-scale"}
+ scaleField={this.sidebarKey + "-scale"}
setHeight={(height) => this.props.setHeight(height + this.filtersHeight())}
isAnnotationOverlay={false}
select={emptyFunction}
@@ -132,7 +137,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
ScreenToLocalTransform={this.screenToLocalTransform}
renderDepth={this.props.renderDepth + 1}
viewType={CollectionViewType.Stacking}
- fieldKey={this.sidebarKey()}
+ fieldKey={this.sidebarKey}
pointerEvents={"all"}
/>
</div>
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index a8471f8e2..c0d39b2a2 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -4,7 +4,7 @@ import { action, IReactionDisposer, observable, reaction, runInAction } from "mo
import { observer } from "mobx-react";
import * as ReactDOM from 'react-dom';
import * as GoldenLayout from "../../../client/goldenLayout";
-import { Doc, DocListCast, Opt, DocListCastAsync } from "../../../fields/Doc";
+import { Doc, DocListCast, Opt, DocListCastAsync, DataSym } from "../../../fields/Doc";
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
import { List } from '../../../fields/List';
@@ -24,6 +24,7 @@ import React = require("react");
import { DocumentType } from '../../documents/DocumentTypes';
import { listSpec } from '../../../fields/Schema';
import { LightboxView } from '../LightboxView';
+import { inheritParentAcls } from '../../../fields/util';
const _global = (window /* browser */ || global /* node */) as any;
@observer
@@ -160,6 +161,18 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
}
const instance = CollectionDockingView.Instance;
if (!instance) return false;
+ else {
+ const docList = DocListCast(instance.props.Document[DataSym]["data-all"]);
+ // adds the doc of the newly created tab to the data-all field if it doesn't already include that doc or one of its aliases
+ !docList.includes(document) && !docList.includes(document.aliasOf as Doc) && Doc.AddDocToList(instance.props.Document[DataSym], "data-all", document);
+ // adds an alias of the doc to the data-all field of the layoutdocs of the aliases
+ DocListCast(instance.props.Document[DataSym].aliases).forEach(alias => {
+ const aliasDocList = DocListCast(alias["data-all"]);
+ // if aliasDocList contains the alias, don't do anything
+ // otherwise add the original or an alias depending on whether the doc you're looking at is the current doc or a different alias
+ !DocListCast(document.aliases).some(a => aliasDocList.includes(a)) && Doc.AddDocToList(alias, "data-all", alias !== instance.props.Document ? Doc.MakeAlias(document) : document);
+ });
+ }
const docContentConfig = CollectionDockingView.makeDocumentConfig(document, panelName);
if (!pullSide && stack) {
@@ -381,15 +394,22 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
setTimeout(async () => {
const sublists = await DocListCastAsync(this.props.Document[this.props.fieldKey]);
const tabs = sublists && Cast(sublists[0], Doc, null);
- const other = sublists && Cast(sublists[1], Doc, null);
+ // const other = sublists && Cast(sublists[1], Doc, null);
const tabdocs = await DocListCastAsync(tabs?.data);
- const otherdocs = await DocListCastAsync(other?.data);
- tabs && (Doc.GetProto(tabs).data = new List<Doc>(docs));
- const otherSet = new Set<Doc>();
- otherdocs?.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc));
- tabdocs?.filter(doc => !docs.includes(doc) && doc.type !== DocumentType.KVP).forEach(doc => otherSet.add(doc));
- const vals = Array.from(otherSet.values()).filter(val => val instanceof Doc).map(d => d).filter(d => d.type !== DocumentType.KVP);
- other && (Doc.GetProto(other).data = new List<Doc>(vals));
+ // const otherdocs = await DocListCastAsync(other?.data);
+ if (tabs) {
+ tabs.data = new List<Doc>(docs);
+ // DocListCast(tabs.aliases).forEach(tab => tab !== tabs && (tab.data = new List<Doc>(docs)));
+ }
+ // const otherSet = new Set<Doc>();
+ // otherdocs?.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc));
+ // tabdocs?.filter(doc => !docs.includes(doc) && doc.type !== DocumentType.KVP).forEach(doc => otherSet.add(doc));
+ // const vals = Array.from(otherSet.values()).filter(val => val instanceof Doc).map(d => d).filter(d => d.type !== DocumentType.KVP);
+ // this.props.Document[DataSym][this.props.fieldKey + "-all"] = new List<Doc>([...docs, ...vals]);
+ // if (other) {
+ // other.data = new List<Doc>(vals);
+ // // DocListCast(other.aliases).forEach(tab => tab !== other && (tab.data = new List<Doc>(vals)));
+ // }
}, 0);
}
@@ -399,7 +419,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
tab.reactComponents?.forEach((ele: any) => ReactDOM.unmountComponentAtNode(ele));
}
tabCreated = (tab: any) => {
- tab.contentItem.element[0]?.firstChild?.firstChild?.InitTab?.(tab); // have to explicitly initialize tabs that reuse contents from previous abs (ie, when dragging a tab around a new tab is created for the old content)
+ tab.contentItem.element[0]?.firstChild?.firstChild?.InitTab?.(tab); // have to explicitly initialize tabs that reuse contents from previous tabs (ie, when dragging a tab around a new tab is created for the old content)
}
stackCreated = (stack: any) => {
@@ -407,9 +427,11 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
if (e.target === stack.header?.element[0] && e.button === 2) {
const emptyPane = CurrentUserUtils.EmptyPane;
emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1;
- CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([], {
- _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _fitWidth: true, title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`
- }), "", stack);
+ const docToAdd = Docs.Create.FreeformDocument([], {
+ _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _fitWidth: true, title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`,
+ });
+ this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd);
+ CollectionDockingView.AddSplit(docToAdd, "", stack);
}
});
@@ -430,9 +452,11 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
// stack.config.fixed = !stack.config.fixed; // force the stack to have a fixed size
const emptyPane = CurrentUserUtils.EmptyPane;
emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1;
- CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([], {
+ const docToAdd = Docs.Create.FreeformDocument([], {
_width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _fitWidth: true, title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`
- }), "", stack);
+ });
+ this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd);
+ CollectionDockingView.AddSplit(docToAdd, "", stack);
}));
}
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 401bdcb02..e33c39d20 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -151,7 +151,10 @@ export class TreeView extends React.Component<TreeViewProps> {
this.treeViewOpen = !this.treeViewOpen;
} else {
// choose an appropriate alias or make one. --- choose the first alias that (1) user owns, (2) has no context field ... otherwise make a new alias
+ // this.props.addDocTab(CurrentUserUtils.ActiveDashboard.isShared ? Doc.MakeAlias(this.props.document) : this.props.document, "add:right");
+ // choose an appropriate alias or make one -- -- choose the first alias that (1) the user owns, (2) has no context field - if I own it and someone else does not have it open,, otherwise create an alias
this.props.addDocTab(this.props.document, "add:right");
+
}
}
constructor(props: any) {
@@ -511,6 +514,7 @@ export class TreeView extends React.Component<TreeViewProps> {
[{ script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, label: "Focus or Open" }];
}
onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick));
+
onChildDoubleClick = () => (!this.props.treeView.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick);
refocus = () => this.props.treeView.props.focus(this.props.treeView.props.Document);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index e1a28fe6e..f716eb7b1 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -754,16 +754,15 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
moreItems.push({ description: "Close", event: this.deleteClicked, icon: "times" });
}
- !more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" });
- cm.moveAfter(cm.findByDescription("More...")!, cm.findByDescription("OnClick...")!);
-
const help = cm.findByDescription("Help...");
const helpItems: ContextMenuProps[] = help && "subitems" in help ? help.subitems : [];
!Doc.UserDoc().novice && helpItems.push({ description: "Show Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "add:right"), icon: "layer-group" });
helpItems.push({ description: "Text Shortcuts Ctrl+/", event: () => this.props.addDocTab(Docs.Create.PdfDocument("/assets/cheat-sheet.pdf", { _width: 300, _height: 300 }), "add:right"), icon: "keyboard" });
!Doc.UserDoc().novice && helpItems.push({ description: "Print Document in Console", event: () => console.log(this.props.Document), icon: "hand-point-right" });
+ !Doc.UserDoc().novice && helpItems.push({ description: "Print DataDoc in Console", event: () => console.log(this.props.Document[DataSym]), icon: "hand-point-right" });
cm.addItem({ description: "Help...", noexpand: true, subitems: helpItems, icon: "question" });
}
+
if (!this.topMost) e?.stopPropagation(); // DocumentViews should stop propagation of this event
cm.displayMenu((e?.pageX || pageX || 0) - 15, (e?.pageY || pageY || 0) - 15);
DocumentViewInternal.SelectAfterContextMenu && !this.props.isSelected(true) && setTimeout(() => SelectionManager.SelectView(this.props.DocumentView(), false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear.
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 6a2325342..c72b25040 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -530,7 +530,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
<div className="searchBox-lozenge-dashboard" >
<select className="searchBox-dashSelect" onChange={e => CurrentUserUtils.openDashboard(Doc.UserDoc(), myDashboards[Number(e.target.value)])}
value={myDashboards.indexOf(CurrentUserUtils.ActiveDashboard)}>
- {myDashboards.map((dash, i) => <option key={dash[Id]} value={i}> {StrCast(dash.title)} </option>)}
+ {myDashboards.map((dash, i) => <option key={dash[Id]} value={i} style={{ backgroundColor: "black" }}> {StrCast(dash.title)} </option>)}
</select>
<div className="searchBox-dashboards" onClick={undoBatch(() => CurrentUserUtils.createNewDashboard(Doc.UserDoc()))}>
New