diff options
Diffstat (limited to 'src/client/views/PropertiesView.tsx')
-rw-r--r-- | src/client/views/PropertiesView.tsx | 758 |
1 files changed, 345 insertions, 413 deletions
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 27b9c3c7a..872f1c6ab 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -8,7 +8,7 @@ import { concat } from 'lodash'; import { Lambda, action, computed, observable } 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 * 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'; @@ -51,7 +51,6 @@ interface PropertiesViewProps { addDocTab: (doc: Doc, where: OpenWhere) => boolean; } - @observer export class PropertiesView extends React.Component<PropertiesViewProps> { private _widthUndo?: UndoManager.Batch; @@ -191,7 +190,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { }); rows.push( - <div className="propertiesView-field" key="newKeyValue" style={{ marginTop: '3px', backgroundColor: "white", textAlign: "center" }}> + <div className="propertiesView-field" key="newKeyValue" style={{ marginTop: '3px', backgroundColor: 'white', textAlign: 'center' }}> <EditableView key="editableView" oneLine contents={'add key:value or #tags'} height={13} fontSize={10} GetValue={() => ''} SetValue={this.setKeyValue} /> </div> ); @@ -249,14 +248,12 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { return !this.selectedDoc ? null : <PropertiesDocContextSelector DocView={this.selectedDocumentView} hideTitle={true} addDocTab={this.props.addDocTab} />; } - @computed get contextCount(){ - console.log("in context count"); - if (this.selectedDocumentView){ - const target = (this.selectedDocumentView.props.Document) - const embeddings = DocListCast(target.proto_embeddings) - console.log(embeddings.length -1 ); - return (embeddings.length - 1) - } else{ + @computed get contextCount() { + if (this.selectedDocumentView) { + const target = this.selectedDocumentView.props.Document; + const embeddings = DocListCast(target.proto_embeddings); + return embeddings.length - 1; + } else { return 0; } } @@ -266,13 +263,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { return !selAnchor ? null : <PropertiesDocBacklinksSelector Document={selAnchor} hideTitle={true} addDocTab={this.props.addDocTab} />; } - @computed get linkCount(){ - const selAnchor = this.selectedDocumentView?.anchorViewDoc ?? LinkManager.currentLinkAnchor ?? this.selectedDoc; + @computed get linkCount() { + const selAnchor = this.selectedDocumentView?.anchorViewDoc ?? LinkManager.currentLinkAnchor ?? this.selectedDoc; var counter = 0; - LinkManager.Links(selAnchor).forEach((l, i) => - counter ++ - ); + LinkManager.Links(selAnchor).forEach((l, i) => counter++); return counter; } @@ -356,7 +351,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { return ( <Tooltip title={<div className="dash-tooltip">Notify with message</div>}> <div className="notify-button"> - <FontAwesomeIcon className="notify-button-icon" icon="bell" size="sm" /> + <FontAwesomeIcon className="notify-button-icon" icon="bell" size="sm" /> </div> </Tooltip> ); @@ -367,16 +362,16 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { */ @computed get expansionIcon() { return ( - <div className="expansion-button" > - <IconButton - icon={<FontAwesomeIcon icon={'ellipsis-h'} />} - size={Size.XSMALL} - color={StrCast(Doc.UserDoc().userColor)} + <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); } - })} + })} /> </div> ); @@ -418,7 +413,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div> <div className={'propertiesView-shareDropDown'}> <div className={`propertiesView-shareDropDown${permission}`}> - <div >{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> @@ -450,7 +445,6 @@ 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 @@ -522,7 +516,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <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 className="propertiesView-sharingTable" style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor) }}> {<div> {individualTableEntries}</div>} </div> {groupTableEntries.length > 0 ? ( @@ -530,7 +524,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div> <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 className="propertiesView-sharingTable" style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor) }}> {<div> {groupTableEntries}</div>} </div> </div> @@ -562,68 +556,43 @@ 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 - /> - ); + return <EditableText val={title} setVal={this.setTitle} color={this.color} type={Type.SEC} formLabel={'Title'} fillWidth />; } @computed get currentType() { - // console.log("current type " + this.selectedDoc?.type) - - const documentType = StrCast(this.selectedDoc?.type) - var currentType: string = documentType; - var capitalizedDocType = Utils.cleanDocumentType(currentType as DocumentType); - - return ( - <div> - <div className = "propertiesView-wordType">Type</div> - <div className= "currentType"> - <div className='currentType-icon'> - {this.currentComponent} - </div> - - {capitalizedDocType} - - </div> - - </div> - - ) - } + const documentType = StrCast(this.selectedDoc?.type); + var currentType: string = documentType; + var capitalizedDocType = Utils.cleanDocumentType(currentType as DocumentType); - @computed get currentComponent() { + return ( + <div> + <div className="propertiesView-wordType">Type</div> + <div className="currentType"> + <div className="currentType-icon">{this.currentComponent}</div> - var iconName = StrCast(this.selectedDoc?.systemIcon) + {capitalizedDocType} + </div> + </div> + ); + } - // if (this.selectedDoc?.type === DocumentType.COL){ - // console.log("i did it!") - // } - + @computed get currentComponent() { + var iconName = StrCast(this.selectedDoc?.systemIcon); - if (iconName){ + if (iconName) { const Icon = Icons[iconName as keyof typeof Icons]; return <Icon />; - } else{ - return <Icons.BsFillCollectionFill/> - + } else { + return <Icons.BsFillCollectionFill />; } } @undoBatch @action setTitle = (value: string | number) => { - console.log(value) if (SelectionManager.Views().length > 1) { SelectionManager.Views().map(dv => Doc.SetInPlace(dv.rootDoc, 'title', value, true)); } else if (this.dataDoc) { @@ -687,7 +656,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { className="inking-button-points" style={{ backgroundColor: InkStrokeProperties.Instance._controlButton ? 'black' : '' }} onPointerDown={action(() => (InkStrokeProperties.Instance._controlButton = !InkStrokeProperties.Instance._controlButton))}> - <FontAwesomeIcon icon="bezier-curve" size="lg" /> + <FontAwesomeIcon icon="bezier-curve" size="lg" /> </div> </Tooltip> </div> @@ -706,10 +675,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <input className="inputBox-input" type="text" value={value} onChange={e => setter(e.target.value)} onKeyPress={e => e.stopPropagation()} /> <div className="inputBox-button"> <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons('up', key)))}> - <FontAwesomeIcon icon="caret-up" size="sm" /> + <FontAwesomeIcon icon="caret-up" size="sm" /> </div> <div className="inputbox-Button-down" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons('down', key)))}> - <FontAwesomeIcon icon="caret-down" size="sm" /> + <FontAwesomeIcon icon="caret-down" size="sm" /> </div> </div> </div> @@ -963,10 +932,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <input className="inputBox-input" type="text" value={value} onChange={e => setter(e.target.value)} /> <div className="inputBox-button"> <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons('up', key)))}> - <FontAwesomeIcon icon="caret-up" size="sm" /> + <FontAwesomeIcon icon="caret-up" size="sm" /> </div> <div className="inputbox-Button-down" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons('down', key)))}> - <FontAwesomeIcon icon="caret-down" size="sm" /> + <FontAwesomeIcon icon="caret-down" size="sm" /> </div> </div> </div> @@ -983,7 +952,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { this.openSharing = false; this.openLayout = false; this.openFilters = false; - } + }; @computed get widthAndDash() { return ( @@ -1065,64 +1034,45 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } getNumber = (label: string, unit: string, min: number, max: number, number: number, setNumber: any) => { - return <div> - <NumberInput - formLabel={label} - formLabelPlacement={'left'} - type={Type.SEC} - unit={unit} - fillWidth - color={this.color} - number={number} - setNumber={setNumber} - min={min} - max={max} - /> - <Slider - multithumb={false} - color={this.color} - size={Size.XSMALL} - min={min} - max={max} - unit={unit} - number={number} - setNumber={setNumber} - fillWidth - /> - </div> - } + return ( + <div> + <NumberInput formLabel={label} formLabelPlacement={'left'} type={Type.SEC} unit={unit} fillWidth color={this.color} number={number} setNumber={setNumber} min={min} max={max} /> + <Slider multithumb={false} color={this.color} size={Size.XSMALL} min={min} max={max} unit={unit} number={number} setNumber={setNumber} fillWidth /> + </div> + ); + }; @computed get transformEditor() { return ( <div className="transform-editor"> {this.isInk ? this.controlPointsButton : null} {this.getNumber( - "Height", - " px", + 'Height', + ' px', 0, 1000, Number(this.shapeHgt), undoable((val: string) => !isNaN(Number(val)) && (this.shapeHgt = val), 'set height') )} {this.getNumber( - "Width", - " px", + 'Width', + ' px', 0, 1000, Number(this.shapeWid), undoable((val: string) => !isNaN(Number(val)) && (this.shapeWid = val), 'set width') )} {this.getNumber( - "X Coordinate", - " px", + 'X Coordinate', + ' px', -2000, 2000, Number(this.shapeXps), undoable((val: string) => !isNaN(Number(val)) && (this.shapeXps = val), 'set x coord') )} {this.getNumber( - "Y Coordinate", - " px", + 'Y Coordinate', + ' px', -2000, 2000, Number(this.shapeYps), @@ -1133,38 +1083,44 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } @computed get optionsSubMenu() { - return <PropertiesSection - title="Options" - content={<PropertiesButtons />} - inSection={this.inOptions} - isOpen={this.openOptions} - setInSection={(bool) => this.inOptions = bool} - setIsOpen={(bool) => this.openOptions = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + return ( + <PropertiesSection + title="Options" + content={<PropertiesButtons />} + inSection={this.inOptions} + isOpen={this.openOptions} + setInSection={bool => (this.inOptions = bool)} + setIsOpen={bool => (this.openOptions = bool)} + onDoubleClick={() => this.onDoubleClick()} + /> + ); } @computed get sharingSubMenu() { - return <PropertiesSection - title="Sharing & Permissions" - content={<> - {/* <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></>}> + return ( + <PropertiesSection + title="Sharing & Permissions" + content={ + <> + {/* <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> */} - {this.sharingTable} - </>} - isOpen={this.openSharing} - setIsOpen={(bool) => this.openSharing = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + {/* </div> */} + {this.sharingTable} + </> + } + isOpen={this.openSharing} + setIsOpen={bool => (this.openSharing = bool)} + onDoubleClick={() => this.onDoubleClick()} + /> + ); } /** @@ -1192,15 +1148,19 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { }; @computed get filtersSubMenu() { - return <PropertiesSection - title="Filters" - content={<div className="propertiesView-content filters" style={{ position: 'relative', height: 'auto' }}> - <FilterPanel rootDoc={this.selectedDoc ?? Doc.ActiveDashboard!} /> - </div>} - isOpen={this.openFilters} - setIsOpen={(bool) => this.openFilters = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + return ( + <PropertiesSection + title="Filters" + content={ + <div className="propertiesView-content filters" style={{ position: 'relative', height: 'auto' }}> + <FilterPanel rootDoc={this.selectedDoc ?? Doc.ActiveDashboard!} /> + </div> + } + isOpen={this.openFilters} + setIsOpen={bool => (this.openFilters = bool)} + onDoubleClick={() => this.onDoubleClick()} + /> + ); } @computed get inkSubMenu() { @@ -1208,68 +1168,42 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { return ( <> - <PropertiesSection - title="Appearance" - content={this.isInk ? this.appearanceEditor : null} - isOpen={this.openAppearance} - setIsOpen={(bool) => this.openAppearance = bool} - onDoubleClick={() => this.onDoubleClick()} - /> - <PropertiesSection - title="Transform" - content={this.transformEditor} - isOpen={this.openTransform} - setIsOpen={(bool) => this.openTransform = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + <PropertiesSection title="Appearance" content={this.isInk ? this.appearanceEditor : null} isOpen={this.openAppearance} setIsOpen={bool => (this.openAppearance = bool)} onDoubleClick={() => this.onDoubleClick()} /> + <PropertiesSection title="Transform" content={this.transformEditor} isOpen={this.openTransform} setIsOpen={bool => (this.openTransform = bool)} onDoubleClick={() => this.onDoubleClick()} /> </> ); } @computed get fieldsSubMenu() { - return <PropertiesSection - title="Fields & Tags" - content={<div className="propertiesView-content fields">{ - Doc.noviceMode ? this.noviceFields : this.expandedField} - </div>} - isOpen={this.openFields} - setIsOpen={(bool) => this.openFields = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + return ( + <PropertiesSection + title="Fields & Tags" + content={<div className="propertiesView-content fields">{Doc.noviceMode ? this.noviceFields : this.expandedField}</div>} + isOpen={this.openFields} + setIsOpen={bool => (this.openFields = bool)} + onDoubleClick={() => this.onDoubleClick()} + /> + ); } @computed get contextsSubMenu() { - return <PropertiesSection - title="Other Contexts" - content={this.contextCount > 0 ? this.contexts : "There are no other contexts."} - isOpen={this.openContexts} - setIsOpen={(bool) => this.openContexts = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + return ( + <PropertiesSection + title="Other Contexts" + content={this.contextCount > 0 ? this.contexts : 'There are no other contexts.'} + isOpen={this.openContexts} + setIsOpen={bool => (this.openContexts = bool)} + onDoubleClick={() => this.onDoubleClick()} + /> + ); } - - - - @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() { @@ -1470,224 +1404,226 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { if (scale > 1) scale = 1; this.sourceAnchor && (this.sourceAnchor.followLinkZoomScale = scale); }; - + @computed get linkProperties() { const zoom = Number((NumCast(this.sourceAnchor?.followLinkZoomScale, 1) * 100).toPrecision(3)); const targZoom = this.sourceAnchor?.followLinkZoom; const indent = 30; const hasSelectedAnchor = LinkManager.Links(this.sourceAnchor).includes(LinkManager.currentLink!); - return <> - <div className="propertiesView-section" style={{ background: 'darkgray' }}> - <div className="propertiesView-input first" style={{ display: 'grid', gridTemplateColumns: '84px auto' }}> - <p>Relationship</p> - {this.editRelationship} - </div> - <div className="propertiesView-input" style={{ display: 'grid', gridTemplateColumns: '84px auto' }}> - <p>Description</p> - {this.editDescription} - </div> - <div className="propertiesView-input inline"> - <p>Show link</p> - <button - style={{ background: !LinkManager.currentLink?.link_displayLine ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleLinkProp(e, 'link_displayLine')} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline" style={{ marginLeft: 10 }}> - <p>Auto-move anchors</p> - <button - style={{ background: !LinkManager.currentLink?.link_autoMoveAnchors ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleLinkProp(e, 'link_autoMoveAnchors')} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline" style={{ marginLeft: 10 }}> - <p>Display arrow</p> - <button - style={{ background: !LinkManager.currentLink?.link_displayArrow ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleLinkProp(e, 'link_displayArrow')} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> - </button> - </div> - </div> - {!hasSelectedAnchor ? null : ( - <div className="propertiesView-section"> - <div className="propertiesView-input inline first" style={{ display: 'grid', gridTemplateColumns: '84px calc(100% - 84px)' }}> - <p>Follow by</p> - <select onChange={e => this.changeFollowBehavior(e.currentTarget.value === 'Default' ? undefined : e.currentTarget.value)} value={Cast(this.sourceAnchor?.followLinkLocation, 'string', null)}> - <option value={undefined}>Default</option> - <option value={OpenWhere.addLeft}>Opening in new left pane</option> - <option value={OpenWhere.addRight}>Opening in new right pane</option> - <option value={OpenWhere.replaceLeft}>Replacing left tab</option> - <option value={OpenWhere.replaceRight}>Replacing right tab</option> - <option value={OpenWhere.lightbox}>Opening in lightbox</option> - <option value={OpenWhere.add}>Opening in new tab</option> - <option value={OpenWhere.replace}>Replacing current tab</option> - <option value={OpenWhere.inParent}>Opening in same collection</option> - {LinkManager.currentLink?.linksToAnnotation ? <option value="openExternal">Open in external page</option> : null} - </select> - </div> - <div className="propertiesView-input inline first" style={{ display: 'grid', gridTemplateColumns: '84px calc(100% - 134px) 50px' }}> - <p>Animation</p> - <select style={{ width: '100%', gridColumn: 2 }} onChange={e => this.changeAnimationBehavior(e.currentTarget.value)} value={StrCast(this.sourceAnchor?.followLinkAnimEffect, 'default')}> - <option value="default">Default</option> - {[PresEffect.None, PresEffect.Zoom, PresEffect.Lightspeed, PresEffect.Fade, PresEffect.Flip, PresEffect.Rotate, PresEffect.Bounce, PresEffect.Roll].map(effect => ( - <option key={effect.toString()} value={effect.toString()}> - {effect.toString()} - </option> - ))} - </select> - <div className="effectDirection" style={{ marginLeft: '10px', display: 'grid', width: 40, height: 36, gridColumn: 3, gridTemplateRows: '12px 12px 12px' }}> - {this.animationDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})} - {this.animationDirection(PresEffectDirection.Right, 'angle-left', 3, 2, {})} - {this.animationDirection(PresEffectDirection.Top, 'angle-down', 2, 1, {})} - {this.animationDirection(PresEffectDirection.Bottom, 'angle-up', 2, 3, {})} - {this.animationDirection(PresEffectDirection.Center, '', 2, 2, { width: 10, height: 10, alignSelf: 'center' })} + return ( + <> + <div className="propertiesView-section" style={{ background: 'darkgray' }}> + <div className="propertiesView-input first" style={{ display: 'grid', gridTemplateColumns: '84px auto' }}> + <p>Relationship</p> + {this.editRelationship} + </div> + <div className="propertiesView-input" style={{ display: 'grid', gridTemplateColumns: '84px auto' }}> + <p>Description</p> + {this.editDescription} + </div> + <div className="propertiesView-input inline"> + <p>Show link</p> + <button + style={{ background: !LinkManager.currentLink?.link_displayLine ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleLinkProp(e, 'link_displayLine')} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline" style={{ marginLeft: 10 }}> + <p>Auto-move anchors</p> + <button + style={{ background: !LinkManager.currentLink?.link_autoMoveAnchors ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleLinkProp(e, 'link_autoMoveAnchors')} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline" style={{ marginLeft: 10 }}> + <p>Display arrow</p> + <button + style={{ background: !LinkManager.currentLink?.link_displayArrow ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleLinkProp(e, 'link_displayArrow')} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> + </button> </div> </div> - {PresBox.inputter( - '0.1', - '0.1', - '10', - NumCast(this.sourceAnchor?.followLinkTransitionTime) / 1000, - true, - (val: string) => PresBox.SetTransitionTime(val, (timeInMS: number) => this.sourceAnchor && (this.sourceAnchor.followLinkTransitionTime = timeInMS)), - indent - )}{' '} - <div - className={'slider-headers'} - style={{ - display: 'grid', - justifyContent: 'space-between', - width: `calc(100% - ${indent * 2}px)`, - marginLeft: indent, - marginRight: indent, - gridTemplateColumns: 'auto auto', - borderTop: 'solid', - }}> - <div className="slider-text">Fast</div> - <div className="slider-text">Slow</div> - </div>{' '} - <div className="propertiesView-input inline"> - <p>Play Target Audio</p> - <button - style={{ background: !this.sourceAnchor?.followLinkAudio ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleAnchorProp(e, 'followLinkAudio', this.sourceAnchor)} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline"> - <p>Zoom Text Selections</p> - <button - style={{ background: !this.sourceAnchor?.followLinkZoomText ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoomText', this.sourceAnchor)} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline"> - <p>Toggle Follow to Outer Context</p> - <button - style={{ background: !this.sourceAnchor?.followLinkToOuterContext ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleAnchorProp(e, 'followLinkToOuterContext', this.sourceAnchor)} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faWindowMaximize as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline"> - <p>Toggle Target (Show/Hide)</p> - <button - style={{ background: !this.sourceAnchor?.followLinkToggle ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleAnchorProp(e, 'followLinkToggle', this.sourceAnchor)} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline"> - <p>Ease Transitions</p> - <button - style={{ background: this.sourceAnchor?.followLinkEase === 'linear' ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleAnchorProp(e, 'followLinkEase', this.sourceAnchor, 'ease', 'linear')} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline"> - <p>Capture Offset to Target</p> - <button - style={{ background: this.sourceAnchor?.followLinkXoffset === undefined ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => { - this.toggleAnchorProp(e, 'followLinkXoffset', this.sourceAnchor, NumCast(this.destinationAnchor?.x) - NumCast(this.sourceAnchor?.x), undefined); - this.toggleAnchorProp(e, 'followLinkYoffset', this.sourceAnchor, NumCast(this.destinationAnchor?.y) - NumCast(this.sourceAnchor?.y), undefined); - }} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline"> - <p>Center Target (no zoom)</p> - <button - style={{ background: this.sourceAnchor?.followLinkZoom ? '' : '#4476f7', borderRadius: 3 }} - onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline" style={{ display: 'grid', gridTemplateColumns: '78px calc(100% - 108px) 50px' }}> - <p>Zoom %</p> - <div className="ribbon-property" style={{ display: !targZoom ? 'none' : 'inline-flex' }}> - <input className="presBox-input" style={{ width: '100%' }} readOnly={true} type="number" value={zoom} /> - <div className="ribbon-propertyUpDown" style={{ display: 'flex', flexDirection: 'column' }}> - <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), 0.1))}> - <FontAwesomeIcon icon={'caret-up'} /> + {!hasSelectedAnchor ? null : ( + <div className="propertiesView-section"> + <div className="propertiesView-input inline first" style={{ display: 'grid', gridTemplateColumns: '84px calc(100% - 84px)' }}> + <p>Follow by</p> + <select onChange={e => this.changeFollowBehavior(e.currentTarget.value === 'Default' ? undefined : e.currentTarget.value)} value={Cast(this.sourceAnchor?.followLinkLocation, 'string', null)}> + <option value={undefined}>Default</option> + <option value={OpenWhere.addLeft}>Opening in new left pane</option> + <option value={OpenWhere.addRight}>Opening in new right pane</option> + <option value={OpenWhere.replaceLeft}>Replacing left tab</option> + <option value={OpenWhere.replaceRight}>Replacing right tab</option> + <option value={OpenWhere.lightbox}>Opening in lightbox</option> + <option value={OpenWhere.add}>Opening in new tab</option> + <option value={OpenWhere.replace}>Replacing current tab</option> + <option value={OpenWhere.inParent}>Opening in same collection</option> + {LinkManager.currentLink?.linksToAnnotation ? <option value="openExternal">Open in external page</option> : null} + </select> + </div> + <div className="propertiesView-input inline first" style={{ display: 'grid', gridTemplateColumns: '84px calc(100% - 134px) 50px' }}> + <p>Animation</p> + <select style={{ width: '100%', gridColumn: 2 }} onChange={e => this.changeAnimationBehavior(e.currentTarget.value)} value={StrCast(this.sourceAnchor?.followLinkAnimEffect, 'default')}> + <option value="default">Default</option> + {[PresEffect.None, PresEffect.Zoom, PresEffect.Lightspeed, PresEffect.Fade, PresEffect.Flip, PresEffect.Rotate, PresEffect.Bounce, PresEffect.Roll].map(effect => ( + <option key={effect.toString()} value={effect.toString()}> + {effect.toString()} + </option> + ))} + </select> + <div className="effectDirection" style={{ marginLeft: '10px', display: 'grid', width: 40, height: 36, gridColumn: 3, gridTemplateRows: '12px 12px 12px' }}> + {this.animationDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})} + {this.animationDirection(PresEffectDirection.Right, 'angle-left', 3, 2, {})} + {this.animationDirection(PresEffectDirection.Top, 'angle-down', 2, 1, {})} + {this.animationDirection(PresEffectDirection.Bottom, 'angle-up', 2, 3, {})} + {this.animationDirection(PresEffectDirection.Center, '', 2, 2, { width: 10, height: 10, alignSelf: 'center' })} </div> - <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), -0.1))}> - <FontAwesomeIcon icon={'caret-down'} /> + </div> + {PresBox.inputter( + '0.1', + '0.1', + '10', + NumCast(this.sourceAnchor?.followLinkTransitionTime) / 1000, + true, + (val: string) => PresBox.SetTransitionTime(val, (timeInMS: number) => this.sourceAnchor && (this.sourceAnchor.followLinkTransitionTime = timeInMS)), + indent + )}{' '} + <div + className={'slider-headers'} + style={{ + display: 'grid', + justifyContent: 'space-between', + width: `calc(100% - ${indent * 2}px)`, + marginLeft: indent, + marginRight: indent, + gridTemplateColumns: 'auto auto', + borderTop: 'solid', + }}> + <div className="slider-text">Fast</div> + <div className="slider-text">Slow</div> + </div>{' '} + <div className="propertiesView-input inline"> + <p>Play Target Audio</p> + <button + style={{ background: !this.sourceAnchor?.followLinkAudio ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleAnchorProp(e, 'followLinkAudio', this.sourceAnchor)} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline"> + <p>Zoom Text Selections</p> + <button + style={{ background: !this.sourceAnchor?.followLinkZoomText ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoomText', this.sourceAnchor)} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline"> + <p>Toggle Follow to Outer Context</p> + <button + style={{ background: !this.sourceAnchor?.followLinkToOuterContext ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleAnchorProp(e, 'followLinkToOuterContext', this.sourceAnchor)} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faWindowMaximize as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline"> + <p>Toggle Target (Show/Hide)</p> + <button + style={{ background: !this.sourceAnchor?.followLinkToggle ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleAnchorProp(e, 'followLinkToggle', this.sourceAnchor)} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline"> + <p>Ease Transitions</p> + <button + style={{ background: this.sourceAnchor?.followLinkEase === 'linear' ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleAnchorProp(e, 'followLinkEase', this.sourceAnchor, 'ease', 'linear')} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline"> + <p>Capture Offset to Target</p> + <button + style={{ background: this.sourceAnchor?.followLinkXoffset === undefined ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => { + this.toggleAnchorProp(e, 'followLinkXoffset', this.sourceAnchor, NumCast(this.destinationAnchor?.x) - NumCast(this.sourceAnchor?.x), undefined); + this.toggleAnchorProp(e, 'followLinkYoffset', this.sourceAnchor, NumCast(this.destinationAnchor?.y) - NumCast(this.sourceAnchor?.y), undefined); + }} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline"> + <p>Center Target (no zoom)</p> + <button + style={{ background: this.sourceAnchor?.followLinkZoom ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline" style={{ display: 'grid', gridTemplateColumns: '78px calc(100% - 108px) 50px' }}> + <p>Zoom %</p> + <div className="ribbon-property" style={{ display: !targZoom ? 'none' : 'inline-flex' }}> + <input className="presBox-input" style={{ width: '100%' }} readOnly={true} type="number" value={zoom} /> + <div className="ribbon-propertyUpDown" style={{ display: 'flex', flexDirection: 'column' }}> + <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), 0.1))}> + <FontAwesomeIcon icon={'caret-up'} /> + </div> + <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), -0.1))}> + <FontAwesomeIcon icon={'caret-down'} /> + </div> + </div> </div> + <button + style={{ background: !targZoom || this.sourceAnchor?.followLinkZoomScale === 0 ? '' : '#4476f7', borderRadius: 3, gridColumn: 3 }} + onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> + </button> </div> + {!targZoom ? null : PresBox.inputter('0', '1', '100', zoom, true, this.setZoom, 30)} + <div + className={'slider-headers'} + style={{ + display: !targZoom ? 'none' : 'grid', + justifyContent: 'space-between', + width: `calc(100% - ${indent * 2}px)`, + marginLeft: indent, + marginRight: indent, + gridTemplateColumns: 'auto auto', + borderTop: 'solid', + }}> + <div className="slider-text">0%</div> + <div className="slider-text">100%</div> + </div>{' '} </div> - <button - style={{ background: !targZoom || this.sourceAnchor?.followLinkZoomScale === 0 ? '' : '#4476f7', borderRadius: 3, gridColumn: 3 }} - onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)} - onClick={e => e.stopPropagation()} - className="propertiesButton"> - <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> - </button> - </div> - {!targZoom ? null : PresBox.inputter('0', '1', '100', zoom, true, this.setZoom, 30)} - <div - className={'slider-headers'} - style={{ - display: !targZoom ? 'none' : 'grid', - justifyContent: 'space-between', - width: `calc(100% - ${indent * 2}px)`, - marginLeft: indent, - marginRight: indent, - gridTemplateColumns: 'auto auto', - borderTop: 'solid', - }}> - <div className="slider-text">0%</div> - <div className="slider-text">100%</div> - </div>{' '} - </div> - )} - </> + )} + </> + ); } /** @@ -1723,23 +1659,20 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { width: this.props.width, minWidth: this.props.width, }}> - <div className = "propertiesView-propAndInfoGrouping"> + <div className="propertiesView-propAndInfoGrouping"> <div className="propertiesView-title" style={{ width: this.props.width }}> Properties </div> - <div className = "propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/')}> - <GrCircleInformation/> </div> - + <div className="propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/')}> + <GrCircleInformation />{' '} + </div> </div> - <div className="propertiesView-name">{this.editableTitle}</div> - <div className = "propertiesView-type"> {this.currentType} </div> + <div className="propertiesView-type"> {this.currentType} </div> {this.contextsSubMenu} {this.linksSubMenu} - {!this.selectedDoc || !LinkManager.currentLink || (!hasSelectedAnchor && this.selectedDoc !== LinkManager.currentLink) ? null : ( - this.linkProperties - )} + {!this.selectedDoc || !LinkManager.currentLink || (!hasSelectedAnchor && this.selectedDoc !== LinkManager.currentLink) ? null : this.linkProperties} {this.inkSubMenu} {this.optionsSubMenu} {this.fieldsSubMenu} @@ -1760,7 +1693,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { Presentation </div> <div className="propertiesView-name" style={{ borderBottom: 0 }}> - {this.editableTitle} <div className="propertiesView-presSelected"> <div className="propertiesView-selectedCount">{PresBox.Instance.selectedArray.size} selected</div> @@ -1772,7 +1704,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div className="propertiesView-presTrails-title" onPointerDown={action(() => (this.openPresTransitions = !this.openPresTransitions))} style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}> <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> Transitions <div className="propertiesView-presTrails-title-icon"> - <FontAwesomeIcon icon={this.openPresTransitions ? 'caret-down' : 'caret-right'} size="lg" /> + <FontAwesomeIcon icon={this.openPresTransitions ? 'caret-down' : 'caret-right'} size="lg" /> </div> </div> {this.openPresTransitions ? <div className="propertiesView-presTrails-content">{PresBox.Instance.transitionDropdown}</div> : null} @@ -1786,7 +1718,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}> <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> Visibilty <div className="propertiesView-presTrails-title-icon"> - <FontAwesomeIcon icon={this.openPresVisibilityAndDuration ? 'caret-down' : 'caret-right'} size="lg" /> + <FontAwesomeIcon icon={this.openPresVisibilityAndDuration ? 'caret-down' : 'caret-right'} size="lg" /> </div> </div> {this.openPresVisibilityAndDuration ? <div className="propertiesView-presTrails-content">{PresBox.Instance.visibiltyDurationDropdown}</div> : null} @@ -1797,7 +1729,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div className="propertiesView-presTrails-title" onPointerDown={action(() => (this.openPresProgressivize = !this.openPresProgressivize))} style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}> <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> Progressivize <div className="propertiesView-presTrails-title-icon"> - <FontAwesomeIcon icon={this.openPresProgressivize ? 'caret-down' : 'caret-right'} size="lg" /> + <FontAwesomeIcon icon={this.openPresProgressivize ? 'caret-down' : 'caret-right'} size="lg" /> </div> </div> {this.openPresProgressivize ? <div className="propertiesView-presTrails-content">{PresBox.Instance.progressivizeDropdown}</div> : null} @@ -1808,7 +1740,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div className="propertiesView-presTrails-title" onPointerDown={action(() => (this.openSlideOptions = !this.openSlideOptions))} style={{ backgroundColor: this.openSlideOptions ? 'black' : '' }}> <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={type === DocumentType.AUDIO ? 'file-audio' : 'file-video'} /> {type === DocumentType.AUDIO ? 'Audio Options' : 'Video Options'} <div className="propertiesView-presTrails-title-icon"> - <FontAwesomeIcon icon={this.openSlideOptions ? 'caret-down' : 'caret-right'} size="lg" /> + <FontAwesomeIcon icon={this.openSlideOptions ? 'caret-down' : 'caret-right'} size="lg" /> </div> </div> {this.openSlideOptions ? <div className="propertiesView-presTrails-content">{PresBox.Instance.mediaOptionsDropdown}</div> : null} |