aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/DocumentButtonBar.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/DocumentButtonBar.tsx')
-rw-r--r--src/client/views/DocumentButtonBar.tsx193
1 files changed, 114 insertions, 79 deletions
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index d42ff436f..90c6c040c 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -1,31 +1,32 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@material-ui/core';
-import { action, computed, observable, runInAction } from 'mobx';
+import { action, computed, observable, runInAction, trace } from 'mobx';
import { observer } from 'mobx-react';
import { Doc } from '../../fields/Doc';
import { RichTextField } from '../../fields/RichTextField';
import { Cast, NumCast } from '../../fields/Types';
-import { emptyFunction, setupMoveUpEvents, simulateMouseClick } from '../../Utils';
+import { emptyFunction, returnFalse, setupMoveUpEvents, simulateMouseClick } from '../../Utils';
import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils';
import { Docs } from '../documents/Documents';
import { DragManager } from '../util/DragManager';
import { SelectionManager } from '../util/SelectionManager';
-import { SettingsManager } from '../util/SettingsManager';
import { SharingManager } from '../util/SharingManager';
-import { undoBatch } from '../util/UndoManager';
+import { undoBatch, UndoManager } from '../util/UndoManager';
import { CollectionDockingView } from './collections/CollectionDockingView';
import { TabDocView } from './collections/TabDocView';
import './DocumentButtonBar.scss';
import { Colors } from './global/globalEnums';
+import { LinkPopup } from './linking/LinkPopup';
import { MetadataEntryMenu } from './MetadataEntryMenu';
import { DocumentLinksButton } from './nodes/DocumentLinksButton';
-import { DocumentView, DocumentViewInternal } from './nodes/DocumentView';
+import { DocumentView, DocumentViewInternal, OpenWhereMod } from './nodes/DocumentView';
import { DashFieldView } from './nodes/formattedText/DashFieldView';
import { GoogleRef } from './nodes/formattedText/FormattedTextBox';
import { TemplateMenu } from './TemplateMenu';
import React = require('react');
+import { DocumentType } from '../documents/DocumentTypes';
const higflyout = require('@hig/flyout');
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -180,7 +181,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
googleDoc = Docs.Create.WebDocument(googleDocUrl, options);
dataDoc.googleDoc = googleDoc;
}
- CollectionDockingView.AddSplit(googleDoc, 'right');
+ CollectionDockingView.AddSplit(googleDoc, OpenWhereMod.right);
} else if (e.altKey) {
e.preventDefault();
window.open(googleDocUrl);
@@ -209,21 +210,74 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
</Tooltip>
);
}
+ @observable subFollow = '';
@computed
get followLinkButton() {
const targetDoc = this.view0?.props.Document;
+ const followBtn = (allDocs: boolean, click: (doc: Doc) => void, isSet: (doc?: Doc) => boolean, icon: IconProp) => {
+ const tooltip = `Follow ${this.subPin}documents`;
+ return !tooltip ? null : (
+ <Tooltip title={<div className="dash-tooltip">{tooltip}</div>}>
+ <div className="documentButtonBar-followIcon" style={{ backgroundColor: isSet(targetDoc) ? Colors.LIGHT_BLUE : Colors.DARK_GRAY, color: isSet(targetDoc) ? Colors.BLACK : Colors.WHITE }}>
+ <FontAwesomeIcon
+ className="documentdecorations-icon"
+ style={{ width: 20 }}
+ key={icon.toString()}
+ size="sm"
+ icon={icon}
+ onPointerEnter={action(e => (this.subPin = allDocs ? 'All ' : ''))}
+ onPointerLeave={action(e => (this.subPin = ''))}
+ onClick={e => {
+ this.props.views().forEach(dv => click(dv!.rootDoc));
+ e.stopPropagation();
+ }}
+ />
+ </div>
+ </Tooltip>
+ );
+ };
return !targetDoc ? null : (
- <Tooltip title={<div className="dash-tooltip">{'Set onClick to follow primary link'}</div>}>
+ <Tooltip title={<div className="dash-tooltip">Set onClick to follow primary link</div>}>
<div
- className="documentButtonBar-icon"
+ className="documentButtonBar-icon documentButtonBar-follow"
style={{ backgroundColor: targetDoc.isLinkButton ? Colors.LIGHT_BLUE : Colors.DARK_GRAY, color: targetDoc.isLinkButton ? Colors.BLACK : Colors.WHITE }}
onClick={undoBatch(e => this.props.views().map(view => view?.docView?.toggleFollowLink(undefined, undefined, false)))}>
+ <div className="documentButtonBar-followTypes">
+ {followBtn(
+ true,
+ (doc: Doc) => (doc.followAllLinks = !doc.followAllLinks),
+ (doc?: Doc) => (doc?.followAllLinks ? true : false),
+ 'window-maximize'
+ )}
+ </div>
<FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="hand-point-right" />
</div>
</Tooltip>
);
}
- @observable expandPin = false;
+
+ @observable subLink = '';
+ @computed get linkButton() {
+ const targetDoc = this.view0?.props.Document;
+ return !targetDoc || !this.view0 ? null : (
+ <div className="documentButtonBar-icon documentButtonBar-link">
+ <div className="documentButtonBar-linkTypes">
+ <Tooltip title={<div>search for target</div>}>
+ <div className="documentButtonBar-button">
+ <button style={{ backgroundColor: 'transparent', width: 35, height: 35, display: 'flex', justifyContent: 'center', alignItems: 'center', position: 'relative' }} onPointerDown={this.toggleLinkSearch}>
+ <FontAwesomeIcon style={{ position: 'absolute', transform: 'scale(1.5)' }} icon={'search'} size="lg" />
+ <FontAwesomeIcon style={{ position: 'absolute', transform: 'scale(0.5)', transformOrigin: 'center', top: 9, left: 2 }} icon={'link'} size="lg" />
+ </button>
+ </div>
+ </Tooltip>
+ </div>
+ <div style={{ width: 25, height: 25 }}>
+ <DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} StartLink={true} />
+ </div>
+ </div>
+ );
+ }
+
@observable subPin = '';
@computed
get pinButton() {
@@ -253,7 +307,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
.views()
.filter(v => v)
.map(dv => dv!.rootDoc);
- TabDocView.PinDoc(docs, { pinDocLayout, pinDocContent, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null) });
+ TabDocView.PinDoc(docs, { pinAudioPlay: true, pinDocLayout, pinDocContent, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null), currentFrame: Cast(docs.lastElement()?.currentFrame, 'number', null) });
e.stopPropagation();
}}
/>
@@ -264,25 +318,20 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
return !targetDoc ? null : (
<Tooltip title={<div className="dash-tooltip">{`Pin Document ${SelectionManager.Views().length > 1 ? 'multiple documents' : ''} to Trail`}</div>}>
<div
- className="documentButtonBar-icon"
- style={{ color: 'white' }}
- onPointerEnter={action(e => (this.expandPin = true))}
- onPointerLeave={action(e => (this.expandPin = false))}
+ className="documentButtonBar-icon documentButtonBar-pin"
onClick={e => {
const docs = this.props
.views()
.filter(v => v)
.map(dv => dv!.rootDoc);
- TabDocView.PinDoc(docs, { pinDocLayout: e.shiftKey, pinDocContent: e.altKey, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null) });
+ TabDocView.PinDoc(docs, { pinAudioPlay: true, pinDocLayout: e.shiftKey, pinDocContent: e.altKey, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null) });
e.stopPropagation();
}}>
- {this.expandPin ? (
- <div className="documentButtonBar-pinTypes">
- {pinBtn(true, false, 'window-maximize')}
- {pinBtn(false, true, 'address-card')}
- {pinBtn(true, true, 'id-card')}
- </div>
- ) : null}
+ <div className="documentButtonBar-pinTypes">
+ {pinBtn(true, false, 'window-maximize')}
+ {pinBtn(false, true, 'address-card')}
+ {pinBtn(true, true, 'id-card')}
+ </div>
<FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin" />
</div>
</Tooltip>
@@ -293,12 +342,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
get shareButton() {
const targetDoc = this.view0?.props.Document;
return !targetDoc ? null : (
- <Tooltip
- title={
- <>
- <div className="dash-tooltip">{'Open Sharing Manager'}</div>
- </>
- }>
+ <Tooltip title={<div className="dash-tooltip">{'Open Sharing Manager'}</div>}>
<div className="documentButtonBar-icon" style={{ color: 'white' }} onClick={e => SharingManager.Instance.open(this.view0, targetDoc)}>
<FontAwesomeIcon className="documentdecorations-icon" icon="users" />
</div>
@@ -317,34 +361,11 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
</Tooltip>
);
}
-
- @computed
- get moreButton() {
- const targetDoc = this.view0?.props.Document;
- return !targetDoc ? null : (
- <Tooltip
- title={
- <>
- <div className="dash-tooltip">{`${SettingsManager.propertiesWidth > 0 ? 'Close' : 'Open'} Properties Panel`}</div>
- </>
- }>
- <div className="documentButtonBar-icon" style={{ color: 'white', cursor: 'e-resize' }} onClick={action(e => (SettingsManager.propertiesWidth = SettingsManager.propertiesWidth > 0 ? 0 : 250))}>
- <FontAwesomeIcon className="documentdecorations-icon" icon="ellipsis-h" />
- </div>
- </Tooltip>
- );
- }
-
@computed
get metadataButton() {
const view0 = this.view0;
return !view0 ? null : (
- <Tooltip
- title={
- <>
- <div className="dash-tooltip">Show metadata panel</div>
- </>
- }>
+ <Tooltip title={<div className="dash-tooltip">Show metadata panel</div>}>
<div className="documentButtonBar-linkFlyout">
<Flyout
anchorPoint={anchorPoints.LEFT_TOP}
@@ -367,28 +388,30 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
}
@observable _isRecording = false;
+ _stopFunc: () => void = emptyFunction;
@computed
get recordButton() {
const targetDoc = this.view0?.props.Document;
return !targetDoc ? null : (
- <Tooltip title={<div className="dash-tooltip">{'Click to record 5 second annotation'}</div>}>
+ <Tooltip title={<div className="dash-tooltip">Press to record audio annotation</div>}>
<div
className="documentButtonBar-icon"
- style={{ backgroundColor: this._isRecording ? 'red' : targetDoc.isLinkButton ? Colors.LIGHT_BLUE : Colors.DARK_GRAY, color: targetDoc.isLinkButton ? Colors.BLACK : Colors.WHITE }}
- onClick={undoBatch(
- action(e => {
- this._isRecording = true;
- this.props.views().map(
- view =>
- view &&
- DocumentViewInternal.recordAudioAnnotation(
- view.dataDoc,
- view.LayoutFieldKey,
- action(() => (this._isRecording = false))
- )
- );
- })
- )}>
+ style={{ backgroundColor: this._isRecording ? Colors.ERROR_RED : Colors.DARK_GRAY, color: Colors.WHITE }}
+ onPointerDown={action((e: React.PointerEvent) => {
+ this._isRecording = true;
+ this.props.views().map(view => view && DocumentViewInternal.recordAudioAnnotation(view.dataDoc, view.LayoutFieldKey, stopFunc => (this._stopFunc = stopFunc), emptyFunction));
+ const b = UndoManager.StartBatch('Recording');
+ setupMoveUpEvents(
+ this,
+ e,
+ returnFalse,
+ action(() => {
+ this._isRecording = false;
+ this._stopFunc();
+ }),
+ emptyFunction
+ );
+ })}>
<FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="microphone" />
</div>
</Tooltip>
@@ -454,6 +477,12 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
simulateMouseClick(child, e.clientX, e.clientY - 30, e.screenX, e.screenY - 30);
};
+ @observable _showLinkPopup = false;
+ @action
+ toggleLinkSearch = (e: React.PointerEvent) => {
+ this._showLinkPopup = !this._showLinkPopup;
+ e.stopPropagation();
+ };
render() {
if (!this.view0) return null;
@@ -464,25 +493,34 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
return (
<div className="documentButtonBar">
<div className="documentButtonBar-button">
- <DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} StartLink={true} />
+ <DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} ShowCount={true} />
</div>
+ {this._showLinkPopup ? (
+ <div style={{ position: 'absolute', zIndex: 1000 }}>
+ <LinkPopup
+ key="popup"
+ showPopup={this._showLinkPopup}
+ linkCreated={link => (link.linkDisplay = !this.props.views().lastElement()?.rootDoc.isLinkButton)}
+ linkCreateAnchor={() => this.props.views().lastElement()?.ComponentView?.getAnchor?.()}
+ linkFrom={() => this.props.views().lastElement()?.rootDoc}
+ />
+ </div>
+ ) : (
+ <div className="documentButtonBar-button">{this.linkButton}</div>
+ )}
+
{(DocumentLinksButton.StartLink || Doc.UserDoc()['documentLinksButton-fullMenu']) && DocumentLinksButton.StartLink !== doc ? (
<div className="documentButtonBar-button">
<DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} StartLink={false} />
</div>
) : null}
- {Doc.noviceMode ? null : <div className="documentButtonBar-button">{this.recordButton}</div>}
{
Doc.noviceMode ? null : <div className="documentButtonBar-button">{this.templateButton}</div>
- /*<div className="documentButtonBar-button">
- {this.metadataButton}
- </div>
- <div className="documentButtonBar-button">
- {this.contextButton}
- </div> */
+ /*<div className="documentButtonBar-button"> {this.metadataButton} </div> */
}
{!SelectionManager.Views()?.some(v => v.allLinks.length) ? null : <div className="documentButtonBar-button">{this.followLinkButton}</div>}
<div className="documentButtonBar-button">{this.pinButton}</div>
+ <div className="documentButtonBar-button">{this.recordButton}</div>
{!Doc.UserDoc()['documentLinksButton-fullMenu'] ? null : <div className="documentButtonBar-button">{this.shareButton}</div>}
{!Doc.UserDoc()['documentLinksButton-fullMenu'] ? null : (
<div className="documentButtonBar-button" style={{ display: !considerPush ? 'none' : '' }}>
@@ -493,9 +531,6 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
{this.considerGoogleDocsPull}
</div>
<div className="documentButtonBar-button">{this.menuButton}</div>
- {/* {Doc.noviceMode ? (null) : <div className="documentButtonBar-button">
- {this.moreButton}
- </div>} */}
</div>
);
}