aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSophie Zhang <sophie_zhang@brown.edu>2023-07-27 14:00:44 -0400
committerSophie Zhang <sophie_zhang@brown.edu>2023-07-27 14:00:44 -0400
commit4ad1c765afcb0402f00ea6a91bf5811904e2a30e (patch)
tree764cb5dd8aacbe1e2be55d58dd65a7ac2295ec7a /src
parentfec79d2b5b8feb361e489c9ee41ee720507d0806 (diff)
parent1f80b87178a84c1a449e27c90b1f7b635593cdad (diff)
Merge branch 'master' into sophie-ai-images
Diffstat (limited to 'src')
-rw-r--r--src/Utils.ts18
-rw-r--r--src/client/DocServer.ts6
-rw-r--r--src/client/util/CurrentUserUtils.ts2
-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.tsx86
-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/MainView.scss8
-rw-r--r--src/client/views/MainView.tsx2
-rw-r--r--src/client/views/PropertiesButtons.tsx2
-rw-r--r--src/client/views/PropertiesView.scss44
-rw-r--r--src/client/views/PropertiesView.tsx70
-rw-r--r--src/client/views/StyleProvider.tsx11
-rw-r--r--src/client/views/UndoStack.tsx10
-rw-r--r--src/client/views/collections/TreeView.scss23
-rw-r--r--src/client/views/collections/TreeView.tsx30
-rw-r--r--src/client/views/nodes/DocumentView.tsx2
-rw-r--r--src/client/views/pdf/PDFViewer.tsx6
-rw-r--r--src/client/views/topbar/TopBar.tsx18
-rw-r--r--src/server/server_Initialization.ts28
28 files changed, 459 insertions, 336 deletions
diff --git a/src/Utils.ts b/src/Utils.ts
index e03632c8b..599c6456a 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -16,18 +16,18 @@ export namespace Utils {
return Date.now() - downTime < Utils.CLICK_TIME && Math.abs(x - downX) < Utils.DRAG_THRESHOLD && Math.abs(y - downY) < Utils.DRAG_THRESHOLD;
}
- export function cleanDocumentType(type: DocumentType) {
- switch(type) {
+ export function cleanDocumentType(type: DocumentType) {
+ switch (type) {
case DocumentType.IMG:
- return "Image"
+ return 'Image';
case DocumentType.AUDIO:
- return "Audio"
+ return 'Audio';
case DocumentType.COL:
- return "Collection"
+ return 'Collection';
case DocumentType.RTF:
- return "Text"
- default:
- return type.charAt(0).toUpperCase() + type.slice(1)
+ return 'Text';
+ default:
+ return type.charAt(0).toUpperCase() + type.slice(1);
}
}
@@ -140,7 +140,7 @@ export namespace Utils {
}
export function colorString(color: ColorState) {
- return color.hex.startsWith('#') ? color.hex + (color.rgb.a ? decimalToHexString(Math.round(color.rgb.a * 255)) : 'ff') : color.hex;
+ return color.hex.startsWith('#') && color.hex.length < 8 ? color.hex + (color.rgb.a ? decimalToHexString(Math.round(color.rgb.a * 255)) : 'ff') : color.hex;
}
export function fromRGBAstr(rgba: string) {
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 39137462a..2e4fb0f1c 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -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/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..795df9c08 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 } 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,13 +525,11 @@ 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>
+ <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 ? (
@@ -557,28 +555,26 @@ export class SharingManager extends React.Component<{}> {
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')} />
+ <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>
+ <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={"tertiary"} color={StrCast(Doc.UserDoc().userColor)} icon={<FontAwesomeIcon icon={"copy"} size="sm" />} iconPlacement={"left"} text={"Copy Guest URL"} />
+ </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 +586,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 +611,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={"tertiary"} 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 +623,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,25 +638,22 @@ 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>
</div>
<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" />
+ <div className="title-group" >
+ 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>
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/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 7c1abc232..41c8dd19d 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -892,7 +892,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 3a3b2fc38..2e3668268 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -111,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;
}
);
}
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 a6a99b3cc..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}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index c7616a9ba..bbbad3690 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -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;
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/TreeView.scss b/src/client/views/collections/TreeView.scss
index cfa658944..d22e85880 100644
--- a/src/client/views/collections/TreeView.scss
+++ b/src/client/views/collections/TreeView.scss
@@ -47,6 +47,7 @@
color: $medium-gray;
border: #80808030 1px solid;
border-radius: 5px;
+ z-index: 1;
}
}
@@ -54,9 +55,6 @@
position: absolute;
height: max-content;
pointer-events: none;
- color: white;
- border-radius: 4px;
- font-size: 10px;
}
.treeView-container-active {
@@ -104,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 {
@@ -140,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 9158508fc..d904749b1 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -539,7 +539,7 @@ 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 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)) {
@@ -585,8 +585,23 @@ export class TreeView extends React.Component<TreeViewProps> {
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 +704,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
@@ -757,7 +772,7 @@ 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 = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.Color);
+ const color = StrCast(Doc.UserDoc().userColor);
return this.props.treeViewHideHeaderFields() || this.doc.treeViewHideHeaderFields ? null : (
<>
{customHeaderButtons} {/* e.g.,. hide button is set by dashboardStyleProvider */}
@@ -1000,6 +1015,11 @@ 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/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 38922cb24..66352678c 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1236,7 +1236,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
const renderDoc = this.renderDoc({
borderRadius: this.borderRounding,
outline: highlighting && !this.borderRounding && !highlighting.highlightStroke ? `${highlighting.highlightColor} ${highlighting.highlightStyle} ${highlighting.highlightIndex}px` : 'solid 0px',
- border: highlighting && this.borderRounding && highlighting.highlightStyle === 'dashed' ? `${highlighting.highlightStyle} ${highlighting.highlightColor} ${highlighting.highlightIndex}px` : undefined,
+ border: highlighting && this.borderRounding && highlighting.highlightStyle === 'dashed' ? `${highlighting.highlightStyle} ${highlighting.highlightColor} ${highlighting.highlightIndex}px` : undefined,
boxShadow,
clipPath: borderPath?.clipPath,
});
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 1d1c34f4f..c9fee4813 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;
@@ -523,7 +524,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);
};
@@ -541,7 +543,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 b82f20dbd..cb8eda9de 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" />} />
diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts
index 805da1d43..c1934451c 100644
--- a/src/server/server_Initialization.ts
+++ b/src/server/server_Initialization.ts
@@ -149,23 +149,15 @@ function registerAuthenticationRoutes(server: express.Express) {
function registerCorsProxy(server: express.Express) {
server.use('/corsProxy', async (req, res) => {
- const referer = req.headers.referer ? decodeURIComponent(req.headers.referer) : '';
- let requrlraw = decodeURIComponent(req.url.substring(1));
- const qsplit = requrlraw.split('?q=');
- const newqsplit = requrlraw.split('&q=');
+ //const referer = req.headers.referer ? decodeURIComponent(req.headers.referer) : '';
+ let requrl = decodeURIComponent(req.url.substring(1));
+ const qsplit = requrl.split('?q=');
+ const newqsplit = requrl.split('&q=');
if (qsplit.length > 1 && newqsplit.length > 1) {
const lastq = newqsplit[newqsplit.length - 1];
- requrlraw = qsplit[0] + '?q=' + lastq.split('&')[0] + '&' + qsplit[1].split('&')[1];
- }
- const requrl = requrlraw.startsWith('/') ? referer + requrlraw : requrlraw;
- // cors weirdness here...
- // if the referer is a cors page and the cors() route (I think) redirected to /corsProxy/<path> and the requested url path was relative,
- // then we redirect again to the cors referer and just add the relative path.
- if (!requrl.startsWith('http') && req.originalUrl.startsWith('/corsProxy') && referer?.includes('corsProxy')) {
- res.redirect(referer + (referer.endsWith('/') ? '' : '/') + requrl);
- } else {
- proxyServe(req, requrl, res);
+ requrl = qsplit[0] + '?q=' + lastq.split('&')[0] + '&' + qsplit[1].split('&')[1];
}
+ proxyServe(req, requrl, res);
});
}
@@ -184,7 +176,7 @@ function proxyServe(req: any, requrl: string, response: any) {
const htmlText = htmlInputText
.toString('utf8')
.replace('<head>', '<head> <style>[id ^= "google"] { display: none; } </style>')
- .replace(/href="https?([^"]*)"/g, httpsToCors)
+ // .replace(/href="https?([^"]*)"/g, httpsToCors)
.replace(/data-srcset="[^"]*"/g, '')
.replace(/srcset="[^"]*"/g, '')
.replace(/target="_blank"/g, '');
@@ -234,8 +226,10 @@ function proxyServe(req: any, requrl: string, response: any) {
function registerEmbeddedBrowseRelativePathHandler(server: express.Express) {
server.use('*', (req, res) => {
const relativeUrl = req.originalUrl;
- if (!req.user) res.redirect('/home'); // When no user is logged in, we interpret a relative URL as being a reference to something they don't have access to and redirect to /home
- else if (!res.headersSent && req.headers.referer?.includes('corsProxy')) {
+ // if (req.originalUrl === '/css/main.css' || req.originalUrl === '/favicon.ico') res.end();
+ // else
+ if (!res.headersSent && req.headers.referer?.includes('corsProxy')) {
+ if (!req.user) res.redirect('/home'); // When no user is logged in, we interpret a relative URL as being a reference to something they don't have access to and redirect to /home
// a request for something by a proxied referrer means it must be a relative reference. So construct a proxied absolute reference here.
try {
const proxiedRefererUrl = decodeURIComponent(req.headers.referer); // (e.g., http://localhost:<port>/corsProxy/https://en.wikipedia.org/wiki/Engelbart)