diff options
Diffstat (limited to 'src/client/views/DocumentDecorations.tsx')
| -rw-r--r-- | src/client/views/DocumentDecorations.tsx | 117 |
1 files changed, 80 insertions, 37 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 85d36dbf8..9aca8c339 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -2,20 +2,22 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@material-ui/core'; import { IconButton } from 'browndash-components'; -import { action, computed, observable, reaction, runInAction } from 'mobx'; +import { action, computed, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import { FaUndo } from 'react-icons/fa'; import { DateField } from '../../fields/DateField'; -import { AclAdmin, AclEdit, DataSym, Doc, DocListCast, Field, HeightSym, WidthSym } from '../../fields/Doc'; -import { Document } from '../../fields/documentSchemas'; +import { AclAdmin, AclAugment, AclEdit, Doc, DocListCast, Field, HeightSym, WidthSym } from '../../fields/Doc'; import { InkField } from '../../fields/InkField'; +import { RichTextField } from '../../fields/RichTextField'; import { ScriptField } from '../../fields/ScriptField'; import { Cast, NumCast, StrCast } from '../../fields/Types'; import { GetEffectiveAcl } from '../../fields/util'; import { aggregateBounds, emptyFunction, numberValue, returnFalse, setupMoveUpEvents, Utils } from '../../Utils'; import { Docs } from '../documents/Documents'; import { DocumentType } from '../documents/DocumentTypes'; +import { DocumentManager } from '../util/DocumentManager'; import { DragManager } from '../util/DragManager'; +import { LinkFollower } from '../util/LinkFollower'; import { SelectionManager } from '../util/SelectionManager'; import { SnappingManager } from '../util/SnappingManager'; import { undoBatch, UndoManager } from '../util/UndoManager'; @@ -27,15 +29,12 @@ import { Colors } from './global/globalEnums'; import { InkingStroke } from './InkingStroke'; import { InkStrokeProperties } from './InkStrokeProperties'; import { LightboxView } from './LightboxView'; -import { DocumentView, OpenWhere, OpenWhereMod } from './nodes/DocumentView'; +import { DocumentView, OpenWhereMod } from './nodes/DocumentView'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { ImageBox } from './nodes/ImageBox'; import React = require('react'); -import { RichTextField } from '../../fields/RichTextField'; -import { LinkFollower } from '../util/LinkFollower'; import _ = require('lodash'); -import { DocumentManager } from '../util/DocumentManager'; -import { isUndefined } from 'lodash'; +import { SettingsManager } from '../util/SettingsManager'; @observer export class DocumentDecorations extends React.Component<{ PanelWidth: number; PanelHeight: number; boundsLeft: number; boundsTop: number }, { value: string }> { @@ -163,27 +162,35 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P }; @action onContainerDown = (e: React.PointerEvent): void => { - setupMoveUpEvents( - this, - e, - e => this.onBackgroundMove(true, e), - e => {}, - emptyFunction - ); + const first = SelectionManager.Views()[0]; + const effectiveAcl = GetEffectiveAcl(first.rootDoc); + if (effectiveAcl == AclAdmin || effectiveAcl == AclEdit || effectiveAcl == AclAugment) { + setupMoveUpEvents( + this, + e, + e => this.onBackgroundMove(true, e), + e => {}, + emptyFunction + ); + } }; @action onTitleDown = (e: React.PointerEvent): void => { - setupMoveUpEvents( - this, - e, - e => this.onBackgroundMove(true, e), - e => {}, - action(e => { - !this._editingTitle && (this._accumulatedTitle = this._titleControlString.startsWith('#') ? this.selectionTitle : this._titleControlString); - this._editingTitle = true; - this._keyinput.current && setTimeout(this._keyinput.current.focus); - }) - ); + const first = SelectionManager.Views()[0]; + const effectiveAcl = GetEffectiveAcl(first.rootDoc); + if (effectiveAcl == AclAdmin || effectiveAcl == AclEdit || effectiveAcl == AclAugment) { + setupMoveUpEvents( + this, + e, + e => this.onBackgroundMove(true, e), + e => {}, + action(e => { + !this._editingTitle && (this._accumulatedTitle = this._titleControlString.startsWith('#') ? this.selectionTitle : this._titleControlString); + this._editingTitle = true; + this._keyinput.current && setTimeout(this._keyinput.current.focus); + }) + ); + } }; onBackgroundDown = (e: React.PointerEvent) => setupMoveUpEvents(this, e, e => this.onBackgroundMove(false, e), emptyFunction, emptyFunction); @@ -479,6 +486,8 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P onPointerMove = (e: PointerEvent, down: number[], move: number[]): boolean => { const first = SelectionManager.Views()[0]; + const effectiveAcl = GetEffectiveAcl(first.rootDoc); + if (!(effectiveAcl == AclAdmin || effectiveAcl == AclEdit || effectiveAcl == AclAugment)) return false; if (!first) return false; let thisPt = { x: e.clientX - this._offX, y: e.clientY - this._offY }; var fixedAspect = Doc.NativeAspect(first.layoutDoc); @@ -744,6 +753,29 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P setTimeout(action(() => (this._showNothing = true))); return null; } + + // sharing + const docShareMode = Doc.GetProto(seldocview.rootDoc)['acl-Public']; + const shareMode = StrCast(docShareMode); + var shareSymbolIcon = null; + switch (shareMode) { + case 'Edit': + shareSymbolIcon = '⬢ '; + break; + case 'Augment': + shareSymbolIcon = '⬟ '; + break; + case 'View': + shareSymbolIcon = '♦ '; + break; + case 'Not-Shared': + shareSymbolIcon = '▲ '; + break; + default: + shareSymbolIcon = ''; + break; + } + // hide the decorations if the parent chooses to hide it or if the document itself hides it const hideDecorations = seldocview.props.hideDecorations || seldocview.rootDoc.hideDecorations; const hideResizers = hideDecorations || seldocview.props.hideResizeHandles || seldocview.rootDoc.hideResizeHandles || this._isRounding || this._isRotating; @@ -764,10 +796,11 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P seldocview.props.hideDeleteButton || seldocview.rootDoc.hideDeleteButton || SelectionManager.Views().some(docView => { - const collectionAcl = docView.props.docViewPath()?.lastElement() ? GetEffectiveAcl(docView.props.docViewPath().lastElement().rootDoc[DataSym]) : AclEdit; - return docView.rootDoc.stayInCollection || (collectionAcl !== AclAdmin && collectionAcl !== AclEdit && GetEffectiveAcl(docView.rootDoc) !== AclAdmin); + // const collectionAcl = docView.props.docViewPath()?.lastElement() ? GetEffectiveAcl(docView.props.docViewPath().lastElement().rootDoc[DataSym]) : AclEdit; + // return docView.rootDoc.stayInCollection || (collectionAcl !== AclAdmin && collectionAcl !== AclEdit && GetEffectiveAcl(docView.rootDoc) !== AclAdmin); + const effectiveAcl = GetEffectiveAcl(Doc.GetProto(seldocview.rootDoc)); + return docView.rootDoc.stayInCollection || (effectiveAcl !== AclAdmin && GetEffectiveAcl(docView.rootDoc) !== AclAdmin); }); - const topBtn = (key: string, icon: string, pointerDown: undefined | ((e: React.PointerEvent) => void), click: undefined | ((e: any) => void), title: string) => ( <Tooltip key={key} title={<div className="dash-tooltip">{title}</div>} placement="top"> <div @@ -806,7 +839,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P const resizerScheme = colorScheme ? 'documentDecorations-resizer' + colorScheme : ''; // Radius constants - const useRounding = seldocview.ComponentView instanceof ImageBox || seldocview.ComponentView instanceof FormattedTextBox || seldocview.ComponentView instanceof CollectionFreeFormView; + const useRounding = seldocview.ComponentView instanceof ImageBox || seldocview.ComponentView instanceof FormattedTextBox; const borderRadius = numberValue(StrCast(seldocview.rootDoc.borderRounding)); const docMax = Math.min(NumCast(seldocview.rootDoc.width) / 2, NumCast(seldocview.rootDoc.height) / 2); const maxDist = Math.min((this.Bounds.r - this.Bounds.x) / 2, (this.Bounds.b - this.Bounds.y) / 2); @@ -829,15 +862,17 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P ) : ( <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown}> <span className={`documentDecorations-titleSpan${colorScheme}`}>{`${hideTitle ? '' : this.selectionTitle}`}</span> - {!useLock ? null : ( - <Tooltip key="lock" title={<div className="dash-tooltip">toggle ability to interact with document</div>} placement="top"> - <div className="documentDecorations-lock" style={{ color: seldocview.rootDoc._lockedPosition ? 'red' : undefined }} onPointerDown={this.onLockDown} onContextMenu={e => e.preventDefault()}> - <FontAwesomeIcon size="sm" icon="lock" /> - </div> - </Tooltip> - )} </div> ); + const sharingMenu = docShareMode ? ( + <div className='documentDecorations-share' onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, action(() => SettingsManager.propertiesWidth =250))}> + <div className={`documentDecorations-share${shareMode}`}> + <span>{shareSymbolIcon + ' ' + shareMode}</span> + </div> + </div> + ) : ( + <div /> + ); return ( <div className={`documentDecorations${colorScheme}`} style={{ opacity: this._showNothing ? 0.1 : undefined }}> <div @@ -871,6 +906,14 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P {hideDeleteButton ? <div /> : topBtn('close', 'times', undefined, e => this.onCloseClick(true), 'Close')} {hideResizers || hideDeleteButton ? <div /> : topBtn('minimize', 'window-maximize', undefined, e => this.onCloseClick(undefined), 'Minimize')} {hideTitle ? null : titleArea} + {sharingMenu} + {hideOpenButton ? ( + <div /> + ) : seldocview.rootDoc._lockedPosition ? ( + topBtn('lock', 'lock', this.onLockDown, undefined, 'Toggle ability to interact with document') + ) : ( + topBtn('lock', 'unlock', this.onLockDown, undefined, 'Toggle ability to interact with document') + )} {hideOpenButton ? <div /> : topBtn('open', 'external-link-alt', this.onMaximizeDown, undefined, 'Open in Lightbox (ctrl: as alias, shift: in new collection)')} </div> {hideResizers ? null : ( |
