aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/client')
-rw-r--r--src/client/DocServer.ts6
-rw-r--r--src/client/util/CurrentUserUtils.ts20
-rw-r--r--src/client/util/DocumentManager.ts8
-rw-r--r--src/client/util/GroupManager.scss66
-rw-r--r--src/client/util/GroupManager.tsx112
-rw-r--r--src/client/util/GroupMemberView.scss33
-rw-r--r--src/client/util/GroupMemberView.tsx47
-rw-r--r--src/client/util/InteractionUtils.tsx2
-rw-r--r--src/client/util/SharingManager.scss109
-rw-r--r--src/client/util/SharingManager.tsx105
-rw-r--r--src/client/views/ContextMenu.scss23
-rw-r--r--src/client/views/ContextMenu.tsx18
-rw-r--r--src/client/views/ContextMenuItem.tsx13
-rw-r--r--src/client/views/DashboardView.tsx2
-rw-r--r--src/client/views/DocumentDecorations.tsx4
-rw-r--r--src/client/views/GlobalKeyHandler.ts20
-rw-r--r--src/client/views/MainView.scss8
-rw-r--r--src/client/views/MainView.tsx13
-rw-r--r--src/client/views/PropertiesButtons.tsx92
-rw-r--r--src/client/views/PropertiesDocContextSelector.tsx10
-rw-r--r--src/client/views/PropertiesView.scss44
-rw-r--r--src/client/views/PropertiesView.tsx71
-rw-r--r--src/client/views/StyleProvider.scss4
-rw-r--r--src/client/views/StyleProvider.tsx28
-rw-r--r--src/client/views/UndoStack.tsx10
-rw-r--r--src/client/views/collections/CollectionDockingView.scss7
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx22
-rw-r--r--src/client/views/collections/CollectionMenu.tsx37
-rw-r--r--src/client/views/collections/TabDocView.tsx1
-rw-r--r--src/client/views/collections/TreeView.scss28
-rw-r--r--src/client/views/collections/TreeView.tsx95
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx4
-rw-r--r--src/client/views/newlightbox/NewLightboxView.tsx4
-rw-r--r--src/client/views/nodes/DocumentView.tsx5
-rw-r--r--src/client/views/nodes/FontIconBox/FontIconBox.tsx165
-rw-r--r--src/client/views/nodes/LinkBox.scss8
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.tsx6
-rw-r--r--src/client/views/pdf/PDFViewer.tsx6
-rw-r--r--src/client/views/topbar/TopBar.tsx18
39 files changed, 689 insertions, 585 deletions
diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts
index fa1fca6ff..ba59a9f50 100644
--- a/src/client/DocServer.ts
+++ b/src/client/DocServer.ts
@@ -64,7 +64,7 @@ export namespace DocServer {
}
export let _socket: SocketIOClient.Socket;
// this client's distinct GUID created at initialization
- let GUID: string;
+ let USER_ID: string;
// indicates whether or not a document is currently being udpated, and, if so, its id
export enum WriteMode {
@@ -154,7 +154,7 @@ export namespace DocServer {
export function init(protocol: string, hostname: string, port: number, identifier: string) {
_cache = {};
- GUID = identifier;
+ USER_ID = identifier;
protocol = protocol.startsWith('https') ? 'wss' : 'ws';
_socket = io.connect(`${protocol}://${hostname}:${port}`);
// io.connect(`https://7f079dda.ngrok.io`);// if using ngrok, create a special address for the websocket
@@ -228,7 +228,7 @@ export namespace DocServer {
* indicating that this client has connected
*/
function onConnection() {
- _socket.emit(MessageStore.Bar.Message, GUID);
+ _socket.emit(MessageStore.Bar.Message, USER_ID);
}
export namespace Util {
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index e8947f190..2e4fb0f1c 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -343,15 +343,15 @@ export class CurrentUserUtils {
const badgeValue = "((len) => len && len !== '0' ? len: undefined)(docList(self.target.data).filter(doc => !docList(self.target.viewed).includes(doc)).length.toString())";
const getActiveDashTrails = "Doc.ActiveDashboard?.myTrails";
return [
- { title: "Dashboards", toolTip: "Dashboards ⌘D", target: this.setupDashboards(doc, "myDashboards"), ignoreClick: true, icon: "desktop", funcs: {hidden: "IsNoviceMode()"} },
- { title: "Search", toolTip: "Search ⌘F", target: this.setupSearcher(doc, "mySearcher"), ignoreClick: true, icon: "search", },
- { title: "Files", toolTip: "Files ⌘⇧F", target: this.setupFilesystem(doc, "myFilesystem"), ignoreClick: true, icon: "folder-open", },
- { title: "Tools", toolTip: "Tools ⌘T", target: this.setupToolsBtnPanel(doc, "myTools"), ignoreClick: true, icon: "wrench", funcs: {hidden: "IsNoviceMode()"} },
- { title: "Imports", toolTip: "Imports ⌘I", target: this.setupImportSidebar(doc, "myImports"), ignoreClick: true, icon: "upload", },
- { title: "Closed", toolTip: "Recently Closed ⌘R", target: this.setupRecentlyClosed(doc, "myRecentlyClosed"), ignoreClick: true, icon: "archive", },
- { title: "Shared", toolTip: "Shared Docs ⌘⇧S", target: Doc.MySharedDocs, ignoreClick: true, icon: "users", funcs: {badgeValue: badgeValue}},
- { title: "Trails", toolTip: "Trails ⌘⇧", target: Doc.UserDoc(), ignoreClick: true, icon: "pres-trail", funcs: {target: getActiveDashTrails}},
- { title: "User Doc", toolTip: "User Doc ⌘U", target: this.setupUserDocView(doc, "myUserDocView"), ignoreClick: true, icon: "address-card",funcs: {hidden: "IsNoviceMode()"} },
+ { title: "Dashboards", toolTip: "Dashboards", target: this.setupDashboards(doc, "myDashboards"), ignoreClick: true, icon: "desktop", funcs: {hidden: "IsNoviceMode()"} },
+ { title: "Search", toolTip: "Search ⌘F", target: this.setupSearcher(doc, "mySearcher"), ignoreClick: true, icon: "search", },
+ { title: "Files", toolTip: "Files", target: this.setupFilesystem(doc, "myFilesystem"), ignoreClick: true, icon: "folder-open", },
+ { title: "Tools", toolTip: "Tools", target: this.setupToolsBtnPanel(doc, "myTools"), ignoreClick: true, icon: "wrench", funcs: {hidden: "IsNoviceMode()"} },
+ { title: "Imports", toolTip: "Imports ⌘I", target: this.setupImportSidebar(doc, "myImports"), ignoreClick: true, icon: "upload", },
+ { title: "Closed", toolTip: "Recently Closed", target: this.setupRecentlyClosed(doc, "myRecentlyClosed"), ignoreClick: true, icon: "archive", },
+ { title: "Shared", toolTip: "Shared Docs", target: Doc.MySharedDocs, ignoreClick: true, icon: "users", funcs: {badgeValue: badgeValue}},
+ { title: "Trails", toolTip: "Trails ⌘R", target: Doc.UserDoc(), ignoreClick: true, icon: "pres-trail", funcs: {target: getActiveDashTrails}},
+ { title: "User Doc", toolTip: "User Doc", target: this.setupUserDocView(doc, "myUserDocView"), ignoreClick: true, icon: "address-card",funcs: {hidden: "IsNoviceMode()"} },
].map(tuple => ({...tuple, scripts:{onClick: 'selectMainMenu(self)'}}));
}
@@ -602,7 +602,7 @@ export class CurrentUserUtils {
const btnDescs = [// setup reactions to change the highlights on the undo/redo buttons -- would be better to encode this in the undo/redo buttons, but the undo/redo stacks are not wired up that way yet
{ scripts: { onClick: "undo()"}, opts: { title: "Undo", icon: "undo-alt", toolTip: "Undo ⌘Z" }},
- { scripts: { onClick: "redo()"}, opts: { title: "Redo", icon: "redo-alt", toolTip: "Redo ⌘R" }},
+ { scripts: { onClick: "redo()"}, opts: { title: "Redo", icon: "redo-alt", toolTip: "Redo ⌘⇧Z" }},
{ scripts: { }, opts: { title: "undoStack", layout: "<UndoStack>", toolTip: "Undo/Redo Stack"}}, // note: layout fields are hacks -- they don't actually run through the JSX parser (yet)
{ scripts: { }, opts: { title: "linker", layout: "<LinkingUI>", toolTip: "link started"}},
{ scripts: { }, opts: { title: "currently playing", layout: "<CurrentlyPlayingUI>", toolTip: "currently playing media"}},
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index b921b3116..8e4e0d8f3 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,10 +1,11 @@
import { action, computed, observable, ObservableSet } from 'mobx';
-import { Doc, Opt } from '../../fields/Doc';
-import { Animation } from '../../fields/DocSymbols';
+import { Doc, DocListCast, Opt } from '../../fields/Doc';
+import { AclAdmin, AclEdit, Animation } from '../../fields/DocSymbols';
import { Id } from '../../fields/FieldSymbols';
import { listSpec } from '../../fields/Schema';
import { Cast, DocCast, StrCast } from '../../fields/Types';
import { AudioField } from '../../fields/URLField';
+import { GetEffectiveAcl } from '../../fields/util';
import { CollectionViewType } from '../documents/DocumentTypes';
import { CollectionDockingView } from '../views/collections/CollectionDockingView';
import { TabDocView } from '../views/collections/TabDocView';
@@ -344,6 +345,9 @@ export function DocFocusOrOpen(doc: Doc, options: DocFocusOptions = { willZoomCe
});
}
};
+ if (Doc.IsDataProto(doc) && DocListCast(doc.proto_embeddings).some(embed => embed.hidden && [AclAdmin, AclEdit].includes(GetEffectiveAcl(embed)))) {
+ doc = DocListCast(doc.proto_embeddings).find(embed => embed.hidden && [AclAdmin, AclEdit].includes(GetEffectiveAcl(embed)))!;
+ }
if (doc.hidden) {
doc.hidden = false;
options.toggleTarget = false;
diff --git a/src/client/util/GroupManager.scss b/src/client/util/GroupManager.scss
index 253ed5d2a..673af16ee 100644
--- a/src/client/util/GroupManager.scss
+++ b/src/client/util/GroupManager.scss
@@ -7,33 +7,48 @@
.group-create {
display: flex;
flex-direction: column;
- height: 90%;
+ overflow: visible;
+ height: 100%;
+ width: 98.5%;
+ padding: 5px;
justify-content: space-between;
margin-left: 5px;
- input {
- border-radius: 5px;
- padding: 8px;
- min-width: 100%;
- border: 1px solid hsl(0, 0%, 80%);
- outline: none;
- height: 30;
-
- &:focus {
- border: 2.5px solid #2684FF;
- }
- }
-
p {
font-size: 20px;
text-align: left;
- color: black;
}
+ }
- button {
- align-self: flex-end;
+ .group-input {
+
+ input {
+ padding: 8px;
+ width: 100%;
+ outline: none;
+ border: none;
+ min-width: 100%;
+ border: 2px solid;
+ border-radius: 4px;
+ border-color: inherit;
+ background: white;
+ color: black;
+ height: 30;
}
}
+
+ .select-users {
+ margin-right: 3;
+ max-height: 30;
+ width: 100%;
+ display: inline-flex;
+ flex-direction: row;
+ border: 2px solid;
+ border-radius: 4px;
+ border-color: inherit;
+ background: white;
+ color: black;
+ }
}
@@ -55,11 +70,14 @@
.group-interface {
display: flex;
flex-direction: column;
+ overflow: hidden;
+ padding: 10px;
.overlay {
transform: translate(-10px, -10px);
width: 400px;
height: 320px;
+ overflow: hidden;
}
.delete-button {
@@ -81,7 +99,6 @@
font-size: 20px;
text-align: left;
margin-right: 15px;
- color: black;
}
}
@@ -94,18 +111,24 @@
margin-left: 5;
width: 50px;
cursor: pointer;
+ display: flex;
+ flex-direction: row;
+ }
+
+ .style-divider {
+ width: 100%;
+ height: 1px;
}
.group-body {
justify-content: space-between;
- height: 220;
- background-color: #e8e8e8;
+ height: 225;
padding-right: 1em;
justify-content: space-around;
text-align: left;
- overflow-y: auto;
+ overflow-y: hidden;
width: 100%;
.group-row {
@@ -117,7 +140,6 @@
.group-name {
max-width: 65%;
margin: 0 10;
- color: black;
}
.group-info {
diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx
index da947aba6..5802d5ee0 100644
--- a/src/client/util/GroupManager.tsx
+++ b/src/client/util/GroupManager.tsx
@@ -15,6 +15,7 @@ import { SharingManager, User } from './SharingManager';
import { listSpec } from '../../fields/Schema';
import { DateField } from '../../fields/DateField';
import { Id } from '../../fields/FieldSymbols';
+import { Button, IconButton, Size } from 'browndash-components';
/**
* Interface for options for the react-select component
@@ -280,47 +281,59 @@ export class GroupManager extends React.Component<{}> {
*/
private get groupCreationModal() {
const contents = (
- <div className="group-create">
+ <div className="group-create" style={{background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor)}}>
<div className="group-heading" style={{ marginBottom: 0 }}>
<p>
<b>New Group</b>
</p>
- <div
- className={'close-button'}
- onClick={action(() => {
- this.createGroupModalOpen = false;
- TaskCompletionBox.taskCompleted = false;
- })}>
- <FontAwesomeIcon icon={'times'} color={'black'} size={'lg'} />
+ <div className="close-button">
+ <Button
+ icon={<FontAwesomeIcon icon={'times'} size={'lg'} />}
+ onClick={action(() => {
+ this.createGroupModalOpen = false;
+ TaskCompletionBox.taskCompleted = false;
+ })}
+ color={StrCast(Doc.UserDoc().userColor)}
+ />
</div>
</div>
- <input className="group-input" ref={this.inputRef} onKeyDown={this.handleKeyDown} autoFocus type="text" placeholder="Group name" onChange={action(() => (this.buttonColour = this.inputRef.current?.value ? 'black' : '#979797'))} />
- <Select
- isMulti
- options={this.options}
- onChange={this.handleChange}
- placeholder={'Select users'}
- value={this.selectedUsers}
- closeMenuOnSelect={false}
- styles={{
- dropdownIndicator: (base, state) => ({
- ...base,
- transition: '0.5s all ease',
- transform: state.selectProps.menuIsOpen ? 'rotate(180deg)' : undefined,
- }),
- multiValue: base => ({
- ...base,
- maxWidth: '50%',
-
- '&:hover': {
- maxWidth: 'unset',
- },
- }),
- }}
- />
- <button ref={this.createGroupButtonRef} onClick={this.createGroup} style={{ background: this.buttonColour }} disabled={this.buttonColour === '#979797'}>
- Create
- </button>
+ <div className="group-input" style={{border: StrCast(Doc.UserDoc().userColor)}} >
+ <input ref={this.inputRef} onKeyDown={this.handleKeyDown} autoFocus type="text" placeholder="Group name" onChange={action(() => (this.buttonColour = this.inputRef.current?.value ? 'black' : '#979797'))} />
+ </div>
+ <div style={{border: StrCast(Doc.UserDoc().userColor)}}>
+ <Select
+ className="select-users"
+ isMulti
+ options={this.options}
+ onChange={this.handleChange}
+ placeholder={'Select users'}
+ value={this.selectedUsers}
+ closeMenuOnSelect={false}
+ styles={{
+ control: () => ({
+ display: 'inline-flex',
+ width: '100%',
+ }),
+ indicatorSeparator: () => ({
+ display: 'inline-flex',
+ visibility: 'hidden',
+ }),
+ indicatorsContainer: () => ({
+ display: 'inline-flex',
+ textDecorationColor: 'black',
+ }),
+ valueContainer: () => ({
+ display: 'inline-flex',
+ fontStyle: StrCast(Doc.UserDoc().userColor),
+ color: StrCast(Doc.UserDoc().userColor),
+ width: '100%',
+ }),
+ }}
+ />
+ </div>
+ <div className={"create-button"}>
+ <Button text={"Create"} type={"tertiary"} color={StrCast(Doc.UserDoc().userColor)} onClick={this.createGroup} />
+ </div>
</div>
);
@@ -353,37 +366,34 @@ export class GroupManager extends React.Component<{}> {
const groups = this.groupSort === 'ascending' ? this.allGroups.sort(sortGroups) : this.groupSort === 'descending' ? this.allGroups.sort(sortGroups).reverse() : this.allGroups;
return (
- <div className="group-interface">
+ <div className="group-interface" style={{background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor)}}>
{this.groupCreationModal}
{this.currentGroup ? <GroupMemberView group={this.currentGroup} onCloseButtonClick={action(() => (this.currentGroup = undefined))} /> : null}
<div className="group-heading">
<p>
<b>Manage Groups</b>
</p>
- <button onClick={action(() => (this.createGroupModalOpen = true))}>
- <FontAwesomeIcon icon={'plus'} size={'sm'} /> Create Group
- </button>
- <div className={'close-button'} onClick={this.close}>
- <FontAwesomeIcon icon={'times'} color={'black'} size={'lg'} />
+ <Button icon={<FontAwesomeIcon icon={'plus'}/>} iconPlacement={'left'} text={"Create Group"} type={"tertiary"} color={StrCast(Doc.UserDoc().userColor)} onClick={action(() => (this.createGroupModalOpen = true))} />
+ <div className={'close-button'} >
+ <Button
+ icon={<FontAwesomeIcon icon={'times'} size={'lg'} />}
+ onClick={this.close}
+ color={StrCast(Doc.UserDoc().userColor)}
+ />
</div>
</div>
<div className="main-container">
<div className="sort-groups" onClick={action(() => (this.groupSort = this.groupSort === 'ascending' ? 'descending' : this.groupSort === 'descending' ? 'none' : 'ascending'))}>
- Name{' '}
- {this.groupSort === 'ascending' ? (
- <FontAwesomeIcon icon={'caret-up'} size={'xs'} />
- ) : this.groupSort === 'descending' ? (
- <FontAwesomeIcon icon={'caret-down'} size={'xs'} />
- ) : (
- <FontAwesomeIcon icon={'caret-right'} size={'xs'} />
- )}
+ Name
+ <IconButton icon={<FontAwesomeIcon icon={this.groupSort === 'ascending' ? 'caret-up' : this.groupSort === 'descending' ? 'caret-down' : 'caret-right'}/>} size={Size.XSMALL} color={StrCast(Doc.UserDoc().userColor)} />
</div>
- <div className="group-body">
+ <div className={'style-divider'} style={{background: StrCast(Doc.UserDoc().userColor)}}/>
+ <div className="group-body" style={{background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor)}}>
{groups.map(group => (
<div className="group-row" key={StrCast(group.title || group.groupName)}>
<div className="group-name">{StrCast(group.title || group.groupName)}</div>
<div className="group-info" onClick={action(() => (this.currentGroup = group))}>
- <FontAwesomeIcon icon={'info-circle'} color={'#e8e8e8'} size={'sm'} style={{ backgroundColor: '#1e89d7', borderRadius: '100%', border: '1px solid #1e89d7' }} />
+ <IconButton icon={<FontAwesomeIcon icon={'info-circle'} />} size={Size.XSMALL} color={StrCast(Doc.UserDoc().userColor)} onClick={action(() => (this.currentGroup = group))} />
</div>
</div>
))}
diff --git a/src/client/util/GroupMemberView.scss b/src/client/util/GroupMemberView.scss
index 2eb164988..d50569b26 100644
--- a/src/client/util/GroupMemberView.scss
+++ b/src/client/util/GroupMemberView.scss
@@ -1,6 +1,9 @@
.editing-interface {
width: 100%;
height: 100%;
+ padding: 10px;
+ float: right;
+ overflow: visible;
hr {
margin-top: 20;
@@ -10,7 +13,6 @@
outline: none;
border-radius: 5px;
border: 0px;
- color: #fcfbf7;
text-transform: none;
letter-spacing: 2px;
font-size: 75%;
@@ -37,8 +39,6 @@
text-align: center;
border: none;
outline: none;
- color: black;
- margin-top: -5;
height: 20;
text-overflow: ellipsis;
background: none;
@@ -61,21 +61,36 @@
margin-bottom: 25;
.add-member-dropdown {
- width: 65%;
- margin: 0 5;
+ margin-right: 3;
+ max-height: 30;
+ width: 250px;
+ display: inline-flex;
+ flex-direction: row;
+ border: 2px solid;
+ border-radius: 4px;
+ border-color: inherit;
+ background: white;
+ color: black;
+ }
- input {
- height: 30;
- }
+ .delete-button {
+ align-self: center;
+ background: inherit;
}
}
}
+ .style-divider {
+ width: 98%;
+ height: 1px;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ }
+
.editing-contents {
overflow-y: auto;
height: 62%;
width: 100%;
- color: black;
margin-top: -15px;
.editing-row {
diff --git a/src/client/util/GroupMemberView.tsx b/src/client/util/GroupMemberView.tsx
index b7f89794d..f2050dc61 100644
--- a/src/client/util/GroupMemberView.tsx
+++ b/src/client/util/GroupMemberView.tsx
@@ -8,6 +8,7 @@ import { StrCast } from "../../fields/Types";
import { MainViewModal } from "../views/MainViewModal";
import { GroupManager, UserOptions } from "./GroupManager";
import "./GroupMemberView.scss";
+import { Button, IconButton, Size } from "browndash-components";
interface GroupMemberViewProps {
group: Doc;
@@ -28,7 +29,7 @@ export class GroupMemberView extends React.Component<GroupMemberViewProps> {
const hasEditAccess = GroupManager.Instance.hasEditAccess(this.props.group);
return (!this.props.group ? null :
- <div className="editing-interface">
+ <div className="editing-interface" style={{background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor)}}>
<div className="editing-header">
<input
className="group-title"
@@ -38,28 +39,48 @@ export class GroupMemberView extends React.Component<GroupMemberViewProps> {
disabled={!hasEditAccess}
>
</input>
- <div className={"memberView-closeButton"} onClick={action(this.props.onCloseButtonClick)}>
- <FontAwesomeIcon icon={"times"} color={"black"} size={"lg"} />
+ <div className={"memberView-closeButton"} >
+ <Button
+ icon={<FontAwesomeIcon icon={'times'} size={'lg'} />}
+ onClick={action(this.props.onCloseButtonClick)}
+ color={StrCast(Doc.UserDoc().userColor)}
+ />
</div>
{GroupManager.Instance.hasEditAccess(this.props.group) ?
<div className="group-buttons">
- <div className="add-member-dropdown">
- <Select
+ <div style={{border: StrCast(Doc.UserDoc().userColor)}} >
+ <Select
+ className="add-member-dropdown"
isSearchable={true}
options={options}
onChange={selectedOption => GroupManager.Instance.addMemberToGroup(this.props.group, (selectedOption as UserOptions).value)}
placeholder={"Add members"}
value={null}
styles={{
- dropdownIndicator: (base, state) => ({
- ...base,
- transition: '0.5s all ease',
- transform: state.selectProps.menuIsOpen ? 'rotate(180deg)' : undefined
- })
+ control: () => ({
+ display: 'inline-flex',
+ width: '100%',
+ }),
+ indicatorSeparator: () => ({
+ display: 'inline-flex',
+ visibility: 'hidden',
+ }),
+ indicatorsContainer: () => ({
+ display: 'inline-flex',
+ textDecorationColor: 'black',
+ }),
+ valueContainer: () => ({
+ display: 'inline-flex',
+ fontStyle: StrCast(Doc.UserDoc().userColor),
+ color: StrCast(Doc.UserDoc().userColor),
+ width: '100%',
+ }),
}}
/>
</div>
- <button onClick={() => GroupManager.Instance.deleteGroup(this.props.group)}>Delete group</button>
+ <div className={"delete-button"}>
+ <Button text={"Delete Group"} type={"tertiary"} color={StrCast(Doc.UserDoc().userColor)} onClick={() => GroupManager.Instance.deleteGroup(this.props.group)} />
+ </div>
</div> :
null}
<div
@@ -69,7 +90,7 @@ export class GroupMemberView extends React.Component<GroupMemberViewProps> {
Emails {this.memberSort === "ascending" ? "↑" : this.memberSort === "descending" ? "↓" : ""} {/* → */}
</div>
</div>
- <hr />
+ <div className={'style-divider'} style={{background: StrCast(Doc.UserDoc().userColor)}}/>
<div className="editing-contents"
style={{ height: hasEditAccess ? "62%" : "85%" }}
>
@@ -83,7 +104,7 @@ export class GroupMemberView extends React.Component<GroupMemberViewProps> {
</div>
{hasEditAccess ?
<div className={"remove-button"} onClick={() => GroupManager.Instance.removeMemberFromGroup(this.props.group, member)}>
- <FontAwesomeIcon icon={"trash-alt"} size={"sm"} />
+ <IconButton icon={<FontAwesomeIcon icon={'trash-alt'} />} size={Size.XSMALL} color={StrCast(Doc.UserDoc().userColor)} onClick={() => GroupManager.Instance.removeMemberFromGroup(this.props.group, member)} />
</div>
: null}
</div>
diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx
index 043f0f1f3..d0f459291 100644
--- a/src/client/util/InteractionUtils.tsx
+++ b/src/client/util/InteractionUtils.tsx
@@ -178,7 +178,7 @@ export namespace InteractionUtils {
filter: mask ? `url(#mask${defGuid})` : undefined,
opacity: 1.0,
// opacity: strokeWidth !== width ? 0.5 : undefined,
- pointerEvents: pevents as any,
+ pointerEvents: (pevents as any) === 'all' ? 'visiblepainted' : (pevents as any),
stroke: color ?? 'rgb(0, 0, 0)',
strokeWidth: strokeWidth,
strokeLinecap: lineCap as any,
diff --git a/src/client/util/SharingManager.scss b/src/client/util/SharingManager.scss
index b11e694ff..c9f86f0e1 100644
--- a/src/client/util/SharingManager.scss
+++ b/src/client/util/SharingManager.scss
@@ -2,10 +2,6 @@
width: 600px;
// height: 360px;
- .overlay {
- transform: translate(-20px, -20px);
- }
-
.select {
text-align: justify;
text-align-last: end
@@ -33,12 +29,7 @@
}
.share-copy-link {
- display: inline;
border-radius: 4px;
- border: solid gray 1px;
- font-size: x-small;
- background: #E8E8E8;
- color: black;
margin-top: -15px;
margin-bottom: 15px;
width: fit-content;
@@ -50,13 +41,22 @@
display: flex;
margin-bottom: 20px;
align-items: center;
- height: 36;
+ max-height: 28;
.user-search {
+ max-height: 30;
width: 90%;
+ display: inline-flex;
+ flex-direction: row;
+ border: 2px solid;
+ border-radius: 4px;
+ border-color: inherit;
+ background: white;
+ color: black;
input {
- height: 30;
+ height: 20px;
+ width: 100px;
}
}
@@ -68,14 +68,12 @@
text-align-last: end;
font-size: 13px;
min-width: 90px;
- height: 36;
+ height: 28;
margin-left: 2px;
}
.share-button {
- height: 36;
margin-left: 3%;
- background-color: black;
}
}
@@ -131,6 +129,7 @@
display: flex;
top:0;
flex-direction: column;
+ border-radius: 4px;
.user-sort {
text-align: left;
@@ -147,11 +146,12 @@
.groups-list,
.users-list {
font-style: italic;
- background: #e8e8e8;
- border: 2px solid gray;
+ border: 2px solid;
padding-left: 10px;
padding-right: 10px;
width: 97%;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
overflow-y: scroll;
overflow-x: hidden;
text-align: left;
@@ -160,7 +160,6 @@
align-items: center;
text-align: center;
justify-content: center;
- color: black;
height: 250px;
margin: 0 2;
@@ -175,7 +174,6 @@
outline: none;
border-radius: 5px;
border: 0px;
- color: #fcfbf7;
text-transform: none;
letter-spacing: 2px;
font-size: 75%;
@@ -194,11 +192,10 @@
font-size: 20px;
text-align: left;
margin: 0 0 20px 0;
- color: black;
}
.hr-substitute {
- border: solid black 0.5px;
+ border: solid 0.5px;
margin-top: 20px;
}
@@ -223,11 +220,12 @@
height: 25px;
padding-left: 2;
width: 97%;
+ border-radius: 4px;
margin-top: 10px;
margin-left: -8px;
font-size: 14;
margin-bottom: -4;
- border: 2px solid gray;
+ border: 2px solid;
border-bottom: none;
align-items: center;
display: flex;
@@ -237,11 +235,12 @@
height: 25px;
padding-left: 2;
width: 97%;
+ border-radius: 4px;
margin-top: 10px;
- margin-left: -.5px;
+ margin-left: -8px;
font-size: 14;
margin-bottom: -4;
- border: 2px solid gray;
+ border: 2px solid;
border-bottom: none;
align-items: center;
display: flex;
@@ -264,7 +263,7 @@
font-weight: normal;
padding: 3px;
- border-bottom: 0.5px solid grey;
+ border-bottom: 0.5px solid;
.group-info {
cursor: pointer;
@@ -368,35 +367,35 @@
margin-top: 20px;
}
- .link-container {
- display: flex;
- flex-direction: row;
- margin-bottom: 10px;
- margin-left: auto;
- margin-right: auto;
-
- .link-box,
- .copy {
- padding: 10px;
- border-radius: 10px;
- padding: 10px;
- border: solid black 1px;
- }
-
- .link-box {
- background: white;
- color: blue;
- text-decoration: underline;
- }
-
- .copy {
- margin-left: 20px;
- cursor: alias;
- border-radius: 50%;
- width: 42px;
- height: 42px;
- transition: 1.5s all ease;
- padding-top: 12px;
- }
- }
+ // .link-container {
+ // display: flex;
+ // flex-direction: row;
+ // margin-bottom: 10px;
+ // margin-left: auto;
+ // margin-right: auto;
+
+ // .link-box,
+ // .copy {
+ // padding: 10px;
+ // border-radius: 10px;
+ // padding: 10px;
+ // border: solid black 1px;
+ // }
+
+ // .link-box {
+ // background: white;
+ // color: blue;
+ // text-decoration: underline;
+ // }
+
+ // .copy {
+ // margin-left: 20px;
+ // cursor: alias;
+ // border-radius: 50%;
+ // width: 42px;
+ // height: 42px;
+ // transition: 1.5s all ease;
+ // padding-top: 12px;
+ // }
+ // }
} \ No newline at end of file
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 33c9992d0..cadcb1f8a 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -1,5 +1,5 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Colors } from 'browndash-components';
+import { Button, IconButton, Size, Type } from 'browndash-components';
import { concat, intersection } from 'lodash';
import { action, computed, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
@@ -80,7 +80,7 @@ export class SharingManager extends React.Component<{}> {
@observable private showUserOptions: boolean = false; // whether to show individuals as options when sharing (in the react-select component)
@observable private showGroupOptions: boolean = false; // // whether to show groups as options when sharing (in the react-select component)
private populating: boolean = false; // whether the list of users is populating or not
- @observable private overrideNested: boolean = false; // whether child docs in a collection/dashboard should be changed to be less private - initially selected so default is override
+ @observable private upgradeNested: boolean = false; // whether child docs in a collection/dashboard should be changed to be less private - initially selected so default is upgrade all
@observable private layoutDocAcls: boolean = false; // whether the layout doc or data doc's acls are to be used
@observable private myDocAcls: boolean = false; // whether the My Docs checkbox is selected or not
@observable private _buttonDown = false;
@@ -97,7 +97,7 @@ export class SharingManager extends React.Component<{}> {
DictationOverlay.Instance.hasActiveModal = true;
this.isOpen = this.targetDoc !== undefined;
this.permissions = SharingPermissions.Augment;
- this.overrideNested = true;
+ this.upgradeNested = true;
});
};
@@ -162,7 +162,7 @@ export class SharingManager extends React.Component<{}> {
const acl = `acl-${normalizeEmail(user.email)}`;
const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.rootDoc);
docs.map(doc => (this.layoutDocAcls || doc.dockingConfig ? doc : Doc.GetProto(doc))).forEach(doc => {
- distributeAcls(acl, permission as SharingPermissions, doc, undefined, this.overrideNested ? true : undefined);
+ distributeAcls(acl, permission as SharingPermissions, doc, undefined, this.upgradeNested ? true : undefined);
if (permission !== SharingPermissions.None) {
Doc.AddDocToList(sharingDoc, doc.dockingConfig ? dashStorage : storage, doc);
} else GetEffectiveAcl(doc, user.email) === AclPrivate && Doc.RemoveDocFromList(sharingDoc, ((doc.createdFrom as Doc) || doc).dockingConfig ? dashStorage : storage, (doc.createdFrom as Doc) || doc);
@@ -180,7 +180,7 @@ export class SharingManager extends React.Component<{}> {
const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.rootDoc);
docs.map(doc => (this.layoutDocAcls || doc.dockingConfig ? doc : Doc.GetProto(doc))).forEach(doc => {
- distributeAcls(acl, permission as SharingPermissions, doc, undefined, this.overrideNested ? true : undefined);
+ distributeAcls(acl, permission as SharingPermissions, doc, undefined, this.upgradeNested ? true : undefined);
if (group instanceof Doc) {
Doc.AddDocToList(group, 'docsShared', doc);
@@ -525,14 +525,10 @@ export class SharingManager extends React.Component<{}> {
const permissions = uniform ? StrCast(targetDoc?.[groupKey]) : '-multiple-';
return !permissions ? null : (
- <div key={groupKey} className={'container'}>
+ <div key={groupKey} className={'container'} style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor) }}>
<div className={'padding'}>{StrCast(group.title)}</div>
&nbsp;
- {group instanceof Doc ? (
- <div className="group-info" onClick={action(() => (GroupManager.Instance.currentGroup = group))}>
- <FontAwesomeIcon icon={'info-circle'} color={'#e8e8e8'} size={'sm'} style={{ backgroundColor: '#1e89d7', borderRadius: '100%', border: '1px solid #1e89d7' }} />
- </div>
- ) : null}
+ {group instanceof Doc ? <IconButton icon={<FontAwesomeIcon icon={'info-circle'} />} size={Size.XSMALL} color={StrCast(Doc.UserDoc().userColor)} onClick={action(() => (GroupManager.Instance.currentGroup = group))} /> : null}
<div className={'edit-actions'}>
{admin || this.myDocAcls ? (
<select className={`permissions-dropdown-${permissions}`} value={permissions} onChange={e => this.setInternalGroupSharing(group, e.currentTarget.value)}>
@@ -551,34 +547,28 @@ export class SharingManager extends React.Component<{}> {
return (
<div className="sharing-interface">
{GroupManager.Instance?.currentGroup ? <GroupMemberView group={GroupManager.Instance.currentGroup} onCloseButtonClick={action(() => (GroupManager.Instance.currentGroup = undefined))} /> : null}
- <div className="sharing-contents"
+ <div
+ className="sharing-contents"
style={{
background: StrCast(Doc.UserDoc().userBackgroundColor),
- color: StrCast(Doc.UserDoc().userColor)
- }}
- >
- <p className="share-title">
- <div className="share-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/properties/sharing-and-permissions/', '_blank')}>
- <FontAwesomeIcon icon={'question-circle'} size={'sm'} onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/properties/sharing-and-permissions/', '_blank')} />
+ color: StrCast(Doc.UserDoc().userColor),
+ }}>
+ <p className="share-title" style={{ color: StrCast(Doc.UserDoc().userColor) }}>
+ <div className="share-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/features/collaboration/', '_blank')}>
+ <FontAwesomeIcon icon={'question-circle'} size={'sm'} onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/features/collaboration/', '_blank')} />
</div>
<b>Share </b>
{this.focusOn(docs.length < 2 ? StrCast(targetDoc?.title, 'this document') : '-multiple-')}
</p>
- <button
- className="share-copy-link"
- style={{ background: this._buttonDown ? Colors.LIGHT_BLUE : undefined }}
- onPointerDown={action(e => (this._buttonDown = true))}
- onPointerUp={action(e => (this._buttonDown = false))}
- onClick={this.copyURL}>
- <FontAwesomeIcon title="Copy Public URL" icon="copy" size="sm" />
- &nbsp; Copy Public URL
- </button>
- <div className="close-button" onClick={this.close}>
- <FontAwesomeIcon icon="times" color="black" size="lg" />
+ <div className="share-copy-link">
+ <Button type={Type.TERT} color={StrCast(Doc.UserDoc().userColor)} icon={<FontAwesomeIcon icon={'copy'} size="sm" />} iconPlacement={'left'} text={'Copy Guest URL'} onClick={this.copyURL} />
+ </div>
+ <div className="close-button">
+ <Button icon={<FontAwesomeIcon icon={'times'} size={'lg'} />} onClick={this.close} color={StrCast(Doc.UserDoc().userColor)} />
</div>
{admin ? (
<div className="share-container">
- <div className="share-setup">
+ <div className="share-setup" style={{ border: StrCast(Doc.UserDoc().userColor) }}>
<Select
className="user-search"
placeholder="Enter user or group name..."
@@ -590,9 +580,24 @@ export class SharingManager extends React.Component<{}> {
onChange={this.handleUsersChange}
value={this.selectedUsers}
styles={{
+ control: () => ({
+ display: 'inline-flex',
+ width: '100%',
+ }),
indicatorSeparator: () => ({
+ display: 'inline-flex',
visibility: 'hidden',
}),
+ indicatorsContainer: () => ({
+ display: 'inline-flex',
+ textDecorationColor: 'black',
+ }),
+ valueContainer: () => ({
+ display: 'inline-flex',
+ fontStyle: StrCast(Doc.UserDoc().userColor),
+ color: StrCast(Doc.UserDoc().userColor),
+ width: '100%',
+ }),
}}
/>
<div className="permissions-select">
@@ -600,9 +605,9 @@ export class SharingManager extends React.Component<{}> {
{this.sharingOptions(true)}
</select>
</div>
- <button ref={this.shareDocumentButtonRef} className="share-button" onClick={this.share}>
- Share
- </button>
+ <div className="share-button">
+ <Button text={'SHARE'} type={Type.TERT} color={StrCast(Doc.UserDoc().userColor)} onClick={this.share} />
+ </div>
</div>
<div className="sort-checkboxes">
<input type="checkbox" onChange={action(() => (this.showUserOptions = !this.showUserOptions))} /> <label style={{ marginRight: 10 }}>Individuals</label>
@@ -612,7 +617,7 @@ export class SharingManager extends React.Component<{}> {
<div className="acl-container">
{Doc.noviceMode ? null : (
<div className="layoutDoc-acls">
- <input type="checkbox" onChange={action(() => (this.overrideNested = !this.overrideNested))} checked={this.overrideNested} /> <label>Override Nested </label>
+ <input type="checkbox" onChange={action(() => (this.upgradeNested = !this.upgradeNested))} checked={this.upgradeNested} /> <label>Upgrade Nested </label>
<input type="checkbox" onChange={action(() => (this.layoutDocAcls = !this.layoutDocAcls))} checked={this.layoutDocAcls} /> <label>Layout</label>
</div>
)}
@@ -627,12 +632,16 @@ export class SharingManager extends React.Component<{}> {
</div>
</div>
)}
- <div className="main-container">
+ <div className="main-container" style={{ color: StrCast(Doc.UserDoc().userColor), border: StrCast(Doc.UserDoc().userColor) }}>
<div className={'individual-container'}>
<div className="user-sort" onClick={action(() => (this.individualSort = this.individualSort === 'ascending' ? 'descending' : this.individualSort === 'descending' ? 'none' : 'ascending'))}>
<div className="title-individual">
- Individuals &nbsp;
- <FontAwesomeIcon icon={this.individualSort === 'ascending' ? 'caret-up' : this.individualSort === 'descending' ? 'caret-down' : 'caret-right'} size="xs" />
+ Individuals
+ <IconButton
+ icon={<FontAwesomeIcon icon={this.individualSort === 'ascending' ? 'caret-up' : this.individualSort === 'descending' ? 'caret-down' : 'caret-right'} />}
+ size={Size.XSMALL}
+ color={StrCast(Doc.UserDoc().userColor)}
+ />
</div>
</div>
<div className="users-list">{userListContents}</div>
@@ -640,12 +649,13 @@ export class SharingManager extends React.Component<{}> {
<div className={'group-container'}>
<div className="user-sort" onClick={action(() => (this.groupSort = this.groupSort === 'ascending' ? 'descending' : this.groupSort === 'descending' ? 'none' : 'ascending'))}>
<div className="title-group">
- Groups &nbsp;
- <div className="group-info" onClick={action(() => GroupManager.Instance?.open())}>
- <FontAwesomeIcon icon={'info-circle'} color={'#e8e8e8'} size={'sm'} style={{ backgroundColor: '#1e89d7', borderRadius: '100%', border: '1px solid #1e89d7' }} />
- </div>
- &nbsp;
- <FontAwesomeIcon icon={this.groupSort === 'ascending' ? 'caret-up' : this.groupSort === 'descending' ? 'caret-down' : 'caret-right'} size="xs" />
+ Groups
+ <IconButton icon={<FontAwesomeIcon icon={'info-circle'} />} size={Size.XSMALL} color={StrCast(Doc.UserDoc().userColor)} onClick={action(() => GroupManager.Instance.open())} />
+ <IconButton
+ icon={<FontAwesomeIcon icon={this.groupSort === 'ascending' ? 'caret-up' : this.groupSort === 'descending' ? 'caret-down' : 'caret-right'} />}
+ size={Size.XSMALL}
+ color={StrCast(Doc.UserDoc().userColor)}
+ />
</div>
</div>
<div className={'groups-list'}>{groupListContents}</div>
@@ -657,13 +667,6 @@ export class SharingManager extends React.Component<{}> {
}
render() {
- return <MainViewModal
- contents={this.sharingInterface}
- isDisplayed={this.isOpen}
- interactive={true}
- dialogueBoxDisplayedOpacity={this.dialogueBoxOpacity}
- overlayDisplayedOpacity={this.overlayOpacity}
- closeOnExternalClick={this.close}
- />;
+ return <MainViewModal contents={this.sharingInterface} isDisplayed={this.isOpen} interactive={true} dialogueBoxDisplayedOpacity={this.dialogueBoxOpacity} overlayDisplayedOpacity={this.overlayOpacity} closeOnExternalClick={this.close} />;
}
}
diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss
index 1361d99fc..588eff1d1 100644
--- a/src/client/views/ContextMenu.scss
+++ b/src/client/views/ContextMenu.scss
@@ -52,13 +52,29 @@
user-select: none;
transition: all 0.1s;
border-style: none;
- // padding: 10px 0px 10px 0px;
+ position: relative;
white-space: nowrap;
font-size: 13px;
letter-spacing: 2px;
text-transform: uppercase;
padding-right: 30px;
+ .contextMenu-item-background {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 0;
+ filter: opacity(0);
+ }
+
+ &:hover {
+ .contextMenu-item-background {
+ filter: opacity(0.2) !important;
+ }
+ }
+
.contextMenu-item-icon-background {
pointer-events: all;
background-color: transparent;
@@ -133,11 +149,6 @@
// border-top: solid 1px; //TODO:glr clean
}
-.contextMenu-item:hover {
- transition: all 0.1s ease;
- background: $light-blue;
-}
-
.contextMenu-description {
margin-left: 5px;
text-align: left;
diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx
index d54d4dc7b..8412a9aae 100644
--- a/src/client/views/ContextMenu.tsx
+++ b/src/client/views/ContextMenu.tsx
@@ -192,11 +192,11 @@ export class ContextMenu extends React.Component {
}
return this.filteredItems.map((value, index) =>
Array.isArray(value) ? (
- <div className="contextMenu-group"
+ <div
+ className="contextMenu-group"
style={{
- background: StrCast(Doc.UserDoc().userVariantColor)
- }}
- >
+ background: StrCast(Doc.UserDoc().userVariantColor),
+ }}>
<div className="contextMenu-description">{value.join(' -> ')}</div>
</div>
) : (
@@ -219,16 +219,18 @@ export class ContextMenu extends React.Component {
this._height = Number(getComputedStyle(r).height.replace('px', ''));
}
})}
- style={{
- left: this.pageX, ...(this._yRelativeToTop ? { top: this.pageY } : { bottom: this.pageY }),
- background: StrCast(Doc.UserDoc().userBackgroundColor)
+ style={{
+ left: this.pageX,
+ ...(this._yRelativeToTop ? { top: this.pageY } : { bottom: this.pageY }),
+ background: StrCast(Doc.UserDoc().userBackgroundColor),
+ color: StrCast(Doc.UserDoc().userColor),
}}>
{!this.itemsNeedSearch ? null : (
<span className={'search-icon'}>
<span className="icon-background">
<FontAwesomeIcon icon="search" size="lg" />
</span>
- <input className="contextMenu-item contextMenu-description search" type="text" placeholder="Filter Menu..." value={this._searchString} onKeyDown={this.onKeyDown} onChange={this.onChange} autoFocus />
+ <input style={{ color: 'black' }} className="contextMenu-item contextMenu-description search" type="text" placeholder="Filter Menu..." value={this._searchString} onKeyDown={this.onKeyDown} onChange={this.onChange} autoFocus />
</span>
)}
{this.menuItems}
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx
index 33f250986..daa2c152a 100644
--- a/src/client/views/ContextMenuItem.tsx
+++ b/src/client/views/ContextMenuItem.tsx
@@ -4,6 +4,8 @@ import { observer } from 'mobx-react';
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { UndoManager } from '../util/UndoManager';
+import { Doc } from '../../fields/Doc';
+import { StrCast } from '../../fields/Types';
export interface OriginalMenuProps {
description: string;
@@ -90,6 +92,11 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
</span>
) : null}
<div className="contextMenu-description">{this.props.description.replace(':', '')}</div>
+ <div className={`contextMenu-item-background`}
+ style={{
+ background: StrCast(Doc.UserDoc().userColor)
+ }}
+ />
</div>
);
} else if ('subitems' in this.props) {
@@ -103,6 +110,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
style={{
marginLeft: window.innerHeight - this._overPosX - 50 > 0 ? '90%' : '20%',
marginTop,
+ background: StrCast(Doc.UserDoc().userBackgroundColor)
}}>
{this._items.map(prop => (
<ContextMenuItem {...prop} key={prop.description} closeMenu={this.props.closeMenu} />
@@ -133,6 +141,11 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
{this.props.description}
<FontAwesomeIcon icon={'angle-right'} size="lg" style={{ position: 'absolute', right: '10px' }} />
</div>
+ <div className={`contextMenu-item-background`}
+ style={{
+ background: StrCast(Doc.UserDoc().userColor)
+ }}
+ />
{submenu}
</div>
);
diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx
index 1a5781df0..ae55c8ebf 100644
--- a/src/client/views/DashboardView.tsx
+++ b/src/client/views/DashboardView.tsx
@@ -199,7 +199,7 @@ export class DashboardView extends React.Component {
<div
className="dashboard-container"
key={dashboard[Id]}
- style={{ background: this.isUnviewedSharedDashboard(dashboard) && this.selectedDashboardGroup === DashboardGroup.SharedDashboards ? 'green' : shared ? 'blue' : '' }}
+ style={{ background: this.isUnviewedSharedDashboard(dashboard) && this.selectedDashboardGroup === DashboardGroup.SharedDashboards ? '#6CB982' : shared ? variant : '' }}
onContextMenu={e => this.onContextMenu(dashboard, e)}
onClick={e => this.clickDashboard(e, dashboard)}>
<img
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 3522830e5..bab07ac96 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -831,7 +831,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
&nbsp;
{shareSymbolIcon + ' ' + shareMode}
&nbsp;
- {!Doc.noviceMode ? (
+ {/* {!Doc.noviceMode ? (
<div className="checkbox">
<div className="checkbox-box">
<input type="checkbox" checked={this.showLayoutAcl} onChange={action(() => (this.showLayoutAcl = !this.showLayoutAcl))} />
@@ -839,7 +839,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
<div className="checkbox-text"> Layout </div>
</div>
) : null}
- &nbsp;
+ &nbsp; */}
</div>
</div>
) : (
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 347c40c18..7b693c8da 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -261,6 +261,18 @@ export class KeyManager {
case 't':
PromiseValue(Cast(Doc.UserDoc()['tabs-button-tools'], Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv }));
break;
+ case 'i':
+ const importBtn = DocListCast(Doc.MyLeftSidebarMenu.data).find(d => d.target === Doc.MyImports);
+ if (importBtn) {
+ MainView.Instance.selectMenu(importBtn);
+ }
+ break;
+ case 's':
+ const trailsBtn = DocListCast(Doc.MyLeftSidebarMenu.data).find(d => d.target === Doc.MyTrails);
+ if (trailsBtn) {
+ MainView.Instance.selectMenu(trailsBtn);
+ }
+ break;
case 'f':
if (SelectionManager.Views().length === 1 && SelectionManager.Views()[0].ComponentView?.search) {
SelectionManager.Views()[0].ComponentView?.search?.('', false, false);
@@ -272,14 +284,10 @@ export class KeyManager {
}
break;
case 'e':
- Doc.ActiveTool = InkTool.Eraser;
+ Doc.ActiveTool = (Doc.ActiveTool === InkTool.Eraser ? InkTool.None : InkTool.Eraser);
break;
case 'p':
- Doc.ActiveTool = InkTool.Pen;
- break;
- case 'o':
- const target = SelectionManager.Docs().lastElement();
- target && CollectionDockingView.OpenFullScreen(target);
+ Doc.ActiveTool = (Doc.ActiveTool === InkTool.Pen ? InkTool.None : InkTool.Pen);
break;
case 'r':
preventDefault = false;
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index 0c377730e..b3faff442 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -47,6 +47,10 @@ h1,
align-items: center;
justify-content: space-between;
gap: 10px;
+ background: rgb(0, 0, 0);
+ border-radius: 8px;
+ padding-left: 5px;
+ padding-right: 5px;
}
.mainView-snapLines {
@@ -190,10 +194,10 @@ h1,
left: 0;
position: absolute;
z-index: 2;
- background-color: linen;//$light-gray;
+ background-color: linen; //$light-gray;
.editable-title {
- background-color: linen;//$light-gray;
+ background-color: linen; //$light-gray;
}
}
}
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index efd8206bf..86e8bab13 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -704,7 +704,6 @@ export class MainView extends React.Component {
// prettier-ignore
switch (whereFields[0]) {
case OpenWhere.lightbox: return LightboxView.AddDocTab(doc, location);
- case OpenWhere.fullScreen: return CollectionDockingView.OpenFullScreen(doc);
case OpenWhere.close: return CollectionDockingView.CloseSplit(doc, whereMods);
case OpenWhere.toggle: return CollectionDockingView.ToggleSplit(doc, whereMods);
case OpenWhere.add:default:return CollectionDockingView.AddSplit(doc, whereMods, undefined, undefined, keyValue);
@@ -750,8 +749,7 @@ export class MainView extends React.Component {
@computed get leftMenuPanel() {
return (
- <div key="menu" className="mainView-leftMenuPanel" style={{ background: StrCast(Doc.UserDoc().userBackgroundColor),
- display: LightboxView.LightboxDoc ? 'none' : undefined }}>
+ <div key="menu" className="mainView-leftMenuPanel" style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), display: LightboxView.LightboxDoc ? 'none' : undefined }}>
<DocumentView
Document={Doc.MyLeftSidebarMenu}
DataDoc={undefined}
@@ -806,14 +804,17 @@ export class MainView extends React.Component {
{this._hideUI ? null : this.leftMenuPanel}
<div key="inner" className={`mainView-innerContent${this.colorScheme}`}>
{this.flyout}
- <div className="mainView-libraryHandle" style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), left: leftMenuFlyoutWidth - 10 /* ~half width of handle */, display: !this._leftMenuFlyoutWidth ? 'none' : undefined }} onPointerDown={this.onFlyoutPointerDown}>
+ <div
+ className="mainView-libraryHandle"
+ style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), left: leftMenuFlyoutWidth - 10 /* ~half width of handle */, display: !this._leftMenuFlyoutWidth ? 'none' : undefined }}
+ onPointerDown={this.onFlyoutPointerDown}>
<FontAwesomeIcon icon="chevron-left" color={StrCast(Doc.UserDoc().userColor)} style={{ opacity: '50%' }} size="sm" />
</div>
<div className="mainView-innerContainer" style={{ width: `calc(100% - ${width}px)` }}>
{this.dockingContent}
{this._hideUI ? null : (
- <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ right: this.propertiesWidth() - 1, background : 'linen' }}>
+ <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ right: this.propertiesWidth() - 1, background: 'linen' }}>
<FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={this.colorScheme === ColorScheme.Dark ? Colors.WHITE : Colors.BLACK} size="sm" />
</div>
)}
@@ -880,7 +881,7 @@ export class MainView extends React.Component {
@computed get docButtons() {
return !Doc.MyDockedBtns ? null : (
- <div className="mainView-docButtons" ref={this._docBtnRef}>
+ <div className="mainView-docButtons" style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor) }} ref={this._docBtnRef}>
<CollectionLinearView
Document={Doc.MyDockedBtns}
DataDoc={undefined}
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 6105cc1b5..2e3668268 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -56,24 +56,25 @@ export class PropertiesButtons extends React.Component<{}, {}> {
propertyToggleBtn = (label: (on?: any) => string, property: string, tooltip: (on?: any) => string, icon: (on?: any) => any, onClick?: (dv: Opt<DocumentView>, doc: Doc, property: string) => void, useUserDoc?: boolean) => {
const targetDoc = useUserDoc ? Doc.UserDoc() : this.selectedDoc;
const onPropToggle = (dv: Opt<DocumentView>, doc: Doc, prop: string) => ((dv?.layoutDoc || doc)[prop] = (dv?.layoutDoc || doc)[prop] ? false : true);
- return !targetDoc ? null : <Toggle
- toggleStatus={BoolCast(targetDoc[property])}
- text={label(targetDoc?.[property])}
- color={StrCast(Doc.UserDoc().userColor)}
- icon={icon(targetDoc?.[property] as any)}
- iconPlacement={'left'}
- align={'flex-start'}
- fillWidth={true}
- toggleType={ToggleType.BUTTON}
- onClick={undoable(() => {
- if (SelectionManager.Views().length > 1) {
- SelectionManager.Views().forEach(dv => (onClick ?? onPropToggle)(dv, dv.rootDoc, property));
- } else if (targetDoc) (onClick ?? onPropToggle)(undefined, targetDoc, property);
- }, property)}
- />
+ return !targetDoc ? null : (
+ <Toggle
+ toggleStatus={BoolCast(targetDoc[property])}
+ text={label(targetDoc?.[property])}
+ color={StrCast(Doc.UserDoc().userColor)}
+ icon={icon(targetDoc?.[property] as any)}
+ iconPlacement={'left'}
+ align={'flex-start'}
+ fillWidth={true}
+ toggleType={ToggleType.BUTTON}
+ onClick={undoable(() => {
+ if (SelectionManager.Views().length > 1) {
+ SelectionManager.Views().forEach(dv => (onClick ?? onPropToggle)(dv, dv.rootDoc, property));
+ } else if (targetDoc) (onClick ?? onPropToggle)(undefined, targetDoc, property);
+ }, property)}
+ />
+ );
};
-
// this implments a container pattern by marking the targetDoc (collection) as a lightbox
// that always fits its contents to its container and that hides all other documents when
// a link is followed that targets a 'lightbox' destination
@@ -110,7 +111,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
(dv, doc) => {
const tdoc = dv?.rootDoc || doc;
const newtitle = !tdoc._layout_showTitle ? 'title' : tdoc._layout_showTitle === 'title' ? 'title:hover' : '';
- tdoc._layout_showTitle = newtitle;
+ tdoc._layout_showTitle = newtitle ? newtitle : undefined;
}
);
}
@@ -148,7 +149,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
@computed get clustersButton() {
return this.propertyToggleBtn(
- on => (on ?'DISABLE CLUSTERS' : 'HIGHLIGHT CLUSTERS'),
+ on => (on ? 'DISABLE CLUSTERS' : 'HIGHLIGHT CLUSTERS'),
'_freeform_useClusters',
on => `${on ? 'Hide' : 'Show'} clusters`,
on => <FaBraille />
@@ -163,12 +164,13 @@ export class PropertiesButtons extends React.Component<{}, {}> {
);
}
- @computed get forceActiveButton() { //select text
+ @computed get forceActiveButton() {
+ //select text
return this.propertyToggleBtn(
- on => on ? 'INACTIVE INTERACTION' : 'ACTIVE INTERACTION',
+ on => (on ? 'INACTIVE INTERACTION' : 'ACTIVE INTERACTION'),
'_forceActive',
on => `${on ? 'Select to activate' : 'Contents always active'} `,
- on => <MdTouchApp/> // 'eye'
+ on => <MdTouchApp /> // 'eye'
);
}
@@ -218,7 +220,8 @@ export class PropertiesButtons extends React.Component<{}, {}> {
}
@computed get captionButton() {
- return this.propertyToggleBtn( //DEVELOPER
+ return this.propertyToggleBtn(
+ //DEVELOPER
on => (on ? 'HIDE CAPTION' : 'SHOW CAPTION'), //'Caption',
'_layout_showCaption',
on => `${on ? 'Hide' : 'Show'} caption footer`,
@@ -227,17 +230,19 @@ export class PropertiesButtons extends React.Component<{}, {}> {
);
}
- @computed get chromeButton() { // developer -- removing UI decoration
+ @computed get chromeButton() {
+ // developer -- removing UI decoration
return this.propertyToggleBtn(
- on => on ? 'ENABLE UI CONTROLS' : 'DISABLE UI CONTROLS',
+ on => (on ? 'ENABLE UI CONTROLS' : 'DISABLE UI CONTROLS'),
'_chromeHidden',
on => `${on ? 'Show' : 'Hide'} editing UI`,
- on => on? <TbEditCircle/> : <TbEditCircleOff/> , // 'edit',
+ on => (on ? <TbEditCircle /> : <TbEditCircleOff />), // 'edit',
(dv, doc) => ((dv?.rootDoc || doc)._chromeHidden = !(dv?.rootDoc || doc)._chromeHidden)
);
}
- @computed get layout_autoHeightButton() { // store previous dimensions to store old values
+ @computed get layout_autoHeightButton() {
+ // store previous dimensions to store old values
return this.propertyToggleBtn(
on => 'Auto\xA0Size',
'_layout_autoHeight',
@@ -251,7 +256,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
on => (on ? 'HIDE GRID' : 'DISPLAY GRID'),
'_freeform_backgroundGrid',
on => `Display background grid in collection`,
- on => (on ? <MdGridOff /> :<MdGridOn /> ) //'border-all'
+ on => (on ? <MdGridOff /> : <MdGridOn />) //'border-all'
);
}
@@ -288,13 +293,14 @@ export class PropertiesButtons extends React.Component<{}, {}> {
// }
// );
// }
- @computed get snapButton() { // THESE ARE NOT COMING
+ @computed get snapButton() {
+ // THESE ARE NOT COMING
return this.propertyToggleBtn(
on => (on ? 'HIDE SNAP LINES' : 'SHOW SNAP LINES'),
'freeform_snapLines',
on => `Display snapping lines when objects are dragged`,
on => <TfiBarChart />, //'th',
- undefined,
+ undefined
);
}
@@ -346,11 +352,11 @@ export class PropertiesButtons extends React.Component<{}, {}> {
const followLoc = this.selectedDoc._followLinkLocation;
const linkedToLightboxView = () => LinkManager.Links(this.selectedDoc).some(link => LinkManager.getOppositeAnchor(link, this.selectedDoc)?._isLightbox);
- if (followLoc === OpenWhere.lightbox && !linkedToLightboxView()) return 'linkInPlace'
- else if (linkButton && followLoc === OpenWhere.addRight) return 'linkOnRight'
- else if (linkButton && this.selectedDoc._followLinkLocation === OpenWhere.lightbox && linkedToLightboxView()) return 'enterPortal'
- else if (ScriptCast(this.selectedDoc.onClick)?.script.originalScript.includes('toggleDetail')) return 'toggleDetail'
- else return 'nothing'
+ if (followLoc === OpenWhere.lightbox && !linkedToLightboxView()) return 'linkInPlace';
+ else if (linkButton && followLoc === OpenWhere.addRight) return 'linkOnRight';
+ else if (linkButton && this.selectedDoc._followLinkLocation === OpenWhere.lightbox && linkedToLightboxView()) return 'enterPortal';
+ else if (ScriptCast(this.selectedDoc.onClick)?.script.originalScript.includes('toggleDetail')) return 'toggleDetail';
+ else return 'nothing';
}
@computed
@@ -362,22 +368,20 @@ export class PropertiesButtons extends React.Component<{}, {}> {
['linkInPlace', 'Open Link in Lightbox'],
['linkOnRight', 'Open Link on Right'],
];
-
+
const items: IListItemProps[] = buttonList.map(value => {
- return (
- {
- text: value[1],
- val: value[1],
- }
- );
+ return {
+ text: value[1],
+ val: value[1],
+ };
});
- console.log("click val: ", this.onClickVal)
+ console.log('click val: ', this.onClickVal);
return !this.selectedDoc ? null : (
<Dropdown
- tooltip={'Choose onClick behavior'}
+ tooltip={'Choose onClick behavior'}
items={items}
selectedVal={this.onClickVal}
- setSelectedVal={(val) => this.handleOptionChange(val as string)}
+ setSelectedVal={val => this.handleOptionChange(val as string)}
title={'Choose onClick behaviour'}
color={StrCast(Doc.UserDoc().userColor)}
dropdownType={DropdownType.SELECT}
diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx
index 6a54f0002..395aa2b61 100644
--- a/src/client/views/PropertiesDocContextSelector.tsx
+++ b/src/client/views/PropertiesDocContextSelector.tsx
@@ -3,11 +3,10 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, DocListCast } from '../../fields/Doc';
import { Id } from '../../fields/FieldSymbols';
-import { Cast, NumCast, StrCast } from '../../fields/Types';
-import { CollectionViewType } from '../documents/DocumentTypes';
+import { Cast, StrCast } from '../../fields/Types';
import { DocFocusOrOpen } from '../util/DocumentManager';
import { CollectionDockingView } from './collections/CollectionDockingView';
-import { DocumentView, OpenWhere, OpenWhereMod } from './nodes/DocumentView';
+import { DocumentView, OpenWhere } from './nodes/DocumentView';
import './PropertiesDocContextSelector.scss';
type PropertiesDocContextSelectorProps = {
@@ -19,7 +18,6 @@ type PropertiesDocContextSelectorProps = {
@observer
export class PropertiesDocContextSelector extends React.Component<PropertiesDocContextSelectorProps> {
-
@computed get _docs() {
if (!this.props.DocView) return [];
const target = this.props.DocView.props.Document;
@@ -40,7 +38,7 @@ export class PropertiesDocContextSelector extends React.Component<PropertiesDocC
}, new Set<Doc>())
.keys()
);
- console.log("embeddings " + embeddings.length);
+ console.log('embeddings ' + embeddings.length);
return doclayouts
.filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance?.props.Document))
@@ -56,7 +54,7 @@ export class PropertiesDocContextSelector extends React.Component<PropertiesDocC
};
render() {
- if (this._docs.length < 1) return undefined
+ if (this._docs.length < 1) return undefined;
return (
<div>
{this.props.hideTitle ? null : <p key="contexts">Contexts:</p>}
diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss
index 060b506e3..b79486167 100644
--- a/src/client/views/PropertiesView.scss
+++ b/src/client/views/PropertiesView.scss
@@ -42,16 +42,6 @@
padding: 0;
margin-top: -5;
}
-
- .propertiesView-acls-checkbox {
- margin-top: -15px;
- margin-bottom: -10px;
-
- .propertiesView-acls-checkbox-text {
- display: inline;
- font-size: 9px;
- }
- }
}
.change-buttons {
@@ -68,14 +58,19 @@
}
}
+ .propertiesView-acls-checkbox {
+ float: right;
+ margin-left: 50px;
+ }
+
.propertiesView-shareDropDown{
margin-right: 10px;
min-width: 65px;
& .propertiesView-shareDropDownNone{
- height: 16px;
padding: 0px;
padding-left: 3px;
+ padding-right: 3px;
background: grey;
color: rgb(71, 71, 71);
border-radius: 6px;
@@ -83,18 +78,18 @@
}
& .propertiesView-shareDropDownEdit,
.propertiesView-shareDropDownAdmin{
- height: 16px;
padding: 0px;
padding-left: 3px;
+ padding-right: 3px;
background: rgb(254, 254, 199);
color: rgb(75, 75, 5);
border-radius: 6px;
border: 1px solid rgb(75, 75, 5);
}
& .propertiesView-shareDropDownAugment{
- height: 16px;
padding: 0px;
padding-left: 3px;
+ padding-right: 3px;
background: rgb(208, 255, 208);
color:rgb(19, 80, 19);
border-radius: 6px;
@@ -102,18 +97,18 @@
}
& .propertiesView-shareDropDownView{
- height: 16px;
padding: 0px;
padding-left: 3px;
+ padding-right: 3px;
background: rgb(213, 213, 255);
color: rgb(25, 25, 101);
border-radius: 6px;
border: 1px solid rgb(25, 25, 101);
}
& .propertiesView-shareDropDownNot-Shared{
- height: 16px;
padding: 0px;
padding-left: 3px;
+ padding-right: 3px;
background: rgb(255, 207, 207);
color: rgb(138, 47, 47);
border-radius: 6px;
@@ -177,19 +172,7 @@
}
.expansion-button {
- margin-left: -15px;
- margin-right: 20px;
-
- .expansion-button-icon {
- width: 11px;
- height: 11px;
- color: black;
-
- &:hover {
- color: rgb(131, 131, 131);
- cursor: pointer;
- }
- }
+ margin-right: 10px;
}
.propertiesView-sharingTable {
@@ -238,6 +221,11 @@
}
}
+ .propertiesView-permissions-select {
+ background: inherit;
+ border: none;
+ }
+
.propertiesView-field {
display: flex;
font-size: 7px;
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index cb0663554..27b9c3c7a 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -3,7 +3,7 @@ import { IconLookup } from '@fortawesome/fontawesome-svg-core';
import { faAnchor, faArrowRight, faWindowMaximize } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Checkbox, Tooltip } from '@material-ui/core';
-import { Button, Colors, EditableText, NumberInput, Size, Slider, Type } from 'browndash-components';
+import { Button, Colors, EditableText, IconButton, NumberInput, Size, Slider, Type } from 'browndash-components';
import { concat } from 'lodash';
import { Lambda, action, computed, observable } from 'mobx';
import { observer } from 'mobx-react';
@@ -367,17 +367,18 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
*/
@computed get expansionIcon() {
return (
- <Tooltip title={<div className="dash-tooltip">Show more permissions</div>}>
- <div
- className="expansion-button"
- onPointerDown={() => {
+ <div className="expansion-button" >
+ <IconButton
+ icon={<FontAwesomeIcon icon={'ellipsis-h'} />}
+ size={Size.XSMALL}
+ color={StrCast(Doc.UserDoc().userColor)}
+ onClick={action(() => {
if (this.selectedDocumentView || this.selectedDoc) {
SharingManager.Instance.open(this.selectedDocumentView?.props.Document === this.selectedDoc ? this.selectedDocumentView : undefined, this.selectedDoc);
}
- }}>
- <FontAwesomeIcon className="expansion-button-icon" icon="ellipsis-h" color="black" size="sm" />
- </div>
- </Tooltip>
+ })}
+ />
+ </div>
);
}
@@ -417,7 +418,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
<div>
<div className={'propertiesView-shareDropDown'}>
<div className={`propertiesView-shareDropDown${permission}`}>
- <div className="propertiesView-shareDropDown">{admin && permission !== 'Owner' ? this.getPermissionsSelect(name, permission, showGuestOptions) : concat(shareImage, ' ', permission)}</div>
+ <div >{admin && permission !== 'Owner' ? this.getPermissionsSelect(name, permission, showGuestOptions) : concat(shareImage, ' ', permission)}</div>
</div>
</div>
</div>
@@ -449,6 +450,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
const target = docs[0];
const showAdmin = GetEffectiveAcl(target) == AclAdmin;
+ console.log(GetEffectiveAcl(target), Doc.GetProto(target)[`acl-${normalizeEmail(Doc.CurrentUserEmail)}`])
const individualTableEntries = [];
const usersAdded: string[] = []; // all shared users being added - organized by denormalized email
@@ -512,28 +514,29 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
}
});
- // public permission
- const publicPermission = StrCast((this.layoutDocAcls ? target : Doc.GetProto(target))['acl-Guest']);
+ // guest permission
+ const guestPermission = StrCast((this.layoutDocAcls ? target : Doc.GetProto(target))['acl-Guest']);
return (
<div>
- <br />
- <div className="propertiesView-sharingTable">{<div> {individualTableEntries}</div>}</div>
+ <div>
+ <br></br> Individuals with Access to this Document
+ </div>
+ <div className="propertiesView-sharingTable" style={{background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor)}}>
+ {<div> {individualTableEntries}</div>}
+ </div>
{groupTableEntries.length > 0 ? (
<div>
<div>
- {' '}
- <br></br> Groups with Access to this Document{' '}
+ <br></br> Groups with Access to this Document
+ </div>
+ <div className="propertiesView-sharingTable" style={{background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor)}}>
+ {<div> {groupTableEntries}</div>}
</div>
- <div className="propertiesView-sharingTable">{<div> {groupTableEntries}</div>}</div>
</div>
) : null}
- Guest
- <div>{this.colorACLDropDown('Guest', true, publicPermission!, true)}</div>
- <div>
- {' '}
- <br></br> Individual Users with Access to this Document{' '}
- </div>
+ <br></br> Guest
+ <div>{this.colorACLDropDown('Guest', showAdmin, guestPermission!, true)}</div>
</div>
);
}
@@ -1145,26 +1148,17 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
return <PropertiesSection
title="Sharing & Permissions"
content={<>
- <div className="propertiesView-buttonContainer">
- {!Doc.noviceMode ? (
- <div className="propertiesView-buttonContainer">
- <div className="propertiesView-acls-checkbox">
- <div className="propertiesView-acls-checkbox-text"> Show / Contol Layout Permissions </div>
- <Checkbox color="primary" onChange={action(() => (this.layoutDocAcls = !this.layoutDocAcls))} checked={this.layoutDocAcls} />
- </div>
- {/* <Tooltip title={<><div className="dash-tooltip">{"Re-distribute sharing settings"}</div></>}>
- <button onPointerDown={() => SharingManager.Instance.distributeOverCollection(this.selectedDoc!)}>
- <FontAwesomeIcon icon="redo-alt" color="white" size="1x" />
- </button>
- </Tooltip> */}
- </div>
- ) : null}
+ {/* <div className="propertiesView-buttonContainer"> */}
+ <div className="propertiesView-acls-checkbox">
+ Layout Permissions
+ <Checkbox color="primary" onChange={action(() => (this.layoutDocAcls = !this.layoutDocAcls))} checked={this.layoutDocAcls} />
+ </div>
{/* <Tooltip title={<><div className="dash-tooltip">{"Re-distribute sharing settings"}</div></>}>
<button onPointerDown={() => SharingManager.Instance.distributeOverCollection(this.selectedDoc!)}>
<FontAwesomeIcon icon="redo-alt" size="1x" />
</button>
</Tooltip> */}
- </div>
+ {/* </div> */}
{this.sharingTable}
</>}
isOpen={this.openSharing}
@@ -1534,7 +1528,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
<option value={OpenWhere.addRight}>Opening in new right pane</option>
<option value={OpenWhere.replaceLeft}>Replacing left tab</option>
<option value={OpenWhere.replaceRight}>Replacing right tab</option>
- <option value={OpenWhere.fullScreen}>Overlaying current tab</option>
<option value={OpenWhere.lightbox}>Opening in lightbox</option>
<option value={OpenWhere.add}>Opening in new tab</option>
<option value={OpenWhere.replace}>Replacing current tab</option>
diff --git a/src/client/views/StyleProvider.scss b/src/client/views/StyleProvider.scss
index 80c878386..c06bb287e 100644
--- a/src/client/views/StyleProvider.scss
+++ b/src/client/views/StyleProvider.scss
@@ -31,8 +31,8 @@
.styleProvider-treeView-icon,
.styleProvider-treeView-icon-active {
- margin-left: 0.25rem;
- margin-right: 0.25rem;
+ margin-left: 0;
+ margin-right: 0;
}
.styleProvider-treeView-icon {
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index a030c7052..bbbad3690 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -1,7 +1,7 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@material-ui/core';
-import { Shadows } from 'browndash-components';
+import { IconButton, Shadows, Size } from 'browndash-components';
import { action, runInAction } from 'mobx';
import { extname } from 'path';
import { Doc, Opt, StrListCast } from '../../fields/Doc';
@@ -22,6 +22,7 @@ import { DocumentViewProps } from './nodes/DocumentView';
import { FieldViewProps } from './nodes/FieldView';
import { KeyValueBox } from './nodes/KeyValueBox';
import { SliderBox } from './nodes/SliderBox';
+import { BsArrowDown, BsArrowUp, BsArrowDownUp } from 'react-icons/bs'
import './StyleProvider.scss';
import React = require('react');
@@ -109,11 +110,11 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
}
return Doc.toIcon(doc, isEmpty ? undefined : isOpen);
case StyleProp.TreeViewSortings:
- const allSorts: { [key: string]: { color: string; label: string } | undefined } = {};
- allSorts[TreeSort.Down] = { color: 'blue', label: '↓' };
- allSorts[TreeSort.Up] = { color: 'crimson', label: '↑' };
- if (doc?._type_collection === CollectionViewType.Freeform) allSorts[TreeSort.Zindex] = { color: 'green', label: 'z' };
- allSorts[TreeSort.None] = { color: 'darkgray', label: '\u00A0\u00A0\u00A0' };
+ const allSorts: { [key: string]: { color: string; icon: JSX.Element | string } | undefined } = {};
+ allSorts[TreeSort.Down] = { color: Colors.MEDIUM_BLUE, icon: <BsArrowDown/> };
+ allSorts[TreeSort.Up] = { color: 'crimson', icon: <BsArrowUp/> };
+ if (doc?._type_collection === CollectionViewType.Freeform) allSorts[TreeSort.Zindex] = { color: 'green', icon: 'Z' };
+ allSorts[TreeSort.None] = { color: 'darkgray', icon: <BsArrowDownUp/> };
return allSorts;
case StyleProp.Highlighting:
if (doc && (Doc.IsSystem(doc) || doc.type === DocumentType.FONTICON)) return undefined;
@@ -323,18 +324,19 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
}
export function DashboardToggleButton(doc: Doc, field: string, onIcon: IconProp, offIcon: IconProp, clickFunc?: () => void) {
+ const color = StrCast(Doc.UserDoc().userColor);
return (
- <div
- title={field}
- className={`styleProvider-treeView-icon${doc[field] ? '-active' : ''}`}
+ <IconButton
+ size={Size.XSMALL}
+ color={color}
+ icon={<FontAwesomeIcon icon={(doc[field] ? (onIcon as any) : offIcon) as IconProp} />}
onClick={undoBatch(
action((e: React.MouseEvent) => {
e.stopPropagation();
clickFunc ? clickFunc() : (doc[field] = doc[field] ? undefined : true);
})
- )}>
- <FontAwesomeIcon icon={(doc[field] ? (onIcon as any) : offIcon) as IconProp} size="sm" />
- </div>
+ )}
+ />
);
}
/**
@@ -342,7 +344,7 @@ export function DashboardToggleButton(doc: Doc, field: string, onIcon: IconProp,
*/
export function DashboardStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps | DocumentViewProps>, property: string) {
if (doc && property.split(':')[0] === StyleProp.Decorations) {
- return doc._type_collection === CollectionViewType.Docking
+ return doc._type_collection === CollectionViewType.Docking || Doc.IsSystem(doc)
? null
: DashboardToggleButton(doc, 'hidden', 'eye-slash', 'eye', () => DocFocusOrOpen(doc, { toggleTarget: true, willZoomCentered: true, zoomScale: 0 }, DocCast(doc?.embedContainer ?? doc?.annotationOn)));
}
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index aaca7110e..caf04cc1b 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -5,7 +5,8 @@ import { UndoManager } from '../util/UndoManager';
import './UndoStack.scss';
import { StrCast } from '../../fields/Types';
import { Doc } from '../../fields/Doc';
-import { Popup, Type } from 'browndash-components';
+import { Popup, Type, isDark } from 'browndash-components';
+import { Colors } from './global/globalEnums';
interface UndoStackProps {
width?: number;
@@ -17,18 +18,19 @@ export class UndoStack extends React.Component<UndoStackProps> {
@observable static HideInline: boolean;
@observable static Expand: boolean;
render() {
+ const background = UndoManager.batchCounter.get() ? 'yellow' : StrCast(Doc.UserDoc().userBackgroundColor)
return this.props.inline && UndoStack.HideInline ? null : (
<div className="undoStack-outerContainer">
<Popup
text={'Undo/Redo Stack'}
- color={StrCast(Doc.UserDoc().userVariantColor)}
+ color={UndoManager.batchCounter.get() ? 'yellow' : StrCast(Doc.UserDoc().userVariantColor)}
placement={`top-start`}
type={Type.TERT}
popup={
<div className="undoStack-commandsContainer" ref={r => r?.scroll({ behavior: 'auto', top: r?.scrollHeight + 20 })}
style={{
- background: UndoManager.batchCounter.get() ? 'yellow' : StrCast(Doc.UserDoc().userBackgroundColor),
- color: StrCast(Doc.UserDoc().userColor)
+ background: background,
+ color: isDark(background) ? Colors.LIGHT_GRAY : Colors.DARK_GRAY
}}>
{UndoManager.undoStackNames.map((name, i) => (
<div className="undoStack-resultContainer" key={i}>
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index 4c15d5eed..a4c5229aa 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -95,6 +95,13 @@
position: relative;
}
+.lm_maximised .lm_header {
+ background-color: #000000;
+}
+.lm_maximised .lm_tab {
+ width: 100%;
+}
+
.lm_stack {
position: relative;
}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 8d1b46ebb..16982595d 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -127,28 +127,6 @@ export class CollectionDockingView extends CollectionSubView() {
}
@undoBatch
- public static OpenFullScreen(doc: Doc) {
- SelectionManager.DeselectAll();
- const instance = CollectionDockingView.Instance;
- if (instance) {
- if (doc._type_collection === CollectionViewType.Docking && doc.layout_fieldKey === 'layout') {
- return DashboardView.openDashboard(doc);
- }
- const newItemStackConfig = {
- type: 'stack',
- content: [CollectionDockingView.makeDocumentConfig(Doc.MakeEmbedding(doc))],
- };
- const docconfig = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout);
- instance._goldenLayout.root.contentItems[0].addChild(docconfig);
- docconfig.callDownwards('_$init');
- instance._goldenLayout._$maximiseItem(docconfig);
- instance._goldenLayout.emit('stateChanged');
- instance.stateChanged();
- }
- return true;
- }
-
- @undoBatch
@action
public static ReplaceTab(document: Doc, panelName: OpenWhereMod, stack: any, addToSplit?: boolean, keyValue?: boolean): boolean {
const instance = CollectionDockingView.Instance;
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 9eb716763..5135cfb57 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -33,7 +33,7 @@ import { LightboxView } from '../LightboxView';
import { MainView } from '../MainView';
import { DefaultStyleProvider } from '../StyleProvider';
import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView';
-import { DocumentView, OpenWhereMod } from '../nodes/DocumentView';
+import { DocumentView, DocumentViewInternal, OpenWhereMod } from '../nodes/DocumentView';
import { RichTextMenu } from '../nodes/formattedText/RichTextMenu';
import { CollectionDockingView } from './CollectionDockingView';
import './CollectionMenu.scss';
@@ -129,7 +129,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
docViewPath={returnEmptyDoclist}
moveDocument={returnFalse}
addDocument={returnFalse}
- addDocTab={returnFalse}
+ addDocTab={DocumentViewInternal.addDocTabFunc}
pinToPres={emptyFunction}
removeDocument={returnFalse}
ScreenToLocalTransform={this.buttonBarXf}
@@ -154,21 +154,21 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
const hardCodedButtons = (
<div className={`hardCodedButtons`}>
- <Toggle
- toggleType={ToggleType.BUTTON}
- type={Type.PRIM}
- color={StrCast(Doc.UserDoc().userColor)}
- onClick={this.toggleTopBar}
- toggleStatus={SettingsManager.headerBarHeight > 0}
+ <Toggle
+ toggleType={ToggleType.BUTTON}
+ type={Type.PRIM}
+ color={StrCast(Doc.UserDoc().userColor)}
+ onClick={this.toggleTopBar}
+ toggleStatus={SettingsManager.headerBarHeight > 0}
icon={<FontAwesomeIcon icon={headerIcon} size="lg" />}
tooltip={headerTitle}
/>
- <Toggle
- toggleType={ToggleType.BUTTON}
+ <Toggle
+ toggleType={ToggleType.BUTTON}
type={Type.PRIM}
- color={StrCast(Doc.UserDoc().userColor)}
- onClick={this.toggleProperties}
- toggleStatus={SettingsManager.propertiesWidth > 0}
+ color={StrCast(Doc.UserDoc().userColor)}
+ onClick={this.toggleProperties}
+ toggleStatus={SettingsManager.propertiesWidth > 0}
icon={<FontAwesomeIcon icon={propIcon} size="lg" />}
tooltip={propTitle}
/>
@@ -178,11 +178,12 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
// NEW BUTTONS
//dash col linear view buttons
const contMenuButtons = (
- <div className="collectionMenu-container"
- style={{
- background: StrCast(Doc.UserDoc().userBackgroundColor),
- // borderColor: StrCast(Doc.UserDoc().userColor)
- }} >
+ <div
+ className="collectionMenu-container"
+ style={{
+ background: StrCast(Doc.UserDoc().userBackgroundColor),
+ // borderColor: StrCast(Doc.UserDoc().userColor)
+ }}>
{this.contMenuButtons}
{hardCodedButtons}
</div>
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index b9f13b188..67b7b39dd 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -377,7 +377,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
}
}
return LightboxView.AddDocTab(doc, location);
- case OpenWhere.fullScreen: return CollectionDockingView.OpenFullScreen(doc);
case OpenWhere.close: return CollectionDockingView.CloseSplit(doc, whereMods);
case OpenWhere.replace: return CollectionDockingView.ReplaceTab(doc, whereMods, this.stack, undefined, keyValue);
case OpenWhere.toggle: return CollectionDockingView.ToggleSplit(doc, whereMods, this.stack, undefined, keyValue);
diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss
index 85f99b9c2..d22e85880 100644
--- a/src/client/views/collections/TreeView.scss
+++ b/src/client/views/collections/TreeView.scss
@@ -13,7 +13,7 @@
.treeView-container-active {
.bullet-outline {
position: relative;
- width: $TREE_BULLET_WIDTH;
+ width: fit-content;
color: $medium-gray;
transform: scale(0.5);
display: inline-flex;
@@ -21,7 +21,6 @@
}
.treeView-bulletIcons {
- // width: $TREE_BULLET_WIDTH;
width: 100%;
height: 100%;
position: relative;
@@ -43,11 +42,12 @@
justify-content: center;
align-items: center;
position: relative;
- width: $TREE_BULLET_WIDTH;
+ width: fit-content;
min-height: 20px;
color: $medium-gray;
border: #80808030 1px solid;
border-radius: 5px;
+ z-index: 1;
}
}
@@ -55,9 +55,6 @@
position: absolute;
height: max-content;
pointer-events: none;
- color: white;
- border-radius: 4px;
- font-size: 10px;
}
.treeView-container-active {
@@ -105,10 +102,26 @@
align-items: center;
width: max-content;
border-radius: 5px;
+ overflow: hidden;
+ position: relative;
+ z-index: 1;
+
+ .treeView-background {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 0;
+ filter: opacity(0);
+ }
&:hover {
- background-color: #bdddf5;
+ .treeView-background {
+ filter: opacity(0.2) !important;
+ }
}
+
//align-items: center;
::-webkit-scrollbar {
@@ -141,6 +154,7 @@
opacity: 0.75;
pointer-events: all;
cursor: pointer;
+ z-index: 1;
> svg {
margin-left: 0.25rem;
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index fa9f895fd..51c70633c 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -222,10 +222,8 @@ export class TreeView extends React.Component<TreeViewProps> {
this.treeViewOpen = !this.treeViewOpen;
} else {
// choose an appropriate embedding or make one. --- choose the first embedding that (1) user owns, (2) has no context field ... otherwise make a new embedding
- const bestEmbedding = docView.rootDoc.author === Doc.CurrentUserEmail && !Doc.IsDataProto(docView.props.Document)
- ? docView.rootDoc
- : Doc.BestEmbedding(docView.rootDoc);
- this.props.addDocTab(bestEmbedding, OpenWhere.lightbox);
+ const bestEmbedding = docView.rootDoc.author === Doc.CurrentUserEmail && !Doc.IsDataProto(docView.props.Document) ? docView.rootDoc : Doc.BestEmbedding(docView.rootDoc);
+ this.props.addDocTab(bestEmbedding, OpenWhere.lightbox);
}
};
@@ -539,9 +537,9 @@ export class TreeView extends React.Component<TreeViewProps> {
@computed get renderContent() {
TraceMobx();
const expandKey = this.treeViewExpandedView;
- const sortings = (this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) as { [key: string]: { color: string; label: string } }) ?? {};
- const color = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.Color)
- console.log("tree view", color, this.doc.title, Doc.IsSystem(this.doc))
+ const sortings = (this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) as { [key: string]: { color: string; icon: JSX.Element | string } }) ?? {};
+ const color = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.Color);
+ console.log('tree view', color, this.doc.title, Doc.IsSystem(this.doc));
if (['links', 'annotations', 'embeddings', this.fieldKey].includes(expandKey)) {
const sorting = StrCast(this.doc.treeViewSortCriterion, TreeSort.None);
const sortKeys = Object.keys(sortings);
@@ -581,12 +579,28 @@ export class TreeView extends React.Component<TreeViewProps> {
);
}
return (
- <div style={{
- color: color
- }}>
+ <div
+ style={{
+ color: color,
+ }}>
{!docs?.length || this.props.AddToMap /* hack to identify pres box trees */ ? null : (
- <div className={'treeView-sorting'} style={{ background: sortings[sorting]?.color }}>
- {sortings[sorting]?.label}
+ <div className={'treeView-sorting'}>
+ <IconButton
+ color={sortings[sorting]?.color}
+ size={Size.XSMALL}
+ icon={sortings[sorting]?.icon}
+ onPointerDown={e => {
+ downX = e.clientX;
+ downY = e.clientY;
+ e.stopPropagation();
+ }}
+ onClick={undoable(e => {
+ if (this.props.isContentActive() && Math.abs(e.clientX - downX) < 3 && Math.abs(e.clientY - downY) < 3) {
+ !this.props.treeView.outlineMode && (this.doc.treeViewSortCriterion = sortKeys[(curSortIndex + 1) % sortKeys.length]);
+ e.stopPropagation();
+ }
+ }, 'sort order')}
+ />
</div>
)}
<ul
@@ -689,7 +703,7 @@ export class TreeView extends React.Component<TreeViewProps> {
@computed get renderBullet() {
TraceMobx();
const iconType = this.props.treeView.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewIcon + (this.treeViewOpen ? ':open' : !this.childDocs.length ? ':empty' : '')) || 'question';
- const color = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.Color)
+ const color = StrCast(Doc.UserDoc().userColor);
const checked = this.onCheckedClick ? this.doc.treeViewChecked ?? 'unchecked' : undefined;
return (
<div
@@ -710,26 +724,19 @@ export class TreeView extends React.Component<TreeViewProps> {
}>
{this.props.treeView.outlineMode ? (
!(this.doc.text as RichTextField)?.Text ? null : (
- <IconButton
- color={color}
- icon={<FontAwesomeIcon icon={[this.childDocs?.length && !this.treeViewOpen ? 'fas' : 'far', 'circle']} />}
- size={Size.XSMALL}
- />
+ <IconButton color={color} icon={<FontAwesomeIcon icon={[this.childDocs?.length && !this.treeViewOpen ? 'fas' : 'far', 'circle']} />} size={Size.XSMALL} />
)
) : (
<div className="treeView-bulletIcons" style={{ color: Doc.IsSystem(DocCast(this.doc.proto)) ? 'red' : undefined }}>
- <IconButton
- color={color}
- icon={<FontAwesomeIcon size="sm" icon={checked === 'check' ? 'check' : checked === 'x' ? 'times' : checked === 'unchecked' ? 'square' : !this.treeViewOpen ? 'caret-right' : 'caret-down'} />}
- size={Size.XSMALL}
- />
- {this.onCheckedClick ? null :
- <IconButton
- color={color}
- icon={<FontAwesomeIcon icon={iconType as IconProp} />}
- size={Size.XSMALL}
- />
- }
+ {this.onCheckedClick ? (
+ <IconButton
+ color={color}
+ icon={<FontAwesomeIcon size="sm" icon={checked === 'check' ? 'check' : checked === 'x' ? 'times' : checked === 'unchecked' ? 'square' : !this.treeViewOpen ? 'caret-right' : 'caret-down'} />}
+ size={Size.XSMALL}
+ />
+ ) : (
+ <IconButton color={color} icon={<FontAwesomeIcon icon={iconType as IconProp} />} size={Size.XSMALL} />
+ )}
</div>
)}
</div>
@@ -757,21 +764,19 @@ export class TreeView extends React.Component<TreeViewProps> {
@observable headerEleWidth = 0;
@computed get titleButtons() {
const customHeaderButtons = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.Decorations);
+ const color = StrCast(Doc.UserDoc().userColor);
return this.props.treeViewHideHeaderFields() || this.doc.treeViewHideHeaderFields ? null : (
<>
{customHeaderButtons} {/* e.g.,. hide button is set by dashboardStyleProvider */}
- {this.doc._layout_hideContextMenu ? null : (
- <FontAwesomeIcon
- title="context menu"
- key="bars"
- icon="bars"
- size="sm"
- onClick={e => {
- this.showContextMenu(e);
- e.stopPropagation();
- }}
- />
- )}
+ <IconButton
+ color={color}
+ icon={<FontAwesomeIcon icon="bars" />}
+ size={Size.XSMALL}
+ onClick={e => {
+ this.showContextMenu(e);
+ e.stopPropagation();
+ }}
+ />
{Doc.noviceMode ? null : this.doc.treeViewExpandedViewLock || Doc.IsSystem(this.doc) ? null : (
<span className="collectionTreeView-keyHeader" title="type of expanded data" key={this.treeViewExpandedView} onPointerDown={this.expandNextviewType}>
{this.treeViewExpandedView}
@@ -1000,6 +1005,12 @@ export class TreeView extends React.Component<TreeViewProps> {
onPointerEnter={this.onPointerEnter}
onPointerLeave={this.onPointerLeave}>
{contents}
+ <div
+ className={`treeView-background`}
+ style={{
+ background: StrCast(Doc.UserDoc().userColor),
+ }}
+ />
</div>
{this.renderBorder}
</>
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 079b94428..7e574e839 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -161,7 +161,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
});
})
);
- } else if (e.key === 's' && e.ctrlKey) {
+ } /* else if (e.key === 's' && e.ctrlKey) {
e.preventDefault();
const slide = DocUtils.copyDragFactory(DocCast(Doc.UserDoc().emptySlide))!;
slide.x = x;
@@ -178,7 +178,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
this.pasteTable(ns, x, y);
})();
e.stopPropagation();
- } else if (!e.ctrlKey && !e.metaKey && SelectionManager.Views().length < 2) {
+ }*/ else if (!e.ctrlKey && !e.metaKey && SelectionManager.Views().length < 2) {
FormattedTextBox.SelectOnLoadChar = Doc.UserDoc().defaultTextLayout && !this.props.childLayoutString ? e.key : '';
FormattedTextBox.LiveTextUndo = UndoManager.StartBatch('type new note');
this.props.addLiveTextDocument(DocUtils.GetNewTextDoc('-typed text-', x, y, 200, 100, this.props.xPadding === 0));
diff --git a/src/client/views/newlightbox/NewLightboxView.tsx b/src/client/views/newlightbox/NewLightboxView.tsx
index c5e98da86..3acbd1a32 100644
--- a/src/client/views/newlightbox/NewLightboxView.tsx
+++ b/src/client/views/newlightbox/NewLightboxView.tsx
@@ -305,8 +305,8 @@ export class NewLightboxView extends React.Component<LightboxViewProps> {
renderDepth={0}
rootSelected={returnTrue}
docViewPath={returnEmptyDoclist}
- docFilters={this.docFilters}
- docRangeFilters={returnEmptyFilter}
+ childFilters={this.docFilters}
+ childFiltersByRanges={returnEmptyFilter}
searchFilterDocs={returnEmptyDoclist}
addDocument={undefined}
removeDocument={undefined}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 4211b8a81..f9fa1955f 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -70,7 +70,6 @@ export enum OpenWhere {
addRight = 'add:right',
addBottom = 'add:bottom',
close = 'close',
- fullScreen = 'fullScreen',
toggle = 'toggle',
toggleRight = 'toggle:right',
replace = 'replace',
@@ -800,7 +799,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
!more && moreItems.length && cm.addItem({ description: 'More...', subitems: moreItems, icon: 'compass' });
}
const constantItems: ContextMenuProps[] = [];
- constantItems.push({ description: 'Show Metadata', event: () => this.props.addDocTab(this.props.Document, (OpenWhere.addRight.toString() + 'KeyValue') as OpenWhere), icon: 'layer-group' });
if (!Doc.IsSystem(this.rootDoc)) {
constantItems.push({ description: 'Export as Zip file', icon: 'download', event: async () => Doc.Zip(this.props.Document) });
(this.rootDoc._type_collection !== CollectionViewType.Docking || !Doc.noviceMode) && constantItems.push({ description: 'Share', event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: 'users' });
@@ -809,7 +807,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
constantItems.push({ description: 'Close', event: this.deleteClicked, icon: 'times' });
}
}
- cm.addItem({ description: 'General...', noexpand: !Doc.IsSystem(this.rootDoc), subitems: constantItems, icon: 'question' });
+ constantItems.push({ description: 'Show Metadata', event: () => this.props.addDocTab(this.props.Document, (OpenWhere.addRight.toString() + 'KeyValue') as OpenWhere), icon: 'layer-group' });
+ cm.addItem({ description: 'General...', noexpand: false, subitems: constantItems, icon: 'question' });
const help = cm.findByDescription('Help...');
const helpItems: ContextMenuProps[] = help && 'subitems' in help ? help.subitems : [];
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 3ec53beac..da1b89200 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -86,10 +86,10 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
}
Icon = (color: string, iconFalse?: boolean) => {
let icon;
- if (iconFalse ) {
+ if (iconFalse) {
icon = StrCast(this.dataDoc[this.fieldKey ?? 'iconFalse'] ?? this.dataDoc.icon, 'user') as any;
- if (icon) return <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />
- else return null
+ if (icon) return <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />;
+ else return null;
}
icon = StrCast(this.dataDoc[this.fieldKey ?? 'icon'] ?? this.dataDoc.icon, 'user') as any;
const trailsIcon = () => <img src={`/assets/${'presTrails.png'}`} style={{ width: 30, height: 30, filter: `invert(${color === Colors.DARK_GRAY ? '0%' : '100%'})` }} />;
@@ -124,36 +124,38 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
*/
@computed get numberDropdown() {
let type: NumberDropdownType;
- switch(this.type) {
- case ButtonType.NumberDropdownButton:
- type = 'dropdown'
+ switch (this.type) {
+ case ButtonType.NumberDropdownButton:
+ type = 'dropdown';
break;
case ButtonType.NumberInlineButton:
- type = 'input'
+ type = 'input';
break;
case ButtonType.NumberSliderButton:
default:
- type = 'slider'
+ type = 'slider';
break;
}
- const numScript = (value?: number) => ScriptCast(this.rootDoc.script).script.run({ self: this.rootDoc, value, _readOnly_: value === undefined });
+ const numScript = (value?: number) => ScriptCast(this.rootDoc.script).script.run({ this: this.layoutDoc, self: this.rootDoc, value, _readOnly_: value === undefined });
const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
// Script for checking the outcome of the toggle
const checkResult = Number(Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3)));
const label = !FontIconBox.GetShowLabels() ? null : <div className="fontIconBox-label">{this.label}</div>;
- return <NumberDropdown
- color={color}
- numberDropdownType={type}
- showPlusMinus={false}
- tooltip={this.label}
- type={Type.PRIM}
- min={NumCast(this.rootDoc.numBtnMin, 0)}
- max={NumCast(this.rootDoc.numBtnMax, 100)}
- number={checkResult}
- setNumber={undoable(value => numScript(value), `${this.rootDoc.title} button set from list`)}
- fillWidth
- />
+ return (
+ <NumberDropdown
+ color={color}
+ numberDropdownType={type}
+ showPlusMinus={false}
+ tooltip={this.label}
+ type={Type.PRIM}
+ min={NumCast(this.rootDoc.numBtnMin, 0)}
+ max={NumCast(this.rootDoc.numBtnMax, 100)}
+ number={checkResult}
+ setNumber={undoable(value => numScript(value), `${this.rootDoc.title} button set from list`)}
+ fillWidth
+ />
+ );
}
/**
@@ -202,84 +204,69 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
let dropdown = true;
let getStyle: (val: string) => any = () => {};
let icon: IconProp = 'caret-down';
- let isViewDropdown: boolean = script?.script.originalScript.startsWith('setView')
+ let isViewDropdown: boolean = script?.script.originalScript.startsWith('setView');
try {
if (isViewDropdown) {
const selectedDocs: Doc[] = SelectionManager.Docs();
const selected = SelectionManager.Docs().lastElement();
- console.log('selected')
+ console.log('selected');
if (selected) {
if (StrCast(selected.type) === DocumentType.COL) {
text = StrCast(selected._type_collection);
- console.log("collection selected", text)
+ console.log('collection selected', text);
} else {
- console.log("doc selected", selected.title);
+ console.log('doc selected', selected.title);
dropdown = false;
if (selectedDocs.length > 1) {
- text = selectedDocs.length + " selected"
+ text = selectedDocs.length + ' selected';
} else {
text = Utils.cleanDocumentType(StrCast(selected.type) as DocumentType);
icon = Doc.toIcon(selected);
}
- return <Popup
- icon={<FontAwesomeIcon size={'1x'} icon={icon} />}
- text={text}
- type={Type.TERT}
- color={color}
- popup={<SelectedDocView selectedDocs={selectedDocs}/>}
- fillWidth
- />
+ return <Popup icon={<FontAwesomeIcon size={'1x'} icon={icon} />} text={text} type={Type.TERT} color={color} popup={<SelectedDocView selectedDocs={selectedDocs} />} fillWidth />;
}
} else {
dropdown = false;
- return <Button
- text={`None Selected`}
- type={Type.TERT}
- color={color}
- fillWidth
- inactive
- />
+ return <Button text={`None Selected`} type={Type.TERT} color={color} fillWidth inactive />;
}
noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking, CollectionViewType.NoteTaking];
- } else {
+ } else {
text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
- getStyle = (val: string) => { return { fontFamily: val } }
+ getStyle = (val: string) => {
+ return { fontFamily: val };
+ };
}
} catch (e) {
console.log(e);
}
- console.log("current item: ", text);
+ console.log('current item: ', text);
// Get items to place into the list
const list: IListItemProps[] = this.buttonList
.filter(value => !Doc.noviceMode || !noviceList.length || noviceList.includes(value))
- .map(value => (
- {
- text: value.charAt(0).toUpperCase() + value.slice(1),
- val: value,
- style: getStyle(value),
- onClick: undoable(() => script.script.run({ self: this.rootDoc, value }), value)
- // shortcut: '#',
- }
- ));
-
+ .map(value => ({
+ text: value.charAt(0).toUpperCase() + value.slice(1),
+ val: value,
+ style: getStyle(value),
+ onClick: undoable(() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value }), value),
+ // shortcut: '#',
+ }));
return (
- <Dropdown
+ <Dropdown
selectedVal={text}
- setSelectedVal={undoable((val) => script.script.run({ self: this.rootDoc, val }), `dropdown select ${this.label}`)}
- color={color}
- type={isViewDropdown ? Type.TERT : Type.PRIM}
- dropdownType={DropdownType.SELECT}
+ setSelectedVal={undoable(val => script.script.run({ this: this.layoutDoc, self: this.rootDoc, val }), `dropdown select ${this.label}`)}
+ color={color}
+ type={isViewDropdown ? Type.TERT : Type.PRIM}
+ dropdownType={DropdownType.SELECT}
items={list}
tooltip={this.label}
fillWidth
/>
- )
+ );
}
-
@computed get colorScript() {
return ScriptCast(this.rootDoc.script);
}
@@ -290,14 +277,14 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
@computed get colorButton() {
const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
- const curColor = this.colorScript?.script.run({ self: this.rootDoc, value: undefined, _readOnly_: true }).result ?? 'transparent';
+ const curColor = this.colorScript?.script.run({ this: this.layoutDoc, self: this.rootDoc, value: undefined, _readOnly_: true }).result ?? 'transparent';
const tooltip: string = StrCast(this.rootDoc.toolTip);
return (
- <ColorPicker
- setSelectedColor={(value) => {
+ <ColorPicker
+ setSelectedColor={value => {
const s = this.colorScript;
- s && undoable(() => s.script.run({ self: this.rootDoc, value: value, _readOnly_: false }).result, `Set ${tooltip} to ${value}`)();
+ s && undoable(() => s.script.run({ this: this.layoutDoc, self: this.rootDoc, value: value, _readOnly_: false }).result, `Set ${tooltip} to ${value}`)();
}}
selectedColor={curColor}
type={Type.PRIM}
@@ -306,7 +293,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
tooltip={tooltip}
label={this.label}
/>
- )
+ );
}
@computed get toggleButton() {
@@ -315,25 +302,24 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
const tooltip: string = StrCast(this.rootDoc.toolTip);
const script = ScriptCast(this.rootDoc.onClick);
- const toggleStatus = script ? script.script.run({ self: this.rootDoc, value: undefined, _readOnly_: true }).result : false;
+ const toggleStatus = script ? script.script.run({ this: this.layoutDoc, self: this.rootDoc, value: undefined, _readOnly_: true }).result : false;
// Colors
const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
- console.log(tooltip, toggleStatus);
return (
- <Toggle
- tooltip={`Toggle ${tooltip}`}
- toggleType={ToggleType.BUTTON}
- type={Type.PRIM}
- toggleStatus={toggleStatus}
- text={buttonText}
- color={color}
- icon={this.Icon(color)!}
+ <Toggle
+ tooltip={`Toggle ${tooltip}`}
+ toggleType={ToggleType.BUTTON}
+ type={Type.PRIM}
+ toggleStatus={toggleStatus}
+ text={buttonText}
+ color={color}
+ icon={this.Icon(color)!}
label={this.label}
- onPointerDown={() => script.script.run({ self: this.rootDoc, value: !toggleStatus, _readOnly_: false })}
+ onPointerDown={() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value: !toggleStatus, _readOnly_: false })}
/>
- )
+ );
}
/**
@@ -344,28 +330,24 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
const tooltip: string = StrCast(this.rootDoc.toolTip);
- return (
- <IconButton tooltip={tooltip} icon={this.Icon(color)!} label={this.label}/>
- )
+ return <IconButton tooltip={tooltip} icon={this.Icon(color)!} label={this.label} />;
}
@computed get editableText() {
// Script for running the toggle
const script = ScriptCast(this.rootDoc.script);
// Function to run the script
- const checkResult = script?.script.run({ value: '', _readOnly_: true }).result;
+ const checkResult = script?.script.run({ this: this.layoutDoc, self: this.rootDoc, value: '', _readOnly_: true }).result;
+
+ const setValue = (value: string, shiftDown?: boolean): boolean => script?.script.run({ this: this.layoutDoc, self: this.rootDoc, value, _readOnly_: false }).result;
+
+ return <EditableText editing={false} setEditing={(editing: boolean) => {}} />;
- const setValue = (value: string, shiftDown?: boolean): boolean => script?.script.run({ value, _readOnly_: false }).result;
-
- return <EditableText
- editing={false} setEditing={(editing: boolean) => {}}
- />
-
return (
<div className="menuButton editableText">
<FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={'lock'} />
<div style={{ width: 'calc(100% - .875em)', paddingLeft: '4px' }}>
- <EditableView GetValue={() => script?.script.run({ value: '', _readOnly_: true }).result} SetValue={setValue} oneLine={true} contents={checkResult} />
+ <EditableView GetValue={() => script?.script.run({ this: this.layoutDoc, self: this.rootDoc, value: '', _readOnly_: true }).result} SetValue={setValue} oneLine={true} contents={checkResult} />
</div>
</div>
);
@@ -403,7 +385,8 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
case ButtonType.ClickButton:
case ButtonType.ToolButton:
button = (
- <IconButton tooltip={tooltip} onPointerDown={() => onClickScript?.script.run({ _readOnly_: false })} color={color} icon={this.Icon(color)!} label={this.label}/>
+ <IconButton tooltip={tooltip}
+ color={color} icon={this.Icon(color)!} label={this.label}/>
);
break;
case ButtonType.TextButton:
@@ -412,7 +395,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
);
break;
case ButtonType.MenuButton: button = (
- <IconButton tooltip={tooltip} onPointerDown={() => onClickScript?.script.run({ self: this.rootDoc, _readOnly_: false })} tooltipPlacement='right' size={Size.LARGE} color={color} icon={this.Icon(color)!} label={this.label}/>
+ <IconButton tooltip={tooltip} onPointerDown={() => onClickScript?.script.run({ this: this.layoutDoc, self: this.rootDoc, _readOnly_: false })} tooltipPlacement='right' size={Size.LARGE} color={color} icon={this.Icon(color)!} label={this.label}/>
);
break;
}
diff --git a/src/client/views/nodes/LinkBox.scss b/src/client/views/nodes/LinkBox.scss
index b5b8e660f..767f0291b 100644
--- a/src/client/views/nodes/LinkBox.scss
+++ b/src/client/views/nodes/LinkBox.scss
@@ -1,3 +1,7 @@
-.linkBox-container-interactive {
+.linkBox-container-interactive {
pointer-events: all;
-} \ No newline at end of file
+ width: 100%;
+}
+.linkBox-container {
+ width: 100%;
+}
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index b4fb7a44e..d5ad128fe 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.tsx
@@ -17,6 +17,7 @@ import { OpenWhere } from '../DocumentView';
import './DashFieldView.scss';
import { FormattedTextBox } from './FormattedTextBox';
import React = require('react');
+import { Transform } from '../../../util/Transform';
export class DashFieldView {
dom: HTMLDivElement; // container for label and value
@@ -113,6 +114,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
componentWillUnmount() {
this._reactionDisposer?.();
}
+ return100 = () => 100;
// set the display of the field's value (checkbox for booleans, span of text for strings)
@computed get fieldValueContent() {
@@ -123,7 +125,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
col={0}
deselectCell={emptyFunction}
selectCell={emptyFunction}
- maxWidth={this.props.hideKey ? undefined : () => 100}
+ maxWidth={this.props.hideKey ? undefined : this.return100}
columnWidth={this.props.hideKey ? () => this.props.tbox.props.PanelWidth() - 20 : returnZero}
selectedCell={() => [this._dashDoc!, 0]}
fieldKey={this._fieldKey}
@@ -135,6 +137,8 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
allowCRs={true}
oneLine={!this._expanded}
finishEdit={action(() => (this._expanded = false))}
+ transform={Transform.Identity}
+ menuTarget={null}
/>
</div>
);
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 0fd93868a..1319a236d 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -26,6 +26,7 @@ import { Annotation } from './Annotation';
import './PDFViewer.scss';
import React = require('react');
import { GPTPopup } from './GPTPopup/GPTPopup';
+import { InkingStroke } from '../InkingStroke';
const PDFJSViewer = require('pdfjs-dist/web/pdf_viewer');
const pdfjsLib = require('pdfjs-dist');
const _global = (window /* browser */ || global) /* node */ as any;
@@ -519,7 +520,8 @@ export class PDFViewer extends React.Component<IViewerProps> {
childStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string): any => {
if (doc instanceof Doc && property === StyleProp.PointerEvents) {
if (this.inlineTextAnnotations.includes(doc) || this.props.isContentActive() === false) return 'none';
- return 'all';
+ const isInk = doc && StrCast(Doc.Layout(doc).layout).includes(InkingStroke.name) && !props?.LayoutTemplateString;
+ return isInk ? 'visiblePainted' : 'all';
}
return this.props.styleProvider?.(doc, props, property);
};
@@ -537,7 +539,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
NativeWidth={returnZero}
NativeHeight={returnZero}
setContentView={emptyFunction} // override setContentView to do nothing
- pointerEvents={SnappingManager.GetIsDragging() && this.props.isContentActive() ? returnAll : returnNone} // freeform view doesn't get events unless something is being dragged onto it.
+ pointerEvents={this.props.isContentActive() && (SnappingManager.GetIsDragging() || Doc.ActiveTool !== InkTool.None) ? returnAll : returnNone} // freeform view doesn't get events unless something is being dragged onto it.
childPointerEvents={this.props.isContentActive() !== false ? 'all' : 'none'} // but freeform children need to get events to allow text editing, etc
renderDepth={this.props.renderDepth + 1}
isAnnotationOverlay={true}
diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
index 79f41fe9d..ec4252eb8 100644
--- a/src/client/views/topbar/TopBar.tsx
+++ b/src/client/views/topbar/TopBar.tsx
@@ -134,14 +134,16 @@ export class TopBar extends React.Component {
@computed get topbarRight() {
return (
<div className="topbar-right">
- <Button
- text={GetEffectiveAcl(Doc.ActiveDashboard) === AclAdmin ? 'Share' : 'View Original'}
- type={Type.TERT}
- color={this.variantColor}
- onClick={() => {
- SharingManager.Instance.open(undefined, Doc.ActiveDashboard);
- }}
- />
+ {Doc.ActiveDashboard ?
+ <Button
+ text={GetEffectiveAcl(Doc.ActiveDashboard) === AclAdmin ? 'Share' : 'View Original'}
+ type={Type.TERT}
+ color={this.variantColor}
+ onClick={() => {
+ SharingManager.Instance.open(undefined, Doc.ActiveDashboard);
+ }}
+ />
+ : null }
<IconButton tooltip={"Issue Reporter ⌘I"} size={Size.SMALL} color={this.color} onClick={ReportManager.Instance.open} icon={<FaBug />} />
<IconButton tooltip={"Documentation ⌘D"} size={Size.SMALL} color={this.color} onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/', '_blank')} icon={<FontAwesomeIcon icon="question-circle" />} />
<IconButton tooltip={"Settings ⌘⇧S"} size={Size.SMALL} color={this.color} onClick={SettingsManager.Instance.open} icon={<FontAwesomeIcon icon="cog" />} />