diff options
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 2 | ||||
-rw-r--r-- | src/client/util/RTFMarkup.tsx | 2 | ||||
-rw-r--r-- | src/client/util/SelectionManager.ts | 5 | ||||
-rw-r--r-- | src/client/util/ServerStats.tsx | 2 | ||||
-rw-r--r-- | src/client/views/DashboardView.tsx | 12 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/PropertiesDocBacklinksSelector.tsx | 7 | ||||
-rw-r--r-- | src/client/views/PropertiesView.scss | 6 | ||||
-rw-r--r-- | src/client/views/PropertiesView.tsx | 71 | ||||
-rw-r--r-- | src/client/views/collections/TabDocView.tsx | 4 | ||||
-rw-r--r-- | src/client/views/linking/LinkMenuItem.tsx | 15 |
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} |