diff options
Diffstat (limited to 'src/client/views/PropertiesView.tsx')
-rw-r--r-- | src/client/views/PropertiesView.tsx | 1729 |
1 files changed, 974 insertions, 755 deletions
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index faab2ed26..aecbc4255 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -1,44 +1,42 @@ -import React = require("react"); +import React = require('react'); +import { IconLookup } from '@fortawesome/fontawesome-svg-core'; import { faAnchor, faArrowRight } from '@fortawesome/free-solid-svg-icons'; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Checkbox, Tooltip } from "@material-ui/core"; -import { intersection } from "lodash"; -import { action, autorun, computed, Lambda, observable } from "mobx"; -import { observer } from "mobx-react"; -import { ColorState, SketchPicker } from "react-color"; -import { AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, AclSelfEdit, AclSym, AclUnset, DataSym, Doc, Field, HeightSym, NumListCast, Opt, StrListCast, WidthSym } from "../../fields/Doc"; -import { Id } from "../../fields/FieldSymbols"; -import { InkField } from "../../fields/InkField"; -import { List } from "../../fields/List"; -import { ComputedField } from "../../fields/ScriptField"; -import { Cast, NumCast, StrCast, DocCast } from "../../fields/Types"; -import { denormalizeEmail, GetEffectiveAcl, SharingPermissions } from "../../fields/util"; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from "../../Utils"; -import { DocumentType } from "../documents/DocumentTypes"; -import { CurrentUserUtils } from "../util/CurrentUserUtils"; -import { DocumentManager } from "../util/DocumentManager"; -import { LinkManager } from "../util/LinkManager"; -import { SelectionManager } from "../util/SelectionManager"; -import { SharingManager } from "../util/SharingManager"; -import { Transform } from "../util/Transform"; -import { undoBatch, UndoManager } from "../util/UndoManager"; -import { CollectionDockingView } from "./collections/CollectionDockingView"; -import { CollectionViewType } from "./collections/CollectionView"; -import { EditableView } from "./EditableView"; -import { InkStrokeProperties } from "./InkStrokeProperties"; -import { DocumentView, StyleProviderFunc } from "./nodes/DocumentView"; -import { KeyValueBox } from "./nodes/KeyValueBox"; -import { PropertiesButtons } from "./PropertiesButtons"; -import { PropertiesDocContextSelector } from "./PropertiesDocContextSelector"; -import "./PropertiesView.scss"; -import { DefaultStyleProvider } from "./StyleProvider"; -import { PresBox } from "./nodes/trails"; -import { IconLookup } from "@fortawesome/fontawesome-svg-core"; -import { PropertiesDocBacklinksSelector } from "./PropertiesDocBacklinksSelector"; -const higflyout = require("@hig/flyout"); +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Checkbox, Tooltip } from '@material-ui/core'; +import { intersection } from 'lodash'; +import { action, autorun, computed, Lambda, observable } from 'mobx'; +import { observer } from 'mobx-react'; +import { ColorState, SketchPicker } from 'react-color'; +import { AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, AclSelfEdit, AclSym, AclUnset, DataSym, Doc, Field, HeightSym, NumListCast, Opt, StrListCast, WidthSym } from '../../fields/Doc'; +import { Id } from '../../fields/FieldSymbols'; +import { InkField } from '../../fields/InkField'; +import { List } from '../../fields/List'; +import { ComputedField } from '../../fields/ScriptField'; +import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types'; +import { denormalizeEmail, GetEffectiveAcl, SharingPermissions } from '../../fields/util'; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../Utils'; +import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; +import { DocumentManager } from '../util/DocumentManager'; +import { LinkManager } from '../util/LinkManager'; +import { SelectionManager } from '../util/SelectionManager'; +import { SharingManager } from '../util/SharingManager'; +import { Transform } from '../util/Transform'; +import { undoBatch, UndoManager } from '../util/UndoManager'; +import { EditableView } from './EditableView'; +import { InkStrokeProperties } from './InkStrokeProperties'; +import { DocumentView, StyleProviderFunc } from './nodes/DocumentView'; +import { FilterBox } from './nodes/FilterBox'; +import { KeyValueBox } from './nodes/KeyValueBox'; +import { PresBox } from './nodes/trails'; +import { PropertiesButtons } from './PropertiesButtons'; +import { PropertiesDocBacklinksSelector } from './PropertiesDocBacklinksSelector'; +import { PropertiesDocContextSelector } from './PropertiesDocContextSelector'; +import './PropertiesView.scss'; +import { DefaultStyleProvider } from './StyleProvider'; +const higflyout = require('@hig/flyout'); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; -const _global = (window /* browser */ || global /* node */) as any; +const _global = (window /* browser */ || global) /* node */ as any; interface PropertiesViewProps { width: number; @@ -51,9 +49,13 @@ interface PropertiesViewProps { export class PropertiesView extends React.Component<PropertiesViewProps> { private _widthUndo?: UndoManager.Batch; - @computed get MAX_EMBED_HEIGHT() { return 200; } + @computed get MAX_EMBED_HEIGHT() { + return 200; + } - @computed get selectedDoc() { return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.rootDoc || CurrentUserUtils.ActiveDashboard; } + @computed get selectedDoc() { + return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.rootDoc || Doc.ActiveDashboard; + } @computed get selectedDocumentView() { if (SelectionManager.Views().length) return SelectionManager.Views()[0]; if (PresBox.Instance?._selectedArray.size) return DocumentManager.Instance.getDocumentView(PresBox.Instance.rootDoc); @@ -65,7 +67,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { @computed get isLink(): boolean { return this.selectedDoc?.type === DocumentType.LINK; } - @computed get dataDoc() { return this.selectedDoc?.[DataSym]; } + @computed get dataDoc() { + return this.selectedDoc?.[DataSym]; + } @observable layoutFields: boolean = false; @@ -107,14 +111,16 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { this.selectedDocListenerDisposer?.(); } - @computed get isInk() { return this.selectedDoc?.type === DocumentType.INK; } + @computed get isInk() { + return this.selectedDoc?.type === DocumentType.INK; + } rtfWidth = () => { return !this.selectedDoc ? 0 : Math.min(this.selectedDoc?.[WidthSym](), this.props.width - 20); - } + }; rtfHeight = () => { return !this.selectedDoc ? 0 : this.rtfWidth() <= this.selectedDoc?.[WidthSym]() ? Math.min(this.selectedDoc?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT; - } + }; @action docWidth = () => { @@ -126,62 +132,74 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } else { return 0; } - } + }; @action docHeight = () => { if (this.selectedDoc && this.dataDoc) { const layoutDoc = this.selectedDoc; - return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, - Doc.NativeAspect(layoutDoc, undefined, true) ? this.docWidth() / Doc.NativeAspect(layoutDoc, undefined, true) : - layoutDoc._fitWidth ? (!Doc.NativeHeight(this.dataDoc) ? NumCast(this.props.height) : - Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc)) / Doc.NativeWidth(layoutDoc) || NumCast(this.props.height))) : - NumCast(layoutDoc._height) || 50)); + return Math.max( + 70, + Math.min( + this.MAX_EMBED_HEIGHT, + Doc.NativeAspect(layoutDoc, undefined, true) + ? this.docWidth() / Doc.NativeAspect(layoutDoc, undefined, true) + : layoutDoc._fitWidth + ? !Doc.NativeHeight(this.dataDoc) + ? NumCast(this.props.height) + : Math.min((this.docWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc))) / Doc.NativeWidth(layoutDoc) || NumCast(this.props.height)) + : NumCast(layoutDoc._height) || 50 + ) + ); } return 0; - } + }; @computed get expandedField() { if (this.dataDoc && this.selectedDoc) { const ids: { [key: string]: string } = {}; - const docs = SelectionManager.Views().length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : - SelectionManager.Views().map(dv => this.layoutFields ? dv.layoutDoc : dv.dataDoc); + const docs = SelectionManager.Views().length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views().map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc)); docs.forEach(doc => Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key))); const rows: JSX.Element[] = []; for (const key of Object.keys(ids).slice().sort()) { const docvals = new Set<any>(); docs.forEach(doc => docvals.add(doc[key])); - const contents = Array.from(docvals.keys()).length > 1 ? "-multiple" : docs[0][key]; - if (key[0] === "#") { - rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "2px" }} key={key}> - <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key}</span> - - </div>); + const contents = Array.from(docvals.keys()).length > 1 ? '-multiple' : docs[0][key]; + if (key[0] === '#') { + rows.push( + <div style={{ display: 'flex', overflowY: 'visible', marginBottom: '2px' }} key={key}> + <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key}</span> + + </div> + ); } else { - const contentElement = <EditableView key="editableView" - contents={contents !== undefined ? Field.toString(contents as Field) : "null"} - height={13} - fontSize={10} - GetValue={() => contents !== undefined ? Field.toString(contents as Field) : "null"} - SetValue={(value: string) => { docs.map(doc => KeyValueBox.SetField(doc, key, value, true)); return true; }} - />; - rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "-1px" }} key={key}> - <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key + ":"}</span> - - {contentElement} - </div>); + const contentElement = ( + <EditableView + key="editableView" + contents={contents !== undefined ? Field.toString(contents as Field) : 'null'} + height={13} + fontSize={10} + GetValue={() => (contents !== undefined ? Field.toString(contents as Field) : 'null')} + SetValue={(value: string) => { + docs.map(doc => KeyValueBox.SetField(doc, key, value, true)); + return true; + }} + /> + ); + rows.push( + <div style={{ display: 'flex', overflowY: 'visible', marginBottom: '-1px' }} key={key}> + <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key + ':'}</span> + + {contentElement} + </div> + ); } } - rows.push(<div className="propertiesView-field" key={"newKeyValue"} style={{ marginTop: "3px" }}> - <EditableView - key="editableView" - oneLine - contents={"add key:value or #tags"} - height={13} - fontSize={10} - GetValue={() => ""} - SetValue={this.setKeyValue} /> - </div>); + rows.push( + <div className="propertiesView-field" key={'newKeyValue'} style={{ marginTop: '3px' }}> + <EditableView key="editableView" oneLine contents={'add key:value or #tags'} height={13} fontSize={10} GetValue={() => ''} SetValue={this.setKeyValue} /> + </div> + ); return rows; } } @@ -192,74 +210,80 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const docs = SelectionManager.Views().length < 2 ? [this.dataDoc] : SelectionManager.Views().map(dv => dv.dataDoc); docs.forEach(doc => Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key))); const rows: JSX.Element[] = []; - const noviceReqFields = ["author", "creationDate", "tags"]; - const noviceLayoutFields = ["_curPage"]; - const noviceKeys = [...Array.from(Object.keys(ids)).filter(key => key[0] === "#" || key.indexOf("lastModified") !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith("acl"))), - ...noviceReqFields, ...noviceLayoutFields]; + const noviceReqFields = ['author', 'creationDate', 'tags']; + const noviceLayoutFields = ['_curPage']; + const noviceKeys = [...Array.from(Object.keys(ids)).filter(key => key[0] === '#' || key.indexOf('lastModified') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('acl'))), ...noviceReqFields, ...noviceLayoutFields]; for (const key of noviceKeys.sort()) { const docvals = new Set<any>(); docs.forEach(doc => docvals.add(doc[key])); - const contents = Array.from(docvals.keys()).length > 1 ? "-multiple" : docs[0][key]; - if (key[0] === "#") { - rows.push(<div className="propertiesView-uneditable-field" key={key}> - <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key}</span> - - </div>); + const contents = Array.from(docvals.keys()).length > 1 ? '-multiple' : docs[0][key]; + if (key[0] === '#') { + rows.push( + <div className="propertiesView-uneditable-field" key={key}> + <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key}</span> + + </div> + ); } else if (contents !== undefined) { const value = Field.toString(contents as Field); - if (noviceReqFields.includes(key) || key.indexOf("lastModified") !== -1) { - rows.push(<div className="propertiesView-uneditable-field" key={key}> - <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key + ": "}</span> - <div style={{ whiteSpace: "nowrap", overflowX: "hidden" }}>{value}</div> - </div>); + if (noviceReqFields.includes(key) || key.indexOf('lastModified') !== -1) { + rows.push( + <div className="propertiesView-uneditable-field" key={key}> + <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key + ': '}</span> + <div style={{ whiteSpace: 'nowrap', overflowX: 'hidden' }}>{value}</div> + </div> + ); } else { - const contentElement = <EditableView key="editableView" - contents={value} - height={13} - fontSize={10} - GetValue={() => contents !== undefined ? Field.toString(contents as Field) : "null"} - SetValue={(value: string) => { docs.map(doc => KeyValueBox.SetField(doc, key, value, true)); return true; }} - />; + const contentElement = ( + <EditableView + key="editableView" + contents={value} + height={13} + fontSize={10} + GetValue={() => (contents !== undefined ? Field.toString(contents as Field) : 'null')} + SetValue={(value: string) => { + docs.map(doc => KeyValueBox.SetField(doc, key, value, true)); + return true; + }} + /> + ); - rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "-1px" }} key={key}> - <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key + ":"}</span> - - {contentElement} - </div>); + rows.push( + <div style={{ display: 'flex', overflowY: 'visible', marginBottom: '-1px' }} key={key}> + <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key + ':'}</span> + + {contentElement} + </div> + ); } } } - rows.push(<div className="propertiesView-field" key={"newKeyValue"} style={{ marginTop: "3px" }}> - <EditableView - key="editableView" - oneLine - contents={"add key:value or #tags"} - height={13} - fontSize={10} - GetValue={() => ""} - SetValue={this.setKeyValue} /> - </div>); + rows.push( + <div className="propertiesView-field" key={'newKeyValue'} style={{ marginTop: '3px' }}> + <EditableView key="editableView" oneLine contents={'add key:value or #tags'} height={13} fontSize={10} GetValue={() => ''} SetValue={this.setKeyValue} /> + </div> + ); return rows; } } @undoBatch setKeyValue = (value: string) => { - const docs = SelectionManager.Views().length < 2 && this.selectedDoc ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views().map(dv => this.layoutFields ? dv.layoutDoc : dv.dataDoc); + const docs = SelectionManager.Views().length < 2 && this.selectedDoc ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views().map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc)); docs.forEach(doc => { - if (value.indexOf(":") !== -1) { + if (value.indexOf(':') !== -1) { const newVal = value[0].toUpperCase() + value.substring(1, value.length); - const splits = newVal.split(":"); + const splits = newVal.split(':'); KeyValueBox.SetField(doc, splits[0], splits[1], true); - const tags = StrCast(doc.tags, ":"); - if (tags.includes(`${splits[0]}:`) && splits[1] === "undefined") { - KeyValueBox.SetField(doc, "tags", `"${tags.replace(splits[0] + ":", "")}"`, true); + const tags = StrCast(doc.tags, ':'); + if (tags.includes(`${splits[0]}:`) && splits[1] === 'undefined') { + KeyValueBox.SetField(doc, 'tags', `"${tags.replace(splits[0] + ':', '')}"`, true); } return true; - } else if (value[0] === "#") { + } else if (value[0] === '#') { const newVal = value + `:'${value}'`; doc[DataSym][value] = value; - const tags = StrCast(doc.tags, ":"); + const tags = StrCast(doc.tags, ':'); if (!tags.includes(`${value}:`)) { doc[DataSym].tags = `${tags + value + ':'}`; } @@ -267,68 +291,72 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } }); return false; - } + }; @observable transform: Transform = Transform.Identity(); getTransform = () => this.transform; propertiesDocViewRef = (ref: HTMLDivElement) => { - const observer = new _global.ResizeObserver(action((entries: any) => { - const cliRect = ref.getBoundingClientRect(); - this.transform = new Transform(-cliRect.x, -cliRect.y, 1); - })); + const observer = new _global.ResizeObserver( + action((entries: any) => { + const cliRect = ref.getBoundingClientRect(); + this.transform = new Transform(-cliRect.x, -cliRect.y, 1); + }) + ); ref && observer.observe(ref); - } + }; @computed get contexts() { - return !this.selectedDoc ? (null) : <PropertiesDocContextSelector DocView={this.selectedDocumentView} hideTitle={true} addDocTab={this.props.addDocTab} />; + return !this.selectedDoc ? null : <PropertiesDocContextSelector DocView={this.selectedDocumentView} hideTitle={true} addDocTab={this.props.addDocTab} />; } @computed get links() { - return !this.selectedDoc ? (null) : <PropertiesDocBacklinksSelector Document={this.selectedDoc} hideTitle={true} addDocTab={this.props.addDocTab} />; + return !this.selectedDoc ? null : <PropertiesDocBacklinksSelector Document={this.selectedDoc} hideTitle={true} addDocTab={this.props.addDocTab} />; } @computed get layoutPreview() { if (SelectionManager.Views().length > 1) { - return "-- multiple selected --"; + return '-- multiple selected --'; } if (this.selectedDoc) { const layoutDoc = Doc.Layout(this.selectedDoc); - const panelHeight = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : this.docHeight; - const panelWidth = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : this.docWidth; - return <div ref={this.propertiesDocViewRef} style={{ pointerEvents: "none", display: "inline-block", height: panelHeight() }} key={this.selectedDoc[Id]}> - <DocumentView - Document={layoutDoc} - DataDoc={this.dataDoc} - renderDepth={1} - fitContentsToBox={returnTrue} - rootSelected={returnFalse} - styleProvider={DefaultStyleProvider} - docViewPath={returnEmptyDoclist} - dontCenter={"y"} - isDocumentActive={returnFalse} - isContentActive={emptyFunction} - NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined} - NativeHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : undefined} - PanelWidth={panelWidth} - PanelHeight={panelHeight} - focus={returnFalse} - ScreenToLocalTransform={this.getTransform} - docFilters={returnEmptyFilter} - docRangeFilters={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - ContainingCollectionDoc={undefined} - ContainingCollectionView={undefined} - addDocument={returnFalse} - moveDocument={undefined} - removeDocument={returnFalse} - whenChildContentsActiveChanged={emptyFunction} - addDocTab={returnFalse} - pinToPres={emptyFunction} - bringToFront={returnFalse} - dontRegisterView={true} - dropAction={undefined} - /> - </div>; + const panelHeight = StrCast(Doc.LayoutField(layoutDoc)).includes('FormattedTextBox') ? this.rtfHeight : this.docHeight; + const panelWidth = StrCast(Doc.LayoutField(layoutDoc)).includes('FormattedTextBox') ? this.rtfWidth : this.docWidth; + return ( + <div ref={this.propertiesDocViewRef} style={{ pointerEvents: 'none', display: 'inline-block', height: panelHeight() }} key={this.selectedDoc[Id]}> + <DocumentView + Document={layoutDoc} + DataDoc={this.dataDoc} + renderDepth={1} + fitContentsToBox={returnTrue} + rootSelected={returnFalse} + styleProvider={DefaultStyleProvider} + docViewPath={returnEmptyDoclist} + dontCenter={'y'} + isDocumentActive={returnFalse} + isContentActive={emptyFunction} + NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined} + NativeHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : undefined} + PanelWidth={panelWidth} + PanelHeight={panelHeight} + focus={returnFalse} + ScreenToLocalTransform={this.getTransform} + docFilters={returnEmptyFilter} + docRangeFilters={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} + ContainingCollectionDoc={undefined} + ContainingCollectionView={undefined} + addDocument={returnFalse} + moveDocument={undefined} + removeDocument={returnFalse} + whenChildContentsActiveChanged={emptyFunction} + addDocTab={returnFalse} + pinToPres={emptyFunction} + bringToFront={returnFalse} + dontRegisterView={true} + dropAction={undefined} + /> + </div> + ); } else { return null; } @@ -339,67 +367,85 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { */ @undoBatch changePermissions = (e: any, user: string) => { - const docs = SelectionManager.Views().length < 2 ? (this.selectedDoc ? [this.selectedDoc]:[]) : SelectionManager.Views().map(docView => docView.props.Document); + const docs = SelectionManager.Views().length < 2 ? (this.selectedDoc ? [this.selectedDoc] : []) : SelectionManager.Views().map(docView => docView.props.Document); SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, docs); - } + }; /** * @returns the options for the permissions dropdown. */ getPermissionsSelect(user: string, permission: string) { const dropdownValues: string[] = Object.values(SharingPermissions); - if (permission === "-multiple-") dropdownValues.unshift(permission); - if (user === "Override") dropdownValues.unshift("None"); - return <select className="permissions-select" - value={permission} - onChange={e => this.changePermissions(e, user)}> - {dropdownValues.filter(permission => - !Doc.noviceMode || ![SharingPermissions.View, SharingPermissions.SelfEdit].includes(permission as any)).map(permission => - <option key={permission} value={permission}> {permission} </option>)} - </select>; + if (permission === '-multiple-') dropdownValues.unshift(permission); + if (user === 'Override') dropdownValues.unshift('None'); + return ( + <select className="permissions-select" value={permission} onChange={e => this.changePermissions(e, user)}> + {dropdownValues + .filter(permission => !Doc.noviceMode || ![SharingPermissions.View, SharingPermissions.SelfEdit].includes(permission as any)) + .map(permission => ( + <option key={permission} value={permission}> + {' '} + {permission}{' '} + </option> + ))} + </select> + ); } /** * @returns the notification icon. On clicking, it should notify someone of a document been shared with them. */ @computed get notifyIcon() { - return <Tooltip title={<div className="dash-tooltip">Notify with message</div>}> - <div className="notify-button"> - <FontAwesomeIcon className="notify-button-icon" icon="bell" color="white" size="sm" /> - </div> - </Tooltip>; + return ( + <Tooltip title={<div className="dash-tooltip">Notify with message</div>}> + <div className="notify-button"> + <FontAwesomeIcon className="notify-button-icon" icon="bell" color="white" size="sm" /> + </div> + </Tooltip> + ); } /** * ... next to the owner that opens the main SharingManager interface on click. */ @computed get expansionIcon() { - return <Tooltip title={<div className="dash-tooltip">{"Show more permissions"}</div>}> - <div className="expansion-button" onPointerDown={() => { - if (this.selectedDocumentView || this.selectedDoc) { - SharingManager.Instance.open(this.selectedDocumentView?.props.Document === this.selectedDoc ? this.selectedDocumentView : undefined, this.selectedDoc); - } - }}> - <FontAwesomeIcon className="expansion-button-icon" icon="ellipsis-h" color="black" size="sm" /> - </div> - </Tooltip>; + return ( + <Tooltip title={<div className="dash-tooltip">{'Show more permissions'}</div>}> + <div + className="expansion-button" + onPointerDown={() => { + if (this.selectedDocumentView || this.selectedDoc) { + SharingManager.Instance.open(this.selectedDocumentView?.props.Document === this.selectedDoc ? this.selectedDocumentView : undefined, this.selectedDoc); + } + }}> + <FontAwesomeIcon className="expansion-button-icon" icon="ellipsis-h" color="black" size="sm" /> + </div> + </Tooltip> + ); } /** * @returns a row of the permissions panel */ sharingItem(name: string, admin: boolean, permission: string, showExpansionIcon?: boolean) { - return <div className="propertiesView-sharingTable-item" key={name + permission} - // style={{ backgroundColor: this.selectedUser === name ? "#bcecfc" : "" }} - // onPointerDown={action(() => this.selectedUser = this.selectedUser === name ? "" : name)} - > - <div className="propertiesView-sharingTable-item-name" style={{ width: name !== "Me" ? "85px" : "80px" }}> {name} </div> - {/* {name !== "Me" ? this.notifyIcon : null} */} - <div className="propertiesView-sharingTable-item-permission"> - {admin && permission !== "Owner" ? this.getPermissionsSelect(name, permission) : permission} - {permission === "Owner" || showExpansionIcon ? this.expansionIcon : null} + return ( + <div + className="propertiesView-sharingTable-item" + key={name + permission} + // style={{ backgroundColor: this.selectedUser === name ? "#bcecfc" : "" }} + // onPointerDown={action(() => this.selectedUser = this.selectedUser === name ? "" : name)} + > + <div className="propertiesView-sharingTable-item-name" style={{ width: name !== 'Me' ? '85px' : '80px' }}> + {' '} + {name}{' '} + </div> + {/* {name !== "Me" ? this.notifyIcon : null} */} + <div className="propertiesView-sharingTable-item-permission"> + {admin && permission !== 'Owner' ? this.getPermissionsSelect(name, permission) : permission} + {permission === 'Owner' || showExpansionIcon ? this.expansionIcon : null} + </div> </div> - </div>; + ); } /** @@ -407,19 +453,18 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { */ @computed get sharingTable() { const AclMap = new Map<symbol, string>([ - [AclUnset, "None"], + [AclUnset, 'None'], [AclPrivate, SharingPermissions.None], [AclReadonly, SharingPermissions.View], [AclAugment, SharingPermissions.Augment], [AclSelfEdit, SharingPermissions.SelfEdit], [AclEdit, SharingPermissions.Edit], - [AclAdmin, SharingPermissions.Admin] + [AclAdmin, SharingPermissions.Admin], ]); // all selected docs - const docs = SelectionManager.Views().length < 2 ? - [this.layoutDocAcls ? this.selectedDoc : this.selectedDoc?.[DataSym]] - : SelectionManager.Views().map(docView => this.layoutDocAcls ? docView.props.Document : docView.props.Document[DataSym]); + const docs = + SelectionManager.Views().length < 2 ? [this.layoutDocAcls ? this.selectedDoc : this.selectedDoc?.[DataSym]] : SelectionManager.Views().map(docView => (this.layoutDocAcls ? docView.props.Document : docView.props.Document[DataSym])); const target = docs[0]; @@ -428,7 +473,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const showAdmin = effectiveAcls.every(acl => acl === AclAdmin); // users in common between all docs - const commonKeys: string[] = intersection(...docs.map(doc => this.layoutDocAcls ? doc?.[AclSym] && Object.keys(doc[AclSym]) : doc?.[DataSym][AclSym] && Object.keys(doc[DataSym][AclSym]))); + const commonKeys: string[] = intersection(...docs.map(doc => (this.layoutDocAcls ? doc?.[AclSym] && Object.keys(doc[AclSym]) : doc?.[DataSym][AclSym] && Object.keys(doc[DataSym][AclSym])))); const tableEntries = []; @@ -436,9 +481,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { if (commonKeys.length) { for (const key of commonKeys) { const name = denormalizeEmail(key.substring(4)); - const uniform = docs.every(doc => this.layoutDocAcls ? doc?.[AclSym]?.[key] === docs[0]?.[AclSym]?.[key] : doc?.[DataSym]?.[AclSym]?.[key] === docs[0]?.[DataSym]?.[AclSym]?.[key]); - if (name !== Doc.CurrentUserEmail && name !== target.author && name !== "Public" && name !== "Override"/* && sidebarUsersDisplayed![name] !== false*/) { - tableEntries.push(this.sharingItem(name, showAdmin, uniform ? AclMap.get(this.layoutDocAcls ? target[AclSym][key] : target[DataSym][AclSym][key])! : "-multiple-")); + const uniform = docs.every(doc => (this.layoutDocAcls ? doc?.[AclSym]?.[key] === docs[0]?.[AclSym]?.[key] : doc?.[DataSym]?.[AclSym]?.[key] === docs[0]?.[DataSym]?.[AclSym]?.[key])); + if (name !== Doc.CurrentUserEmail && name !== target.author && name !== 'Public' && name !== 'Override' /* && sidebarUsersDisplayed![name] !== false*/) { + tableEntries.push(this.sharingItem(name, showAdmin, uniform ? AclMap.get(this.layoutDocAcls ? target[AclSym][key] : target[DataSym][AclSym][key])! : '-multiple-')); } } } @@ -446,62 +491,53 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const ownerSame = Doc.CurrentUserEmail !== target.author && docs.filter(doc => doc).every(doc => doc.author === docs[0].author); // shifts the current user, owner, public to the top of the doc. // tableEntries.unshift(this.sharingItem("Override", showAdmin, docs.filter(doc => doc).every(doc => doc["acl-Override"] === docs[0]["acl-Override"]) ? (AclMap.get(target[AclSym]?.["acl-Override"]) || "None") : "-multiple-")); - tableEntries.unshift(this.sharingItem("Public", showAdmin, docs.filter(doc => doc).every(doc => doc["acl-Public"] === docs[0]["acl-Public"]) ? (AclMap.get(target[AclSym]?.["acl-Public"]) || SharingPermissions.None) : "-multiple-")); - tableEntries.unshift(this.sharingItem("Me", showAdmin, docs.filter(doc => doc).every(doc => doc.author === Doc.CurrentUserEmail) ? "Owner" : effectiveAcls.every(acl => acl === effectiveAcls[0]) ? AclMap.get(effectiveAcls[0])! : "-multiple-", !ownerSame)); - if (ownerSame) tableEntries.unshift(this.sharingItem(StrCast(target.author), showAdmin, "Owner")); + tableEntries.unshift(this.sharingItem('Public', showAdmin, docs.filter(doc => doc).every(doc => doc['acl-Public'] === docs[0]['acl-Public']) ? AclMap.get(target[AclSym]?.['acl-Public']) || SharingPermissions.None : '-multiple-')); + tableEntries.unshift( + this.sharingItem('Me', showAdmin, docs.filter(doc => doc).every(doc => doc.author === Doc.CurrentUserEmail) ? 'Owner' : effectiveAcls.every(acl => acl === effectiveAcls[0]) ? AclMap.get(effectiveAcls[0])! : '-multiple-', !ownerSame) + ); + if (ownerSame) tableEntries.unshift(this.sharingItem(StrCast(target.author), showAdmin, 'Owner')); - return <div className="propertiesView-sharingTable"> - {tableEntries} - </div>; + return <div className="propertiesView-sharingTable">{tableEntries}</div>; } @computed get fieldsCheckbox() { - return <Checkbox - color="primary" - onChange={this.toggleCheckbox} - checked={this.layoutFields} - />; + return <Checkbox color="primary" onChange={this.toggleCheckbox} checked={this.layoutFields} />; } @action toggleCheckbox = () => { this.layoutFields = !this.layoutFields; - } + }; @computed get editableTitle() { const titles = new Set<string>(); SelectionManager.Views().forEach(dv => titles.add(StrCast(dv.rootDoc.title))); - const title = Array.from(titles.keys()).length > 1 ? "--multiple selected--" : StrCast(this.selectedDoc?.title); - return <div className="editable-title"> - <EditableView - key="editableView" - contents={title} - height={25} - fontSize={14} - GetValue={() => title} - SetValue={this.setTitle} /> - </div>; + const title = Array.from(titles.keys()).length > 1 ? '--multiple selected--' : StrCast(this.selectedDoc?.title); + return ( + <div className="editable-title"> + <EditableView key="editableView" contents={title} height={25} fontSize={14} GetValue={() => title} SetValue={this.setTitle} /> + </div> + ); } @undoBatch @action setTitle = (value: string) => { if (SelectionManager.Views().length > 1) { - SelectionManager.Views().map(dv => Doc.SetInPlace(dv.rootDoc, "title", value, true)); + SelectionManager.Views().map(dv => Doc.SetInPlace(dv.rootDoc, 'title', value, true)); return true; } else if (this.dataDoc) { - if (this.selectedDoc) Doc.SetInPlace(this.selectedDoc, "title", value, true); - else KeyValueBox.SetField(this.dataDoc, "title", value, true); + if (this.selectedDoc) Doc.SetInPlace(this.selectedDoc, 'title', value, true); + else KeyValueBox.SetField(this.dataDoc, 'title', value, true); return true; } return false; - } - + }; @undoBatch @action rotate = (angle: number) => { - const _centerPoints: { X: number, Y: number }[] = []; + const _centerPoints: { X: number; Y: number }[] = []; if (this.selectedDoc) { const doc = this.selectedDoc; if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) { @@ -522,7 +558,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { doc.rotation = NumCast(doc.rotation) + angle; const inks = Cast(doc.data, InkField)?.inkData; if (inks) { - const newPoints: { X: number, Y: number }[] = []; + const newPoints: { X: number; Y: number }[] = []; inks.forEach(ink => { const newX = Math.cos(angle) * (ink.X - _centerPoints[index].X) - Math.sin(angle) * (ink.Y - _centerPoints[index].Y) + _centerPoints[index].X; const newY = Math.sin(angle) * (ink.X - _centerPoints[index].X) + Math.cos(angle) * (ink.Y - _centerPoints[index].Y) + _centerPoints[index].Y; @@ -536,117 +572,134 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const right = Math.max(...xs); const bottom = Math.max(...ys); - doc._height = (bottom - top); - doc._width = (right - left); + doc._height = bottom - top; + doc._width = right - left; } index++; } } - } + }; @computed get controlPointsButton() { - return <div className="inking-button"> - <Tooltip title={<div className="dash-tooltip">{"Edit points"}</div>}> - <div className="inking-button-points" - style={{ backgroundColor: InkStrokeProperties.Instance._controlButton ? "black" : "" }} - onPointerDown={action(() => InkStrokeProperties.Instance._controlButton = !InkStrokeProperties.Instance._controlButton)} > - <FontAwesomeIcon icon="bezier-curve" color="white" size="lg" /> - </div> - </Tooltip> - <Tooltip title={<div className="dash-tooltip">{InkStrokeProperties.Instance._lock ? "Unlock ratio" : "Lock ratio"}</div>}> - <div className="inking-button-lock" onPointerDown={action(() => InkStrokeProperties.Instance._lock = !InkStrokeProperties.Instance._lock)} > - <FontAwesomeIcon icon={InkStrokeProperties.Instance._lock ? "lock" : "unlock"} color="white" size="lg" /> - </div> - </Tooltip> - <Tooltip title={<div className="dash-tooltip">{"Rotate 90˚"}</div>}> - <div className="inking-button-rotate" onPointerDown={action(() => this.rotate(Math.PI / 2))}> - <FontAwesomeIcon icon="undo" color="white" size="lg" /> - </div> - </Tooltip> - </div>; + return ( + <div className="inking-button"> + <Tooltip title={<div className="dash-tooltip">{'Edit points'}</div>}> + <div + className="inking-button-points" + style={{ backgroundColor: InkStrokeProperties.Instance._controlButton ? 'black' : '' }} + onPointerDown={action(() => (InkStrokeProperties.Instance._controlButton = !InkStrokeProperties.Instance._controlButton))}> + <FontAwesomeIcon icon="bezier-curve" color="white" size="lg" /> + </div> + </Tooltip> + <Tooltip title={<div className="dash-tooltip">{InkStrokeProperties.Instance._lock ? 'Unlock ratio' : 'Lock ratio'}</div>}> + <div className="inking-button-lock" onPointerDown={action(() => (InkStrokeProperties.Instance._lock = !InkStrokeProperties.Instance._lock))}> + <FontAwesomeIcon icon={InkStrokeProperties.Instance._lock ? 'lock' : 'unlock'} color="white" size="lg" /> + </div> + </Tooltip> + <Tooltip title={<div className="dash-tooltip">{'Rotate 90˚'}</div>}> + <div className="inking-button-rotate" onPointerDown={action(() => this.rotate(Math.PI / 2))}> + <FontAwesomeIcon icon="undo" color="white" size="lg" /> + </div> + </Tooltip> + </div> + ); } inputBox = (key: string, value: any, setter: (val: string) => {}, title: string) => { - return <div className="inputBox" - style={{ - marginRight: title === "X:" ? "19px" : "", - marginLeft: title === "∠:" ? "39px" : "" - }}> - <div className="inputBox-title"> {title} </div> - <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" color="white" size="sm" /> - </div> - <div className="inputbox-Button-down" key="down2" - onPointerDown={undoBatch(action(() => this.upDownButtons("down", key)))} > - <FontAwesomeIcon icon="caret-down" color="white" size="sm" /> + return ( + <div + className="inputBox" + style={{ + marginRight: title === 'X:' ? '19px' : '', + marginLeft: title === '∠:' ? '39px' : '', + }}> + <div className="inputBox-title"> {title} </div> + <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" color="white" size="sm" /> + </div> + <div className="inputbox-Button-down" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons('down', key)))}> + <FontAwesomeIcon icon="caret-down" color="white" size="sm" /> + </div> </div> </div> - </div>; - } + ); + }; inputBoxDuo = (key: string, value: any, setter: (val: string) => {}, title1: string, key2: string, value2: any, setter2: (val: string) => {}, title2: string) => { - return <div className="inputBox-duo"> - {this.inputBox(key, value, setter, title1)} - {title2 === "" ? (null) : this.inputBox(key2, value2, setter2, title2)} - </div>; - } + return ( + <div className="inputBox-duo"> + {this.inputBox(key, value, setter, title1)} + {title2 === '' ? null : this.inputBox(key2, value2, setter2, title2)} + </div> + ); + }; @action upDownButtons = (dirs: string, field: string) => { switch (field) { - case "rot": this.rotate((dirs === "up" ? .1 : -.1)); break; - case "Xps": this.selectedDoc && (this.selectedDoc.x = NumCast(this.selectedDoc?.x) + (dirs === "up" ? 10 : -10)); break; - case "Yps": this.selectedDoc && (this.selectedDoc.y = NumCast(this.selectedDoc?.y) + (dirs === "up" ? 10 : -10)); break; - case "stk": this.selectedDoc && (this.selectedDoc.strokeWidth = NumCast(this.selectedDoc?.strokeWidth) + (dirs === "up" ? .1 : -.1)); break; - case "wid": + case 'rot': + this.rotate(dirs === 'up' ? 0.1 : -0.1); + break; + case 'Xps': + this.selectedDoc && (this.selectedDoc.x = NumCast(this.selectedDoc?.x) + (dirs === 'up' ? 10 : -10)); + break; + case 'Yps': + this.selectedDoc && (this.selectedDoc.y = NumCast(this.selectedDoc?.y) + (dirs === 'up' ? 10 : -10)); + break; + case 'stk': + this.selectedDoc && (this.selectedDoc.strokeWidth = NumCast(this.selectedDoc?.strokeWidth) + (dirs === 'up' ? 0.1 : -0.1)); + break; + case 'wid': const oldWidth = NumCast(this.selectedDoc?._width); const oldHeight = NumCast(this.selectedDoc?._height); const oldX = NumCast(this.selectedDoc?.x); const oldY = NumCast(this.selectedDoc?.y); - this.selectedDoc && (this.selectedDoc._width = oldWidth + (dirs === "up" ? 10 : - 10)); - InkStrokeProperties.Instance._lock && this.selectedDoc && (this.selectedDoc._height = (NumCast(this.selectedDoc?._width) / oldWidth * NumCast(this.selectedDoc?._height))); + this.selectedDoc && (this.selectedDoc._width = oldWidth + (dirs === 'up' ? 10 : -10)); + InkStrokeProperties.Instance._lock && this.selectedDoc && (this.selectedDoc._height = (NumCast(this.selectedDoc?._width) / oldWidth) * NumCast(this.selectedDoc?._height)); const doc = this.selectedDoc; if (doc?.type === DocumentType.INK && doc.x && doc.y && doc._height && doc._width) { const ink = Cast(doc.data, InkField)?.inkData; if (ink) { - const newPoints: { X: number, Y: number }[] = []; + const newPoints: { X: number; Y: number }[] = []; for (var j = 0; j < ink.length; j++) { - // (new x — oldx) + (oldxpoint * newWidt)/oldWidth - const newX = (NumCast(doc.x) - oldX) + (ink[j].X * NumCast(doc._width)) / oldWidth; - const newY = (NumCast(doc.y) - oldY) + (ink[j].Y * NumCast(doc._height)) / oldHeight; + // (new x — oldx) + (oldxpoint * newWidt)/oldWidth + const newX = NumCast(doc.x) - oldX + (ink[j].X * NumCast(doc._width)) / oldWidth; + const newY = NumCast(doc.y) - oldY + (ink[j].Y * NumCast(doc._height)) / oldHeight; newPoints.push({ X: newX, Y: newY }); } doc.data = new InkField(newPoints); } } break; - case "hgt": + case 'hgt': const oWidth = NumCast(this.selectedDoc?._width); const oHeight = NumCast(this.selectedDoc?._height); const oX = NumCast(this.selectedDoc?.x); const oY = NumCast(this.selectedDoc?.y); - this.selectedDoc && (this.selectedDoc._height = oHeight + (dirs === "up" ? 10 : - 10)); - InkStrokeProperties.Instance._lock && this.selectedDoc && (this.selectedDoc._width = (NumCast(this.selectedDoc?._height) / oHeight * NumCast(this.selectedDoc?._width))); + this.selectedDoc && (this.selectedDoc._height = oHeight + (dirs === 'up' ? 10 : -10)); + InkStrokeProperties.Instance._lock && this.selectedDoc && (this.selectedDoc._width = (NumCast(this.selectedDoc?._height) / oHeight) * NumCast(this.selectedDoc?._width)); const docu = this.selectedDoc; if (docu?.type === DocumentType.INK && docu.x && docu.y && docu._height && docu._width) { const ink = Cast(docu.data, InkField)?.inkData; if (ink) { - const newPoints: { X: number, Y: number }[] = []; + const newPoints: { X: number; Y: number }[] = []; for (var j = 0; j < ink.length; j++) { - // (new x — oldx) + (oldxpoint * newWidt)/oldWidth - const newX = (NumCast(docu.x) - oX) + (ink[j].X * NumCast(docu._width)) / oWidth; - const newY = (NumCast(docu.y) - oY) + (ink[j].Y * NumCast(docu._height)) / oHeight; + // (new x — oldx) + (oldxpoint * newWidt)/oldWidth + const newX = NumCast(docu.x) - oX + (ink[j].X * NumCast(docu._width)) / oWidth; + const newY = NumCast(docu.y) - oY + (ink[j].Y * NumCast(docu._height)) / oHeight; newPoints.push({ X: newX, Y: newY }); } docu.data = new InkField(newPoints); @@ -654,7 +707,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } break; } - } + }; getField(key: string) { //if (this.selectedDoc) { @@ -664,14 +717,30 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { // } } - @computed get shapeXps() { return this.getField("x"); } - @computed get shapeYps() { return this.getField("y"); } - @computed get shapeRot() { return this.getField("rotation"); } - @computed get shapeHgt() { return this.getField("_height"); } - @computed get shapeWid() { return this.getField("_width"); } - set shapeXps(value) { this.selectedDoc && (this.selectedDoc.x = Number(value)); } - set shapeYps(value) { this.selectedDoc && (this.selectedDoc.y = Number(value)); } - set shapeRot(value) { this.selectedDoc && (this.selectedDoc.rotation = Number(value)); } + @computed get shapeXps() { + return this.getField('x'); + } + @computed get shapeYps() { + return this.getField('y'); + } + @computed get shapeRot() { + return this.getField('rotation'); + } + @computed get shapeHgt() { + return this.getField('_height'); + } + @computed get shapeWid() { + return this.getField('_width'); + } + set shapeXps(value) { + this.selectedDoc && (this.selectedDoc.x = Number(value)); + } + set shapeYps(value) { + this.selectedDoc && (this.selectedDoc.y = Number(value)); + } + set shapeRot(value) { + this.selectedDoc && (this.selectedDoc.rotation = Number(value)); + } set shapeWid(value) { const oldWidth = NumCast(this.selectedDoc?._width); this.selectedDoc && (this.selectedDoc._width = Number(value)); @@ -683,38 +752,122 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { InkStrokeProperties.Instance._lock && this.selectedDoc && (this.selectedDoc._width = (NumCast(this.selectedDoc?._height) * NumCast(this.selectedDoc?._width)) / oldHeight); } - @computed get hgtInput() { return this.inputBoxDuo("hgt", this.shapeHgt, (val: string) => { if (!isNaN(Number(val))) { this.shapeHgt = val; } return true; }, "H:", "wid", this.shapeWid, (val: string) => { if (!isNaN(Number(val))) { this.shapeWid = val; } return true; }, "W:"); } - @computed get XpsInput() { return this.inputBoxDuo("Xps", this.shapeXps, (val: string) => { if (val !== "0" && !isNaN(Number(val))) { this.shapeXps = val; } return true; }, "X:", "Yps", this.shapeYps, (val: string) => { if (val !== "0" && !isNaN(Number(val))) { this.shapeYps = val; } return true; }, "Y:"); } - @computed get rotInput() { return this.inputBoxDuo("rot", this.shapeRot, (val: string) => { if (!isNaN(Number(val))) { this.rotate(Number(val) - Number(this.shapeRot)); this.shapeRot = val; } return true; }, "∠:", "rot", this.shapeRot, (val: string) => { if (!isNaN(Number(val))) { this.rotate(Number(val) - Number(this.shapeRot)); this.shapeRot = val; } return true; }, ""); } - + @computed get hgtInput() { + return this.inputBoxDuo( + 'hgt', + this.shapeHgt, + (val: string) => { + if (!isNaN(Number(val))) { + this.shapeHgt = val; + } + return true; + }, + 'H:', + 'wid', + this.shapeWid, + (val: string) => { + if (!isNaN(Number(val))) { + this.shapeWid = val; + } + return true; + }, + 'W:' + ); + } + @computed get XpsInput() { + return this.inputBoxDuo( + 'Xps', + this.shapeXps, + (val: string) => { + if (val !== '0' && !isNaN(Number(val))) { + this.shapeXps = val; + } + return true; + }, + 'X:', + 'Yps', + this.shapeYps, + (val: string) => { + if (val !== '0' && !isNaN(Number(val))) { + this.shapeYps = val; + } + return true; + }, + 'Y:' + ); + } + @computed get rotInput() { + return this.inputBoxDuo( + 'rot', + this.shapeRot, + (val: string) => { + if (!isNaN(Number(val))) { + this.rotate(Number(val) - Number(this.shapeRot)); + this.shapeRot = val; + } + return true; + }, + '∠:', + 'rot', + this.shapeRot, + (val: string) => { + if (!isNaN(Number(val))) { + this.rotate(Number(val) - Number(this.shapeRot)); + this.shapeRot = val; + } + return true; + }, + '' + ); + } @observable private _fillBtn = false; @observable private _lineBtn = false; - private _lastFill = "#D0021B"; - private _lastLine = "#D0021B"; - private _lastDash: any = "2"; + private _lastFill = '#D0021B'; + private _lastLine = '#D0021B'; + private _lastDash: any = '2'; - @computed get colorFil() { const ccol = this.getField("fillColor") || ""; ccol && (this._lastFill = ccol); return ccol; } - @computed get colorStk() { const ccol = this.getField("color") || ""; ccol && (this._lastLine = ccol); return ccol; } - set colorFil(value) { value && (this._lastFill = value); this.selectedDoc && (this.selectedDoc.fillColor = value ? value : undefined); } - set colorStk(value) { value && (this._lastLine = value); this.selectedDoc && (this.selectedDoc.color = value ? value : undefined); } + @computed get colorFil() { + const ccol = this.getField('fillColor') || ''; + ccol && (this._lastFill = ccol); + return ccol; + } + @computed get colorStk() { + const ccol = this.getField('color') || ''; + ccol && (this._lastLine = ccol); + return ccol; + } + set colorFil(value) { + value && (this._lastFill = value); + this.selectedDoc && (this.selectedDoc.fillColor = value ? value : undefined); + } + set colorStk(value) { + value && (this._lastLine = value); + this.selectedDoc && (this.selectedDoc.color = value ? value : undefined); + } colorButton(value: string, type: string, setter: () => {}) { // return <div className="properties-flyout" onPointerEnter={e => this.changeScrolling(false)} // onPointerLeave={e => this.changeScrolling(true)}> // <Flyout anchorPoint={anchorPoints.LEFT_TOP} // content={type === "fill" ? this.fillPicker : this.linePicker}> - return <div className="color-button" key="color" onPointerDown={undoBatch(action(e => setter()))}> - <div className="color-button-preview" style={{ - backgroundColor: value ?? "121212", width: 15, height: 15, - display: value === "" || value === "transparent" ? "none" : "" - }} /> - {value === "" || value === "transparent" ? <p style={{ fontSize: 25, color: "red", marginTop: -14 }}>☒</p> : ""} - </div>; + return ( + <div className="color-button" key="color" onPointerDown={undoBatch(action(e => setter()))}> + <div + className="color-button-preview" + style={{ + backgroundColor: value ?? '121212', + width: 15, + height: 15, + display: value === '' || value === 'transparent' ? 'none' : '', + }} + /> + {value === '' || value === 'transparent' ? <p style={{ fontSize: 25, color: 'red', marginTop: -14 }}>☒</p> : ''} + </div> + ); // </Flyout> // </div>; - } @undoBatch @@ -723,206 +876,271 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const val = String(color.hex); this.colorStk = val; return true; - } + }; @undoBatch @action switchFil = (color: ColorState) => { const val = String(color.hex); this.colorFil = val; return true; - } + }; colorPicker(setter: (color: string) => {}, type: string) { - return <SketchPicker onChange={type === "stk" ? this.switchStk : this.switchFil} - presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', - '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', - '#FFFFFF', '#f1efeb', 'transparent']} - color={type === "stk" ? this.colorStk : this.colorFil} />; + return ( + <SketchPicker + onChange={type === 'stk' ? this.switchStk : this.switchFil} + presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']} + color={type === 'stk' ? this.colorStk : this.colorFil} + /> + ); + } + + @computed get fillButton() { + return this.colorButton(this.colorFil, 'fill', () => { + this._fillBtn = !this._fillBtn; + this._lineBtn = false; + return true; + }); + } + @computed get lineButton() { + return this.colorButton(this.colorStk, 'line', () => { + this._lineBtn = !this._lineBtn; + this._fillBtn = false; + return true; + }); } - @computed get fillButton() { return this.colorButton(this.colorFil, "fill", () => { this._fillBtn = !this._fillBtn; this._lineBtn = false; return true; }); } - @computed get lineButton() { return this.colorButton(this.colorStk, "line", () => { this._lineBtn = !this._lineBtn; this._fillBtn = false; return true; }); } - - @computed get fillPicker() { return this.colorPicker((color: string) => this.colorFil = color, "fil"); } - @computed get linePicker() { return this.colorPicker((color: string) => this.colorStk = color, "stk"); } + @computed get fillPicker() { + return this.colorPicker((color: string) => (this.colorFil = color), 'fil'); + } + @computed get linePicker() { + return this.colorPicker((color: string) => (this.colorStk = color), 'stk'); + } @computed get strokeAndFill() { - return <div> - <div key="fill" className="strokeAndFill"> - <div className="fill"> - <div className="fill-title">Fill:</div> - <div className="fill-button">{this.fillButton}</div> - </div> - <div className="stroke"> - <div className="stroke-title"> Stroke: </div> - <div className="stroke-button">{this.lineButton}</div> + return ( + <div> + <div key="fill" className="strokeAndFill"> + <div className="fill"> + <div className="fill-title">Fill:</div> + <div className="fill-button">{this.fillButton}</div> + </div> + <div className="stroke"> + <div className="stroke-title"> Stroke: </div> + <div className="stroke-button">{this.lineButton}</div> + </div> </div> + {this._fillBtn ? this.fillPicker : ''} + {this._lineBtn ? this.linePicker : ''} </div> - {this._fillBtn ? this.fillPicker : ""} - {this._lineBtn ? this.linePicker : ""} - </div>; - } - - @computed get solidStk() { return this.selectedDoc?.color && (!this.selectedDoc?.strokeDash || this.selectedDoc?.strokeDash === "0") ? true : false; } - @computed get dashdStk() { return this.selectedDoc?.strokeDash || ""; } - @computed get unStrokd() { return this.selectedDoc?.color ? true : false; } - @computed get widthStk() { return this.getField("strokeWidth") || "1"; } - @computed get markScal() { return Number(this.getField("strokeMakerScale") || "1"); } - @computed get markHead() { return this.getField("strokeStartMarker") || ""; } - @computed get markTail() { return this.getField("strokeEndMarker") || ""; } - set solidStk(value) { this.dashdStk = ""; this.unStrokd = !value; } + ); + } + + @computed get solidStk() { + return this.selectedDoc?.color && (!this.selectedDoc?.strokeDash || this.selectedDoc?.strokeDash === '0') ? true : false; + } + @computed get dashdStk() { + return this.selectedDoc?.strokeDash || ''; + } + @computed get unStrokd() { + return this.selectedDoc?.color ? true : false; + } + @computed get widthStk() { + return this.getField('strokeWidth') || '1'; + } + @computed get markScal() { + return Number(this.getField('strokeMakerScale') || '1'); + } + @computed get markHead() { + return this.getField('strokeStartMarker') || ''; + } + @computed get markTail() { + return this.getField('strokeEndMarker') || ''; + } + set solidStk(value) { + this.dashdStk = ''; + this.unStrokd = !value; + } set dashdStk(value) { value && (this._lastDash = value) && (this.unStrokd = false); this.selectedDoc && (this.selectedDoc.strokeDash = value ? this._lastDash : undefined); } - set markScal(value) { this.selectedDoc && (this.selectedDoc.strokeMarkerScale = Number(value)); } - set widthStk(value) { this.selectedDoc && (this.selectedDoc.strokeWidth = Number(value)); } - set unStrokd(value) { this.colorStk = value ? "" : this._lastLine; } - set markHead(value) { this.selectedDoc && (this.selectedDoc.strokeStartMarker = value); } - set markTail(value) { this.selectedDoc && (this.selectedDoc.strokeEndMarker = value); } - - - @computed get stkInput() { return this.regInput("stk", this.widthStk, (val: string) => this.widthStk = val); } - @computed get markScaleInput() { return this.regInput("scale", this.markScal.toString(), (val: string) => this.markScal = Number(val)); } + set markScal(value) { + this.selectedDoc && (this.selectedDoc.strokeMarkerScale = Number(value)); + } + set widthStk(value) { + this.selectedDoc && (this.selectedDoc.strokeWidth = Number(value)); + } + set unStrokd(value) { + this.colorStk = value ? '' : this._lastLine; + } + set markHead(value) { + this.selectedDoc && (this.selectedDoc.strokeStartMarker = value); + } + set markTail(value) { + this.selectedDoc && (this.selectedDoc.strokeEndMarker = value); + } + @computed get stkInput() { + return this.regInput('stk', this.widthStk, (val: string) => (this.widthStk = val)); + } + @computed get markScaleInput() { + return this.regInput('scale', this.markScal.toString(), (val: string) => (this.markScal = Number(val))); + } regInput = (key: string, value: any, setter: (val: string) => {}) => { - return <div className="inputBox"> - <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" color="white" size="sm" /> - </div> - <div className="inputbox-Button-down" key="down2" - onPointerDown={undoBatch(action(() => this.upDownButtons("down", key)))} > - <FontAwesomeIcon icon="caret-down" color="white" size="sm" /> + return ( + <div className="inputBox"> + <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" color="white" size="sm" /> + </div> + <div className="inputbox-Button-down" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons('down', key)))}> + <FontAwesomeIcon icon="caret-down" color="white" size="sm" /> + </div> </div> </div> - </div>; - } + ); + }; @computed get widthAndDash() { - return <div className="widthAndDash"> - <div className="width"> - <div className="width-top"> - <div className="width-title">Width:</div> - <div className="width-input">{this.stkInput}</div> - </div> - <input className="width-range" type="range" - defaultValue={Number(this.widthStk)} min={1} max={100} - onChange={(action((e) => this.widthStk = e.target.value))} - onMouseDown={(e) => { this._widthUndo = UndoManager.StartBatch("width undo"); }} - onMouseUp={(e) => { this._widthUndo?.end(); this._widthUndo = undefined; }} - /> - </div> - - <div className="arrows"> - <div className="arrows-head"> + return ( + <div className="widthAndDash"> + <div className="width"> <div className="width-top"> - <div className="width-title">Arrow Scale:</div> - {/* <div className="width-input">{this.markScalInput}</div> */} + <div className="width-title">Width:</div> + <div className="width-input">{this.stkInput}</div> </div> - <input className="width-range" type="range" - defaultValue={this.markScal} min={0} max={10} - onChange={(action(e => this.markScal = +e.target.value))} - onMouseDown={(e) => { this._widthUndo = UndoManager.StartBatch("scale undo"); }} - onMouseUp={(e) => { this._widthUndo?.end(); this._widthUndo = undefined; }} + <input + className="width-range" + type="range" + defaultValue={Number(this.widthStk)} + min={1} + max={100} + onChange={action(e => (this.widthStk = e.target.value))} + onMouseDown={e => { + this._widthUndo = UndoManager.StartBatch('width undo'); + }} + onMouseUp={e => { + this._widthUndo?.end(); + this._widthUndo = undefined; + }} /> </div> - <div className="arrows-head"> - <div className="arrows-head-title" >Arrow Head: </div> - <input key="markHead" className="arrows-head-input" type="checkbox" - checked={this.markHead !== ""} - onChange={undoBatch(action(() => this.markHead = this.markHead ? "" : "arrow"))} /> + + <div className="arrows"> + <div className="arrows-head"> + <div className="width-top"> + <div className="width-title">Arrow Scale:</div> + {/* <div className="width-input">{this.markScalInput}</div> */} + </div> + <input + className="width-range" + type="range" + defaultValue={this.markScal} + min={0} + max={10} + onChange={action(e => (this.markScal = +e.target.value))} + onMouseDown={e => { + this._widthUndo = UndoManager.StartBatch('scale undo'); + }} + onMouseUp={e => { + this._widthUndo?.end(); + this._widthUndo = undefined; + }} + /> + </div> + <div className="arrows-head"> + <div className="arrows-head-title">Arrow Head: </div> + <input key="markHead" className="arrows-head-input" type="checkbox" checked={this.markHead !== ''} onChange={undoBatch(action(() => (this.markHead = this.markHead ? '' : 'arrow')))} /> + </div> + <div className="arrows-tail"> + <div className="arrows-tail-title">Arrow End: </div> + <input key="markTail" className="arrows-tail-input" type="checkbox" checked={this.markTail !== ''} onChange={undoBatch(action(() => (this.markTail = this.markTail ? '' : 'arrow')))} /> + </div> </div> - <div className="arrows-tail"> - <div className="arrows-tail-title" >Arrow End: </div> - <input key="markTail" className="arrows-tail-input" type="checkbox" - checked={this.markTail !== ""} - onChange={undoBatch(action(() => this.markTail = this.markTail ? "" : "arrow"))} /> + <div className="dashed"> + <div className="dashed-title">Dashed Line:</div> + <input key="markHead" className="dashed-input" type="checkbox" checked={this.dashdStk === '2'} onChange={this.changeDash} /> </div> </div> - <div className="dashed"> - <div className="dashed-title">Dashed Line:</div> - <input key="markHead" className="dashed-input" - type="checkbox" checked={this.dashdStk === "2"} - onChange={this.changeDash} /> - </div> - </div>; + ); } - @undoBatch @action + @undoBatch + @action changeDash = () => { - this.dashdStk = this.dashdStk === "2" ? "0" : "2"; - } + this.dashdStk = this.dashdStk === '2' ? '0' : '2'; + }; @computed get appearanceEditor() { - return <div className="appearance-editor"> - {this.widthAndDash} - {this.strokeAndFill} - </div>; + return ( + <div className="appearance-editor"> + {this.widthAndDash} + {this.strokeAndFill} + </div> + ); } @computed get transformEditor() { - return <div className="transform-editor"> - {this.controlPointsButton} - {this.hgtInput} - {this.XpsInput} - {this.rotInput} - </div>; + return ( + <div className="transform-editor"> + {this.controlPointsButton} + {this.hgtInput} + {this.XpsInput} + {this.rotInput} + </div> + ); } @computed get optionsSubMenu() { - return <div className="propertiesView-settings" onPointerEnter={action(() => this.inOptions = true)} - onPointerLeave={action(() => this.inOptions = false)}> - <div className="propertiesView-settings-title" - onPointerDown={action(() => this.openOptions = !this.openOptions)} - style={{ backgroundColor: this.openOptions ? "black" : "" }}> - Options - <div className="propertiesView-settings-title-icon"> - <FontAwesomeIcon icon={this.openOptions ? "caret-down" : "caret-right"} size="lg" color="white" /> + return ( + <div className="propertiesView-settings" onPointerEnter={action(() => (this.inOptions = true))} onPointerLeave={action(() => (this.inOptions = false))}> + <div className="propertiesView-settings-title" onPointerDown={action(() => (this.openOptions = !this.openOptions))} style={{ backgroundColor: this.openOptions ? 'black' : '' }}> + Options + <div className="propertiesView-settings-title-icon"> + <FontAwesomeIcon icon={this.openOptions ? 'caret-down' : 'caret-right'} size="lg" color="white" /> + </div> </div> + {!this.openOptions ? null : ( + <div className="propertiesView-settings-content"> + <PropertiesButtons /> + </div> + )} </div> - {!this.openOptions ? (null) : - <div className="propertiesView-settings-content"> - <PropertiesButtons /> - </div>} - </div>; + ); } @computed get sharingSubMenu() { - return <div className="propertiesView-sharing"> - <div className="propertiesView-sharing-title" - onPointerDown={action(() => this.openSharing = !this.openSharing)} - style={{ backgroundColor: this.openSharing ? "black" : "" }}> - Sharing {"&"} Permissions - <div className="propertiesView-sharing-title-icon"> - <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" /> + return ( + <div className="propertiesView-sharing"> + <div className="propertiesView-sharing-title" onPointerDown={action(() => (this.openSharing = !this.openSharing))} style={{ backgroundColor: this.openSharing ? 'black' : '' }}> + Sharing {'&'} Permissions + <div className="propertiesView-sharing-title-icon"> + <FontAwesomeIcon icon={this.openSharing ? 'caret-down' : 'caret-right'} size="lg" color="white" /> + </div> </div> - </div> - {!this.openSharing ? (null) : - <div className="propertiesView-sharing-content"> - <div className="propertiesView-buttonContainer"> - {!Doc.noviceMode ? (<div className="propertiesView-acls-checkbox"> - <Checkbox - color="primary" - onChange={action(() => this.layoutDocAcls = !this.layoutDocAcls)} - checked={this.layoutDocAcls} - /> - <div className="propertiesView-acls-checkbox-text">Layout</div> - </div>) : (null)} - {/* <Tooltip title={<><div className="dash-tooltip">{"Re-distribute sharing settings"}</div></>}> + {!this.openSharing ? null : ( + <div className="propertiesView-sharing-content"> + <div className="propertiesView-buttonContainer"> + {!Doc.noviceMode ? ( + <div className="propertiesView-acls-checkbox"> + <Checkbox color="primary" onChange={action(() => (this.layoutDocAcls = !this.layoutDocAcls))} checked={this.layoutDocAcls} /> + <div className="propertiesView-acls-checkbox-text">Layout</div> + </div> + ) : null} + {/* <Tooltip title={<><div className="dash-tooltip">{"Re-distribute sharing settings"}</div></>}> <button onPointerDown={() => SharingManager.Instance.distributeOverCollection(this.selectedDoc!)}> <FontAwesomeIcon icon="redo-alt" color="white" size="1x" /> </button> </Tooltip> */} + </div> + {this.sharingTable} </div> - {this.sharingTable} - </div>} - </div>; + )} + </div> + ); } /** @@ -930,11 +1148,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { * If it doesn't exist, it creates it. */ checkFilterDoc() { - if (!this.selectedDoc?.currentFilter) this.selectedDoc!.currentFilter = CurrentUserUtils.createFilterDoc(); + if (!this.selectedDoc?.currentFilter) this.selectedDoc!.currentFilter = FilterBox.createFilterDoc(); } /** - * Creates a new currentFilter for this.filterDoc, + * Creates a new currentFilter for this.filterDoc, */ createNewFilterDoc = () => { if (this.selectedDoc) { @@ -944,9 +1162,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { this.selectedDoc._docRangeFilters = new List<string>(); (this.selectedDoc.currentFilter as Doc)._docFiltersList = currentDocFilters; (this.selectedDoc.currentFilter as Doc)._docRangeFiltersList = currentDocRangeFilters; - this.selectedDoc.currentFilter = CurrentUserUtils.createFilterDoc(); + this.selectedDoc.currentFilter = FilterBox.createFilterDoc(); } - } + }; /** * Updates this.filterDoc's currentFilter and saves the docFilters on the currentFilter @@ -970,20 +1188,18 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { doc._docRangeFiltersList = new List<string>(); this.selectedDoc._docRangeFilters = savedDocRangeFilters; } - } + }; @computed get filtersSubMenu() { - return !(this.selectedDoc?.currentFilter instanceof Doc) ? (null) : <div className="propertiesView-filters"> - <div className="propertiesView-filters-title" - onPointerDown={action(() => this.openFilters = !this.openFilters)} - style={{ backgroundColor: this.openFilters ? "black" : "" }}> - Filters - <div className="propertiesView-filters-title-icon"> - <FontAwesomeIcon icon={this.openFilters ? "caret-down" : "caret-right"} size="lg" color="white" /> + return !(this.selectedDoc?.currentFilter instanceof Doc) ? null : ( + <div className="propertiesView-filters"> + <div className="propertiesView-filters-title" onPointerDown={action(() => (this.openFilters = !this.openFilters))} style={{ backgroundColor: this.openFilters ? 'black' : '' }}> + Filters + <div className="propertiesView-filters-title-icon"> + <FontAwesomeIcon icon={this.openFilters ? 'caret-down' : 'caret-right'} size="lg" color="white" /> + </div> </div> - </div> - { - !this.openFilters ? (null) : + {!this.openFilters ? null : ( <div className="propertiesView-filters-content" style={{ height: this.selectedDoc.currentFilter[HeightSym]() + 15 }}> <DocumentView Document={this.selectedDoc.currentFilter} @@ -1014,110 +1230,106 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { dontCenter="y" /> </div> - } - </div >; + )} + </div> + ); } @computed get inkSubMenu() { - return <> - {!this.isInk ? (null) : - <div className="propertiesView-appearance"> - <div className="propertiesView-appearance-title" - onPointerDown={action(() => this.openAppearance = !this.openAppearance)} - style={{ backgroundColor: this.openAppearance ? "black" : "" }}> - Appearance - <div className="propertiesView-appearance-title-icon"> - <FontAwesomeIcon icon={this.openAppearance ? "caret-down" : "caret-right"} size="lg" color="white" /> + return ( + <> + {!this.isInk ? null : ( + <div className="propertiesView-appearance"> + <div className="propertiesView-appearance-title" onPointerDown={action(() => (this.openAppearance = !this.openAppearance))} style={{ backgroundColor: this.openAppearance ? 'black' : '' }}> + Appearance + <div className="propertiesView-appearance-title-icon"> + <FontAwesomeIcon icon={this.openAppearance ? 'caret-down' : 'caret-right'} size="lg" color="white" /> + </div> </div> + {!this.openAppearance ? null : <div className="propertiesView-appearance-content">{this.appearanceEditor}</div>} </div> - {!this.openAppearance ? (null) : - <div className="propertiesView-appearance-content"> - {this.appearanceEditor} - </div>} - </div>} - - {this.isInk ? <div className="propertiesView-transform"> - <div className="propertiesView-transform-title" - onPointerDown={action(() => this.openTransform = !this.openTransform)} - style={{ backgroundColor: this.openTransform ? "black" : "" }}> - Transform - <div className="propertiesView-transform-title-icon"> - <FontAwesomeIcon icon={this.openTransform ? "caret-down" : "caret-right"} size="lg" color="white" /> + )} + + {this.isInk ? ( + <div className="propertiesView-transform"> + <div className="propertiesView-transform-title" onPointerDown={action(() => (this.openTransform = !this.openTransform))} style={{ backgroundColor: this.openTransform ? 'black' : '' }}> + Transform + <div className="propertiesView-transform-title-icon"> + <FontAwesomeIcon icon={this.openTransform ? 'caret-down' : 'caret-right'} size="lg" color="white" /> + </div> + </div> + {this.openTransform ? <div className="propertiesView-transform-content">{this.transformEditor}</div> : null} </div> - </div> - {this.openTransform ? <div className="propertiesView-transform-content"> - {this.transformEditor} - </div> : null} - </div> : null} - </>; + ) : null} + </> + ); } @computed get fieldsSubMenu() { - return <div className="propertiesView-fields"> - <div className="propertiesView-fields-title" - onPointerDown={action(() => this.openFields = !this.openFields)} - style={{ backgroundColor: this.openFields ? "black" : "" }}> - Fields {"&"} Tags - <div className="propertiesView-fields-title-icon"> - <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="white" /> + return ( + <div className="propertiesView-fields"> + <div className="propertiesView-fields-title" onPointerDown={action(() => (this.openFields = !this.openFields))} style={{ backgroundColor: this.openFields ? 'black' : '' }}> + Fields {'&'} Tags + <div className="propertiesView-fields-title-icon"> + <FontAwesomeIcon icon={this.openFields ? 'caret-down' : 'caret-right'} size="lg" color="white" /> + </div> </div> + {!Doc.noviceMode && this.openFields ? ( + <div className="propertiesView-fields-checkbox"> + {this.fieldsCheckbox} + <div className="propertiesView-fields-checkbox-text">Layout</div> + </div> + ) : null} + {!this.openFields ? null : <div className="propertiesView-fields-content">{Doc.noviceMode ? this.noviceFields : this.expandedField}</div>} </div> - {!Doc.noviceMode && this.openFields ? <div className="propertiesView-fields-checkbox"> - {this.fieldsCheckbox} - <div className="propertiesView-fields-checkbox-text">Layout</div> - </div> : null} - {!this.openFields ? (null) : - <div className="propertiesView-fields-content"> - {Doc.noviceMode ? this.noviceFields : this.expandedField} - </div>} - </div>; + ); } @computed get contextsSubMenu() { - return <div className="propertiesView-contexts"> - <div className="propertiesView-contexts-title" - onPointerDown={action(() => this.openContexts = !this.openContexts)} - style={{ backgroundColor: this.openContexts ? "black" : "" }}> - Other Contexts - <div className="propertiesView-contexts-title-icon"> - <FontAwesomeIcon icon={this.openContexts ? "caret-down" : "caret-right"} size="lg" color="white" /> + return ( + <div className="propertiesView-contexts"> + <div className="propertiesView-contexts-title" onPointerDown={action(() => (this.openContexts = !this.openContexts))} style={{ backgroundColor: this.openContexts ? 'black' : '' }}> + Other Contexts + <div className="propertiesView-contexts-title-icon"> + <FontAwesomeIcon icon={this.openContexts ? 'caret-down' : 'caret-right'} size="lg" color="white" /> + </div> </div> + {this.openContexts ? <div className="propertiesView-contexts-content">{this.contexts}</div> : null} </div> - {this.openContexts ? <div className="propertiesView-contexts-content" >{this.contexts}</div> : null} - </div>; + ); } @computed get linksSubMenu() { - return <div className="propertiesView-contexts"> - <div className="propertiesView-contexts-title" - onPointerDown={action(() => this.openLinks = !this.openLinks)} - style={{ backgroundColor: this.openLinks ? "black" : "" }}> - Linked To - <div className="propertiesView-contexts-title-icon"> - <FontAwesomeIcon icon={this.openLinks ? "caret-down" : "caret-right"} size="lg" color="white" /> + return ( + <div className="propertiesView-contexts"> + <div className="propertiesView-contexts-title" onPointerDown={action(() => (this.openLinks = !this.openLinks))} style={{ backgroundColor: this.openLinks ? 'black' : '' }}> + Linked To + <div className="propertiesView-contexts-title-icon"> + <FontAwesomeIcon icon={this.openLinks ? 'caret-down' : 'caret-right'} size="lg" color="white" /> + </div> </div> + {this.openLinks ? <div className="propertiesView-contexts-content">{this.links}</div> : null} </div> - {this.openLinks ? <div className="propertiesView-contexts-content" >{this.links}</div> : null} - </div>; + ); } @computed get layoutSubMenu() { - return <div className="propertiesView-layout"> - <div className="propertiesView-layout-title" - onPointerDown={action(() => this.openLayout = !this.openLayout)} - style={{ backgroundColor: this.openLayout ? "black" : "" }}> - Layout - <div className="propertiesView-layout-title-icon"> - <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="white" /> + return ( + <div className="propertiesView-layout"> + <div className="propertiesView-layout-title" onPointerDown={action(() => (this.openLayout = !this.openLayout))} style={{ backgroundColor: this.openLayout ? 'black' : '' }}> + Layout + <div className="propertiesView-layout-title-icon"> + <FontAwesomeIcon icon={this.openLayout ? 'caret-down' : 'caret-right'} size="lg" color="white" /> + </div> </div> + {this.openLayout ? <div className="propertiesView-layout-content">{this.layoutPreview}</div> : null} </div> - {this.openLayout ? <div className="propertiesView-layout-content" >{this.layoutPreview}</div> : null} - </div>; + ); } @observable description = Field.toString(LinkManager.currentLink?.description as any as Field); @observable relationship = StrCast(LinkManager.currentLink?.linkRelationship); - @observable private relationshipButtonColor: string = ""; + @observable private relationshipButtonColor: string = ''; // @action // handleDescriptionChange = (e: React.ChangeEvent<HTMLInputElement>) => { this.description = e.target.value; } @@ -1159,11 +1371,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const linkRelationshipSizes = NumListCast(Doc.UserDoc().linkRelationshipSizes); const linkColorList = StrListCast(Doc.UserDoc().linkColorList); - // if the relationship does not exist in the list, add it and a corresponding unique randomly generated color + // if the relationship does not exist in the list, add it and a corresponding unique randomly generated color if (!linkRelationshipList?.includes(value)) { linkRelationshipList.push(value); linkRelationshipSizes.push(1); - const randColor = "rgb(" + Math.floor(Math.random() * 255) + "," + Math.floor(Math.random() * 255) + "," + Math.floor(Math.random() * 255) + ")"; + const randColor = 'rgb(' + Math.floor(Math.random() * 255) + ',' + Math.floor(Math.random() * 255) + ',' + Math.floor(Math.random() * 255) + ')'; linkColorList.push(randColor); // if the relationship is already in the list AND the new rel is different from the prev rel, update the rel sizes } else if (linkRelationshipList && value !== prevRelationship) { @@ -1171,20 +1383,22 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { //increment size of new relationship size if (index !== -1 && index < linkRelationshipSizes.length) { const pvalue = linkRelationshipSizes[index]; - linkRelationshipSizes[index] = (pvalue === undefined || !Number.isFinite(pvalue) ? 1 : pvalue + 1); + linkRelationshipSizes[index] = pvalue === undefined || !Number.isFinite(pvalue) ? 1 : pvalue + 1; } //decrement the size of the previous relationship if it already exists (i.e. not default 'link' relationship upon link creation) if (linkRelationshipList.includes(prevRelationship)) { const pindex = linkRelationshipList.indexOf(prevRelationship); if (pindex !== -1 && pindex < linkRelationshipSizes.length) { const pvalue = linkRelationshipSizes[pindex]; - linkRelationshipSizes[pindex] = Math.max(0, (pvalue === undefined || !Number.isFinite(pvalue) ? 1 : pvalue - 1)); + linkRelationshipSizes[pindex] = Math.max(0, pvalue === undefined || !Number.isFinite(pvalue) ? 1 : pvalue - 1); } } - } - this.relationshipButtonColor = "rgb(62, 133, 55)"; - setTimeout(action(() => this.relationshipButtonColor = ""), 750); + this.relationshipButtonColor = 'rgb(62, 133, 55)'; + setTimeout( + action(() => (this.relationshipButtonColor = '')), + 750 + ); return true; } }); @@ -1200,68 +1414,72 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { onSelectOutDesc = () => { this.setDescripValue(this.description); document.getElementById('link_description_input')?.blur(); - } + }; onDescriptionKey = (e: React.KeyboardEvent<HTMLInputElement>) => { - if (e.key === "Enter") { + if (e.key === 'Enter') { this.setDescripValue(this.description); document.getElementById('link_description_input')?.blur(); } - } + }; onSelectOutRelationship = () => { this.setLinkRelationshipValue(this.relationship); document.getElementById('link_relationship_input')?.blur(); - } + }; onRelationshipKey = (e: React.KeyboardEvent<HTMLInputElement>) => { - if (e.key === "Enter") { + if (e.key === 'Enter') { this.setLinkRelationshipValue(this.relationship); document.getElementById('link_relationship_input')?.blur(); } - } + }; toggleAnchor = (e: React.PointerEvent) => { setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => this.selectedDoc && (this.selectedDoc.linkAutoMove = !this.selectedDoc.linkAutoMove)))); - } + }; toggleArrow = (e: React.PointerEvent) => { setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => this.selectedDoc && (this.selectedDoc.displayArrow = !this.selectedDoc.displayArrow)))); - } + }; toggleZoomToTarget1 = (e: React.PointerEvent) => { setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => this.selectedDoc && (DocCast(this.selectedDoc.anchor1).followLinkZoom = !DocCast(this.selectedDoc.anchor1).followLinkZoom)))); - } + }; toggleZoomToTarget2 = (e: React.PointerEvent) => { setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => this.selectedDoc && (DocCast(this.selectedDoc.anchor2).followLinkZoom = !DocCast(this.selectedDoc.anchor2).followLinkZoom)))); - } + }; @computed get editRelationship() { - return <input - autoComplete={"off"} - id="link_relationship_input" - value={StrCast(this.selectedDoc?.linkRelationship)} - onKeyDown={this.onRelationshipKey} - onBlur={this.onSelectOutRelationship} - onChange={e => this.handleLinkRelationshipChange(e.currentTarget.value)} - className="text" - type="text" - />; + return ( + <input + autoComplete={'off'} + id="link_relationship_input" + value={StrCast(this.selectedDoc?.linkRelationship)} + onKeyDown={this.onRelationshipKey} + onBlur={this.onSelectOutRelationship} + onChange={e => this.handleLinkRelationshipChange(e.currentTarget.value)} + className="text" + type="text" + /> + ); } @computed get editDescription() { - return <input - autoComplete={"off"} - id="link_description_input" - value={StrCast(this.selectedDoc?.description)} - onKeyDown={this.onDescriptionKey} - onBlur={this.onSelectOutDesc} - onChange={e => this.handleDescriptionChange(e.currentTarget.value)} - className="text" - type="text" - />; + return ( + <input + autoComplete={'off'} + id="link_description_input" + value={StrCast(this.selectedDoc?.description)} + onKeyDown={this.onDescriptionKey} + onBlur={this.onSelectOutDesc} + onChange={e => this.handleDescriptionChange(e.currentTarget.value)} + className="text" + type="text" + /> + ); } /** @@ -1278,123 +1496,120 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { render() { const isNovice = Doc.noviceMode; if (!this.selectedDoc && !this.isPres) { - return <div className="propertiesView" style={{ width: this.props.width }}> - <div className="propertiesView-title" style={{ width: this.props.width }}> - No Document Selected + return ( + <div className="propertiesView" style={{ width: this.props.width }}> + <div className="propertiesView-title" style={{ width: this.props.width }}> + No Document Selected + </div> </div> - </div>; - + ); } else { if (this.selectedDoc && this.isLink) { - return <div className="propertiesView"> - <div className="propertiesView-title"> - Linking - </div> - <div className="propertiesView-section"> - <p className="propertiesView-label">Information</p> - <div className="propertiesView-input first"> - <p>Link Relationship</p> - {this.editRelationship} - </div> - <div className="propertiesView-input"> - <p>Description</p> - {this.editDescription} - </div> - </div> - <div className="propertiesView-section"> - <p className="propertiesView-label">Behavior</p> - <div className="propertiesView-input inline first"> - <p>Follow</p> - <select - name="selectList" - id="selectList" - onChange={e => this.changeFollowBehavior(e.currentTarget.value)} - value={StrCast(this.selectedDoc.followLinkLocation, "default")}> - <option value="default">Default</option> - <option value="add:left">Open in new left pane</option> - <option value="add:right">Open in new right pane</option> - <option value="replace:left">Replace left tab</option> - <option value="replace:right">Replace right tab</option> - <option value="fullScreen">Open full screen</option> - <option value="add">Open in new tab</option> - <option value="replace">Replace current tab</option> - {this.selectedDoc.linksToAnnotation - ? <option value="openExternal">Open in external page</option> - : null} - </select> - </div> - <div className="propertiesView-input inline"> - <p>Auto-move anchor</p> - <button - style={{ background: this.selectedDoc.hidden ? "gray" : !this.selectedDoc.linkAutoMove ? "" : "#4476f7", borderRadius: 3 }} - onPointerDown={this.toggleAnchor} onClick={e => e.stopPropagation()} - className="propertiesButton" - > - <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline"> - <p>Display arrow</p> - <button - style={{ background: this.selectedDoc.hidden ? "gray" : !this.selectedDoc.displayArrow ? "" : "#4476f7", borderRadius: 3 }} - onPointerDown={this.toggleArrow} onClick={e => e.stopPropagation()} - className="propertiesButton" - > - <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> - </button> - </div> - <div className="propertiesView-input inline"> - <p>Zoom to target</p> - <button - style={{ background: this.selectedDoc.hidden ? "gray" : !Cast(this.selectedDoc.anchor1, Doc, null).followLinkZoom ? "" : "#4476f7", borderRadius: 3 }} - onPointerDown={this.toggleZoomToTarget1} onClick={e => e.stopPropagation()} - className="propertiesButton" - > - <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> - </button> + return ( + <div className="propertiesView"> + <div className="propertiesView-title">Linking</div> + <div className="propertiesView-section"> + <p className="propertiesView-label">Information</p> + <div className="propertiesView-input first"> + <p>Link Relationship</p> + {this.editRelationship} + </div> + <div className="propertiesView-input"> + <p>Description</p> + {this.editDescription} + </div> </div> - <div className="propertiesView-input inline"> - <p>Zoom to source</p> - <button - style={{ background: this.selectedDoc.hidden ? "gray" : !Cast(this.selectedDoc.anchor2, Doc, null).followLinkZoom ? "" : "#4476f7", borderRadius: 3 }} - onPointerDown={this.toggleZoomToTarget2} onClick={e => e.stopPropagation()} - className="propertiesButton" - > - <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> - </button> + <div className="propertiesView-section"> + <p className="propertiesView-label">Behavior</p> + <div className="propertiesView-input inline first"> + <p>Follow</p> + <select name="selectList" id="selectList" onChange={e => this.changeFollowBehavior(e.currentTarget.value)} value={StrCast(this.selectedDoc.followLinkLocation, 'default')}> + <option value="default">Default</option> + <option value="add:left">Open in new left pane</option> + <option value="add:right">Open in new right pane</option> + <option value="replace:left">Replace left tab</option> + <option value="replace:right">Replace right tab</option> + <option value="fullScreen">Open full screen</option> + <option value="add">Open in new tab</option> + <option value="replace">Replace current tab</option> + {this.selectedDoc.linksToAnnotation ? <option value="openExternal">Open in external page</option> : null} + </select> + </div> + <div className="propertiesView-input inline"> + <p>Auto-move anchor</p> + <button + style={{ background: this.selectedDoc.hidden ? 'gray' : !this.selectedDoc.linkAutoMove ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={this.toggleAnchor} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline"> + <p>Display arrow</p> + <button + style={{ background: this.selectedDoc.hidden ? 'gray' : !this.selectedDoc.displayArrow ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={this.toggleArrow} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline"> + <p>Zoom to target</p> + <button + style={{ background: this.selectedDoc.hidden ? 'gray' : !Cast(this.selectedDoc.anchor1, Doc, null).followLinkZoom ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={this.toggleZoomToTarget1} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> + </button> + </div> + <div className="propertiesView-input inline"> + <p>Zoom to source</p> + <button + style={{ background: this.selectedDoc.hidden ? 'gray' : !Cast(this.selectedDoc.anchor2, Doc, null).followLinkZoom ? '' : '#4476f7', borderRadius: 3 }} + onPointerDown={this.toggleZoomToTarget2} + onClick={e => e.stopPropagation()} + className="propertiesButton"> + <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" /> + </button> + </div> </div> </div> - </div >; + ); } if (this.selectedDoc && !this.isPres) { - return <div className="propertiesView" style={{ - width: this.props.width, - minWidth: this.props.width, - //overflowY: this.scrolling ? "scroll" : "visible" - }} > - <div className="propertiesView-title" style={{ width: this.props.width }}> - Properties - </div> - <div className="propertiesView-name"> - {this.editableTitle} - </div> + return ( + <div + className="propertiesView" + style={{ + width: this.props.width, + minWidth: this.props.width, + //overflowY: this.scrolling ? "scroll" : "visible" + }}> + <div className="propertiesView-title" style={{ width: this.props.width }}> + Properties + </div> + <div className="propertiesView-name">{this.editableTitle}</div> - {this.contextsSubMenu} + {this.contextsSubMenu} - {this.linksSubMenu} + {this.linksSubMenu} - {this.inkSubMenu} + {this.inkSubMenu} - {this.optionsSubMenu} + {this.optionsSubMenu} - {this.fieldsSubMenu} + {this.fieldsSubMenu} - {isNovice ? null : this.sharingSubMenu} + {isNovice ? null : this.sharingSubMenu} - {isNovice ? null : this.filtersSubMenu} + {isNovice ? null : this.filtersSubMenu} - {isNovice ? null : this.layoutSubMenu} - </div>; + {isNovice ? null : this.layoutSubMenu} + </div> + ); } if (this.isPres) { const selectedItem: boolean = PresBox.Instance?._selectedArray.size > 0; @@ -1402,35 +1617,35 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const viewType = PresBox.Instance.activeItem?._viewType; const pannable: boolean = (type === DocumentType.COL && viewType === CollectionViewType.Freeform) || type === DocumentType.IMG; const scrollable: boolean = type === DocumentType.PDF || type === DocumentType.WEB || type === DocumentType.RTF || viewType === CollectionViewType.Stacking; - return <div className="propertiesView" style={{ width: this.props.width }}> - <div className="propertiesView-title" style={{ width: this.props.width }}> - 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> - <div className="propertiesView-selectedList"> - {PresBox.Instance?.listOfSelected} - </div> + return ( + <div className="propertiesView" style={{ width: this.props.width }}> + <div className="propertiesView-title" style={{ width: this.props.width }}> + Presentation </div> - </div> - {!selectedItem ? (null) : <div className="propertiesView-presTrails"> - <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" color="white" /> + <div className="propertiesView-name" style={{ borderBottom: 0 }}> + {this.editableTitle} + <div className="propertiesView-presSelected"> + <div className="propertiesView-selectedCount">{PresBox.Instance?._selectedArray.size} selected</div> + <div className="propertiesView-selectedList">{PresBox.Instance?.listOfSelected}</div> </div> </div> - {this.openPresTransitions ? <div className="propertiesView-presTrails-content"> - {PresBox.Instance.transitionDropdown} - </div> : null} - </div>} - {/* {!selectedItem || type === DocumentType.VID || type === DocumentType.AUDIO ? (null) : <div className="propertiesView-presTrails"> + {!selectedItem ? null : ( + <div className="propertiesView-presTrails"> + <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" color="white" /> + </div> + </div> + {this.openPresTransitions ? <div className="propertiesView-presTrails-content">{PresBox.Instance.transitionDropdown}</div> : null} + </div> + )} + {/* {!selectedItem || type === DocumentType.VID || type === DocumentType.AUDIO ? (null) : <div className="propertiesView-presTrails"> <div className="propertiesView-presTrails-title" onPointerDown={action(() => this.openPresProgressivize = !this.openPresProgressivize)} style={{ backgroundColor: this.openPresProgressivize ? "black" : "" }}> @@ -1443,20 +1658,23 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { {PresBox.Instance.progressivizeDropdown} </div> : null} </div>} */} - {!selectedItem || (type !== DocumentType.VID && type !== DocumentType.AUDIO) ? (null) : <div className="propertiesView-presTrails"> - <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" color="white" /> + {!selectedItem || (type !== DocumentType.VID && type !== DocumentType.AUDIO) ? null : ( + <div className="propertiesView-presTrails"> + <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" color="white" /> + </div> + </div> + {this.openSlideOptions ? <div className="propertiesView-presTrails-content">{PresBox.Instance.mediaOptionsDropdown}</div> : null} </div> - </div> - {this.openSlideOptions ? <div className="propertiesView-presTrails-content"> - {PresBox.Instance.mediaOptionsDropdown} - </div> : null} - </div>} - {/* <div className="propertiesView-presTrails"> + )} + {/* <div className="propertiesView-presTrails"> <div className="propertiesView-presTrails-title" onPointerDown={action(() => { this.openAddSlide = !this.openAddSlide; })} style={{ backgroundColor: this.openAddSlide ? "black" : "" }}> @@ -1469,8 +1687,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { {PresBox.Instance.newDocumentDropdown} </div> : null} </div> */} - </div>; + </div> + ); } } } -}
\ No newline at end of file +} |