aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/util/CurrentUserUtils.ts2
-rw-r--r--src/client/util/RTFMarkup.tsx2
-rw-r--r--src/client/util/SelectionManager.ts5
-rw-r--r--src/client/util/ServerStats.tsx2
-rw-r--r--src/client/views/DashboardView.tsx12
-rw-r--r--src/client/views/MainView.tsx2
-rw-r--r--src/client/views/PropertiesDocBacklinksSelector.tsx7
-rw-r--r--src/client/views/PropertiesView.scss6
-rw-r--r--src/client/views/PropertiesView.tsx71
-rw-r--r--src/client/views/collections/TabDocView.tsx4
-rw-r--r--src/client/views/linking/LinkMenuItem.tsx15
11 files changed, 81 insertions, 47 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index af0f62c0f..836160265 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -488,7 +488,7 @@ export class CurrentUserUtils {
const contextMenuLabels = [/*"Create New Dashboard"*/] as string[];
const contextMenuIcons = [/*"plus"*/] as string[];
const childContextMenuScripts = [toggleDarkTheme, `toggleComicMode()`, `snapshotDashboard()`, `shareDashboard(self)`, 'removeDashboard(self)', 'resetDashboard(self)']; // entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuFilters
- const childContextMenuFilters = ['!IsNoviceMode()', '!IsNoviceMode()', '!IsNoviceMode()', undefined as any, undefined as any, undefined as any];// entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuScripts
+ const childContextMenuFilters = ['!IsNoviceMode()', '!IsNoviceMode()', '!IsNoviceMode()', undefined as any, undefined as any, '!IsNoviceMode()'];// entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuScripts
const childContextMenuLabels = ["Toggle Dark Theme", "Toggle Comic Mode", "Snapshot Dashboard", "Share Dashboard", "Remove Dashboard", "Reset Dashboard"];// entries must be kept in synch with childContextMenuScripts, childContextMenuIcons, and childContextMenuFilters
const childContextMenuIcons = ["chalkboard", "tv", "camera", "users", "times", "trash"]; // entries must be kept in synch with childContextMenuScripts, childContextMenuLabels, and childContextMenuFilters
const reqdOpts:DocumentOptions = {
diff --git a/src/client/util/RTFMarkup.tsx b/src/client/util/RTFMarkup.tsx
index 78069d323..9dd14a3c3 100644
--- a/src/client/util/RTFMarkup.tsx
+++ b/src/client/util/RTFMarkup.tsx
@@ -33,7 +33,7 @@ export class RTFMarkup extends React.Component<{}> {
*/
@computed get cheatSheet() {
return (
- <div style={{ background: SettingsManager.Instance?.userBackgroundColor, color: SettingsManager.Instance?.userColor, textAlign: 'initial', height: '100%' }}>
+ <div style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor, textAlign: 'initial', height: '100%' }}>
<p>
<b style={{ fontSize: 'larger' }}>{`wiki:phrase`}</b>
{` display wikipedia page for entered text (terminate with carriage return)`}
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index dbf33fcf5..d0f66d124 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -26,9 +26,6 @@ export namespace SelectionManager {
// if doc is not in SelectedDocuments, add it
if (!manager.SelectedViewsMap.get(docView)) {
if (!ctrlPressed) {
- if (LinkManager.currentLink && !LinkManager.Links(docView.rootDoc).includes(LinkManager.currentLink) && docView.rootDoc !== LinkManager.currentLink) {
- LinkManager.currentLink = undefined;
- }
this.DeselectAll();
}
@@ -54,6 +51,8 @@ export namespace SelectionManager {
}
@action
DeselectAll(): void {
+ LinkManager.currentLink = undefined;
+ LinkManager.currentLinkAnchor = undefined;
manager.SelectedSchemaDocument = undefined;
Array.from(manager.SelectedViewsMap.keys()).forEach(dv => dv.props.whenChildContentsActiveChanged(false));
manager.SelectedViewsMap.clear();
diff --git a/src/client/util/ServerStats.tsx b/src/client/util/ServerStats.tsx
index 3c7c35a7e..ac9fecd5c 100644
--- a/src/client/util/ServerStats.tsx
+++ b/src/client/util/ServerStats.tsx
@@ -48,7 +48,7 @@ export class ServerStats extends React.Component<{}> {
display: 'flex',
height: 300,
width: 400,
- background: SettingsManager.Instance?.userBackgroundColor,
+ background: SettingsManager.userBackgroundColor,
opacity: 0.6,
}}>
<div style={{ width: 300, height: 100, margin: 'auto', display: 'flex', flexDirection: 'column' }}>
diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx
index 3ef6c0814..34c752eec 100644
--- a/src/client/views/DashboardView.tsx
+++ b/src/client/views/DashboardView.tsx
@@ -18,7 +18,7 @@ import { CollectionViewType } from '../documents/DocumentTypes';
import { HistoryUtil } from '../util/History';
import { ScriptingGlobals } from '../util/ScriptingGlobals';
import { SharingManager } from '../util/SharingManager';
-import { undoBatch, UndoManager } from '../util/UndoManager';
+import { undoable, undoBatch, UndoManager } from '../util/UndoManager';
import { CollectionDockingView } from './collections/CollectionDockingView';
import { CollectionView } from './collections/CollectionView';
import { ContextMenu } from './ContextMenu';
@@ -270,6 +270,7 @@ export class DashboardView extends React.Component {
public static openDashboard = (doc: Doc | undefined, fromHistory = false) => {
if (!doc) return false;
Doc.AddDocToList(Doc.MyDashboards, 'data', doc);
+ Doc.RemoveDocFromList(Doc.MyRecentlyClosed, 'data', doc);
// this has the side-effect of setting the main container since we're assigning the active/guest dashboard
Doc.UserDoc() ? (Doc.ActiveDashboard = doc) : (Doc.GuestDashboard = doc);
@@ -307,9 +308,12 @@ export class DashboardView extends React.Component {
public static removeDashboard = async (dashboard: Doc) => {
const dashboards = await DocListCastAsync(Doc.MyDashboards.data);
if (dashboards?.length) {
- if (dashboard === Doc.ActiveDashboard) DashboardView.openDashboard(dashboards.find(doc => doc !== dashboard));
- Doc.RemoveDocFromList(Doc.MyDashboards, 'data', dashboard);
- if (!dashboards.length) Doc.ActivePage = 'home';
+ undoable(() => {
+ if (dashboard === Doc.ActiveDashboard) DashboardView.openDashboard(dashboards.find(doc => doc !== dashboard));
+ Doc.RemoveDocFromList(Doc.MyDashboards, 'data', dashboard);
+ Doc.AddDocToList(Doc.MyRecentlyClosed, 'data', dashboard, undefined, true, true);
+ if (!dashboards.length) Doc.ActivePage = 'home';
+ }, 'remove dashboard')();
}
};
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index c8b89c1d5..8adb28fe1 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -696,7 +696,7 @@ export class MainView extends React.Component {
switch (whereFields[0]) {
case OpenWhere.lightbox: return LightboxView.AddDocTab(doc, location);
case OpenWhere.close: return CollectionDockingView.CloseSplit(doc, whereMods);
- case OpenWhere.toggle: return CollectionDockingView.ToggleSplit(doc, whereMods);
+ case OpenWhere.toggle: return CollectionDockingView.ToggleSplit(doc, whereMods, undefined, "dontSelectOnActivate"); // bcz: hack! mark the toggle so that it won't be selected on activation- this is needed so that the backlinks menu can toggle views of targets on and off without selecting them
case OpenWhere.add:default:return CollectionDockingView.AddSplit(doc, whereMods, undefined, undefined, keyValue);
}
};
diff --git a/src/client/views/PropertiesDocBacklinksSelector.tsx b/src/client/views/PropertiesDocBacklinksSelector.tsx
index 91a7b3da3..2d1e46361 100644
--- a/src/client/views/PropertiesDocBacklinksSelector.tsx
+++ b/src/client/views/PropertiesDocBacklinksSelector.tsx
@@ -1,3 +1,4 @@
+import { action } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc } from '../../fields/Doc';
@@ -19,16 +20,16 @@ type PropertiesDocBacklinksSelectorProps = {
@observer
export class PropertiesDocBacklinksSelector extends React.Component<PropertiesDocBacklinksSelectorProps> {
- getOnClick = (link: Doc) => {
+ getOnClick = action((link: Doc) => {
const linkAnchor = this.props.Document;
const other = LinkManager.getOppositeAnchor(link, linkAnchor);
const otherdoc = !other ? undefined : other.annotationOn && other.type !== DocumentType.RTF ? Cast(other.annotationOn, Doc, null) : other;
-
+ LinkManager.currentLink = link;
if (otherdoc) {
otherdoc.hidden = false;
this.props.addDocTab(Doc.IsDataProto(otherdoc) ? Doc.MakeDelegate(otherdoc) : otherdoc, OpenWhere.toggleRight);
}
- };
+ });
render() {
return !SelectionManager.Views().length ? null : (
diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss
index b116a622c..510defce4 100644
--- a/src/client/views/PropertiesView.scss
+++ b/src/client/views/PropertiesView.scss
@@ -26,6 +26,12 @@
display: flex;
flex-direction: row;
}
+ .propertiesView-titleExtender {
+ text-overflow: ellipsis;
+ max-width: 100%;
+ white-space: pre;
+ overflow: hidden;
+ }
overflow-x: hidden;
overflow-y: auto;
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 01329b482..6f1461fea 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -3,14 +3,12 @@ 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, IconButton, NumberInput, Size, Slider, Type } from 'browndash-components';
+import { Colors, EditableText, IconButton, NumberInput, Size, Slider, Type } from 'browndash-components';
import { concat } from 'lodash';
-import { Lambda, action, computed, observable } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { ColorState, SketchPicker } from 'react-color';
import * as Icons from 'react-icons/bs'; //{BsCollectionFill, BsFillFileEarmarkImageFill} from "react-icons/bs"
-import { GrCircleInformation } from 'react-icons/gr';
-import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../Utils';
import { Doc, DocListCast, Field, FieldResult, HierarchyMapping, NumListCast, Opt, ReverseHierarchyMap, StrListCast } from '../../fields/Doc';
import { AclAdmin, DocAcl, DocData, Height, Width } from '../../fields/DocSymbols';
import { Id } from '../../fields/FieldSymbols';
@@ -18,28 +16,29 @@ import { InkField } from '../../fields/InkField';
import { List } from '../../fields/List';
import { ComputedField } from '../../fields/ScriptField';
import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types';
-import { GetEffectiveAcl, SharingPermissions, normalizeEmail } from '../../fields/util';
+import { GetEffectiveAcl, normalizeEmail, SharingPermissions } from '../../fields/util';
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../Utils';
import { DocumentType } from '../documents/DocumentTypes';
import { DocumentManager } from '../util/DocumentManager';
import { GroupManager } from '../util/GroupManager';
import { LinkManager } from '../util/LinkManager';
import { SelectionManager } from '../util/SelectionManager';
+import { SettingsManager } from '../util/SettingsManager';
import { SharingManager } from '../util/SharingManager';
import { Transform } from '../util/Transform';
-import { UndoManager, undoBatch, undoable } from '../util/UndoManager';
+import { undoable, undoBatch, UndoManager } from '../util/UndoManager';
import { EditableView } from './EditableView';
import { FilterPanel } from './FilterPanel';
import { InkStrokeProperties } from './InkStrokeProperties';
+import { DocumentView, OpenWhere, StyleProviderFunc } from './nodes/DocumentView';
+import { KeyValueBox } from './nodes/KeyValueBox';
+import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails';
import { PropertiesButtons } from './PropertiesButtons';
import { PropertiesDocBacklinksSelector } from './PropertiesDocBacklinksSelector';
import { PropertiesDocContextSelector } from './PropertiesDocContextSelector';
import { PropertiesSection } from './PropertiesSection';
import './PropertiesView.scss';
import { DefaultStyleProvider } from './StyleProvider';
-import { DocumentView, OpenWhere, StyleProviderFunc } from './nodes/DocumentView';
-import { KeyValueBox } from './nodes/KeyValueBox';
-import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails';
-import { SettingsManager } from '../util/SettingsManager';
const _global = (window /* browser */ || global) /* node */ as any;
interface PropertiesViewProps {
@@ -87,13 +86,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
@observable openTransform: boolean = true;
@observable openFilters: boolean = false;
- /**
- * autorun to set up the filter doc of a collection if that collection has been selected and the filters panel is open
- */
- private selectedDocListenerDisposer: Opt<Lambda>;
-
- // @observable selectedUser: string = "";
- // @observable addButtonPressed: boolean = false;
@observable layoutDocAcls: boolean = false;
//Pres Trails booleans:
@@ -105,14 +97,21 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
@observable inOptions: boolean = false;
@observable _controlButton: boolean = false;
+ private _disposers: { [name: string]: IReactionDisposer } = {};
componentDidMount() {
- this.selectedDocListenerDisposer?.();
- // this.selectedDocListenerDisposer = autorun(() => this.openFilters && this.selectedDoc && this.checkFilterDoc());
+ this._disposers.link = reaction(
+ () => LinkManager.currentLink,
+ link => {
+ link && this.onDoubleClick();
+ link && (this.openLinks = true);
+ },
+ { fireImmediately: true }
+ );
}
componentWillUnmount() {
- this.selectedDocListenerDisposer?.();
+ Object.values(this._disposers).forEach(disposer => disposer?.());
}
@computed get isInk() {
@@ -555,9 +554,29 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
@computed get editableTitle() {
const titles = new Set<string>();
- const title = Array.from(titles.keys()).length > 1 ? '--multiple selected--' : StrCast(this.selectedDoc?.title);
SelectionManager.Views().forEach(dv => titles.add(StrCast(dv.rootDoc.title)));
- return <EditableText val={title} setVal={this.setTitle} color={this.color} type={Type.SEC} formLabel={'Title'} fillWidth />;
+ const title = Array.from(titles.keys()).length > 1 ? '--multiple selected--' : StrCast(this.selectedDoc?.title);
+ return (
+ <div>
+ <EditableText val={title} setVal={this.setTitle} color={this.color} type={Type.SEC} formLabel={'Title'} fillWidth />
+ {LinkManager.currentLinkAnchor ? (
+ <p className="propertiesView-titleExtender">
+ <>
+ <b>Anchor:</b>
+ {LinkManager.currentLinkAnchor.title}
+ </>
+ </p>
+ ) : null}
+ {LinkManager.currentLink?.title ? (
+ <p className="propertiesView-titleExtender">
+ <>
+ <b>Link:</b>
+ {LinkManager.currentLink.title}
+ </>
+ </p>
+ ) : null}
+ </div>
+ );
}
@computed get currentType() {
@@ -1101,7 +1120,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
isOpen={this.openOptions}
setInSection={bool => (this.inOptions = bool)}
setIsOpen={bool => (this.openOptions = bool)}
- onDoubleClick={() => this.onDoubleClick()}
+ onDoubleClick={this.onDoubleClick}
/>
);
}
@@ -1209,11 +1228,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
}
@computed get linksSubMenu() {
- return <PropertiesSection title="Linked To" content={this.linkCount > 0 ? this.links : 'There are no current links.'} isOpen={this.openLinks} setIsOpen={bool => (this.openLinks = bool)} onDoubleClick={() => this.onDoubleClick()} />;
+ return <PropertiesSection title="Linked To" content={this.linkCount > 0 ? this.links : 'There are no current links.'} isOpen={this.openLinks} setIsOpen={bool => (this.openLinks = bool)} onDoubleClick={this.onDoubleClick} />;
}
@computed get layoutSubMenu() {
- return <PropertiesSection title="Layout" content={this.layoutPreview} isOpen={this.openLayout} setIsOpen={bool => (this.openLayout = bool)} onDoubleClick={() => this.onDoubleClick()} />;
+ return <PropertiesSection title="Layout" content={this.layoutPreview} isOpen={this.openLayout} setIsOpen={bool => (this.openLayout = bool)} onDoubleClick={this.onDoubleClick} />;
}
@computed get description() {
@@ -1699,7 +1718,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
<div className="propertiesView-type"> {this.currentType} </div>
{this.optionsSubMenu}
{this.linksSubMenu}
- {!this.selectedDoc || !LinkManager.currentLink || (!hasSelectedAnchor && this.selectedDoc !== LinkManager.currentLink) ? null : this.linkProperties}
+ {!LinkManager.currentLink || !this.openLinks ? null : this.linkProperties}
{this.inkSubMenu}
{this.contextsSubMenu}
{this.fieldsSubMenu}
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 6cdb84dea..9823dfe91 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -348,7 +348,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
private onActiveContentItemChanged(contentItem: any) {
if (!contentItem || (this.stack === contentItem.parent && ((contentItem?.tab === this.tab && !this._isActive) || (contentItem?.tab !== this.tab && this._isActive)))) {
this._activated = this._isActive = !contentItem || contentItem?.tab === this.tab;
- if (!this._view) setTimeout(() => SelectionManager.SelectView(this._view, false));
+ if (!this._view && this.tab?.contentItem?.config?.props?.panelName !== 'dontSelectOnActivate') setTimeout(() => SelectionManager.SelectView(this._view, false));
!this._isActive && this._document && Doc.UnBrushDoc(this._document); // bcz: bad -- trying to simulate a pointer leave event when a new tab is opened up on top of an existing one.
}
}
@@ -380,7 +380,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
return LightboxView.AddDocTab(doc, location);
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);
+ case OpenWhere.toggle: return CollectionDockingView.ToggleSplit(doc, whereMods, this.stack, "dontSelectOnActivate", keyValue);
case OpenWhere.add:default:return CollectionDockingView.AddSplit(doc, whereMods, this.stack, undefined, keyValue);
}
};
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 9bc8f5e8b..0a9d7543b 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -69,10 +69,8 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
}
return this.props.sourceDoc;
}
- @action
+
onEdit = (e: React.PointerEvent) => {
- LinkManager.currentLink = this.props.linkDoc === LinkManager.currentLink ? undefined : this.props.linkDoc;
- LinkManager.currentLinkAnchor = this.sourceAnchor;
setupMoveUpEvents(
this,
e,
@@ -90,8 +88,11 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
DocumentViewInternal.addDocTabFunc(trail, OpenWhere.replaceRight);
} else {
SelectionManager.SelectView(this.props.docView, false);
+ LinkManager.currentLink = this.props.linkDoc === LinkManager.currentLink ? undefined : this.props.linkDoc;
+ LinkManager.currentLinkAnchor = LinkManager.currentLink ? this.sourceAnchor : undefined;
+
if ((SettingsManager.propertiesWidth ?? 0) < 100) {
- SettingsManager.propertiesWidth = 250;
+ setTimeout(action(() => (SettingsManager.propertiesWidth = 250)));
}
}
})
@@ -150,7 +151,11 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
className="linkMenu-item"
onPointerEnter={action(e => (this._hover = true))}
onPointerLeave={action(e => (this._hover = false))}
- style={{ background: /*LinkManager.currentLink !== this.props.linkDoc*/ this._hover ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}>
+ style={{
+ fontSize: this._hover ? 'larger' : undefined,
+ fontWeight: this._hover ? 'bold' : undefined,
+ background: LinkManager.currentLink === this.props.linkDoc ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
+ }}>
<div className="linkMenu-item-content expand-two">
<div
ref={this._drag}