import React = require("react"); import { observer } from "mobx-react"; import "./PropertiesView.scss"; import { observable, action, computed, runInAction } from "mobx"; import { Doc, Field, DocListCast, WidthSym, HeightSym } from "../../../../fields/Doc"; import { DocumentView } from "../../nodes/DocumentView"; import { ComputedField } from "../../../../fields/ScriptField"; import { EditableView } from "../../EditableView"; import { KeyValueBox } from "../../nodes/KeyValueBox"; import { Cast, NumCast, StrCast } from "../../../../fields/Types"; import { listSpec } from "../../../../fields/Schema"; import { ContentFittingDocumentView } from "../../nodes/ContentFittingDocumentView"; import { returnFalse, returnOne, emptyFunction, emptyPath, returnTrue, returnZero, returnEmptyFilter, Utils } from "../../../../Utils"; import { Id } from "../../../../fields/FieldSymbols"; import { Transform } from "../../../util/Transform"; import { PropertiesButtons } from "../../PropertiesButtons"; import { SelectionManager } from "../../../util/SelectionManager"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip, Checkbox } from "@material-ui/core"; import SharingManager from "../../../util/SharingManager"; interface PropertiesViewProps { width: number; height: number; renderDepth: number; ScreenToLocalTransform: () => Transform; onDown: (event: any) => void; } @observer export class PropertiesView extends React.Component { @computed get MAX_EMBED_HEIGHT() { return 200; } @computed get selectedDocumentView() { if (SelectionManager.SelectedDocuments().length) { return SelectionManager.SelectedDocuments()[0]; } else { return undefined; } } @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; } @computed get dataDoc() { return this.selectedDocumentView?.dataDoc; } @observable layoutFields: boolean = false; @observable openActions: boolean = true; @observable openSharing: boolean = true; @observable openFields: boolean = true; @observable openLayout: boolean = true; @action rtfWidth = () => { if (this.selectedDoc) { return Math.min(this.selectedDoc?.[WidthSym](), this.props.width - 20); } else { return 0; } } @action rtfHeight = () => { if (this.selectedDoc) { return this.rtfWidth() <= this.selectedDoc?.[WidthSym]() ? Math.min(this.selectedDoc?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT; } else { return 0; } } @action docWidth = () => { if (this.selectedDoc) { const layoutDoc = this.selectedDoc; const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]()); if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.width - 20)); return NumCast(layoutDoc._nativeWidth) ? Math.min(layoutDoc[WidthSym](), this.props.width - 20) : this.props.width - 20; } else { return 0; } } @action docHeight = () => { if (this.selectedDoc && this.dataDoc) { const layoutDoc = this.selectedDoc; return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, (() => { const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]()); if (aspect) return this.docWidth() * aspect; return layoutDoc._fitWidth ? (!this.dataDoc._nativeHeight ? NumCast(this.props.height) : Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, NumCast(layoutDoc._nativeHeight)) / NumCast(layoutDoc._nativeWidth, NumCast(this.props.height)))) : NumCast(layoutDoc._height) ? NumCast(layoutDoc._height) : 50; })())); } else { return 0; } } @computed get expandedField() { if (this.dataDoc && this.selectedDoc) { const ids: { [key: string]: string } = {}; const doc = this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc; 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 contents = doc[key]; if (contents === "UNDEFINED") { rows.push(
{key}  
); } else { let contentElement: (JSX.Element | null)[] | JSX.Element = []; contentElement = Field.toKeyValueString(doc, key)} SetValue={(value: string) => KeyValueBox.SetField(doc, key, value, true)} />; rows.push(
{key + ":"}   {contentElement}
); } } rows.push(
""} SetValue={this.setKeyValue} />
); return rows; } } @computed get noviceFields() { if (this.dataDoc && this.selectedDoc) { const ids: { [key: string]: string } = {}; const doc = this.dataDoc; 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()) { if (key[0] === key[0].toUpperCase() || key[0] === "#" || key === "author" || key === "creationDate" || key.indexOf("lastModified") !== -1) { const contents = doc[key]; if (contents === "UNDEFINED") { rows.push(
{key}  
); } else { const value = Field.toString(contents as Field); if (key === "author" || key === "creationDate" || key.indexOf("lastModified") !== -1) { rows.push(
{key + ": "}
{value}
); } else { let contentElement: (JSX.Element | null)[] | JSX.Element = []; contentElement = Field.toKeyValueString(doc, key)} SetValue={(value: string) => KeyValueBox.SetField(doc, key, value, true)} />; rows.push(
{key + ":"}   {contentElement}
); } } } } rows.push(
""} SetValue={this.setKeyValue} />
); return rows; } } setKeyValue = (value: string) => { if (this.selectedDoc && this.dataDoc) { const doc = this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc; if (value.indexOf(":") !== -1) { const newVal = value[0].toUpperCase() + value.substring(1, value.length); KeyValueBox.SetField(doc, newVal.substring(0, newVal.indexOf(":")), newVal.substring(newVal.indexOf(":") + 1, newVal.length), true); return true; } else if (value[0] === "#") { const newVal = value + ":'UNDEFINED'"; KeyValueBox.SetField(doc, newVal.substring(0, newVal.indexOf(":")), newVal.substring(newVal.indexOf(":") + 1, newVal.length), true); return true; } } return false; } @computed get layoutPreview() { 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
"lightgrey"} fitToBox={false} FreezeDimensions={true} NativeWidth={layoutDoc.type === StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : returnZero} NativeHeight={layoutDoc.type === StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : returnZero} PanelWidth={panelWidth} PanelHeight={panelHeight} focus={returnFalse} ScreenToLocalTransform={this.props.ScreenToLocalTransform} docFilters={returnEmptyFilter} ContainingCollectionDoc={undefined} ContainingCollectionView={undefined} addDocument={returnFalse} moveDocument={undefined} removeDocument={returnFalse} parentActive={() => false} whenActiveChanged={emptyFunction} addDocTab={returnFalse} pinToPres={emptyFunction} bringToFront={returnFalse} ContentScaling={returnOne} />
; } else { return null; } } @computed get permissionsSelect() { return ; } @computed get notifyIcon() { return
{"Notify group of permissions change"}
}>
; } @computed get expansionIcon() { return
{"Show more permissions"}
}>
{ if (this.selectedDocumentView) { SharingManager.Instance.open(this.selectedDocumentView); } }}>
; } sharingItem(name: string, notify: boolean, editable: boolean, permission?: string) { return
{name}
{notify ? this.notifyIcon : null}
{editable ? this.permissionsSelect : permission} {permission === "Owner" ? this.expansionIcon : null}
; } @computed get sharingTable() { return
{this.sharingItem("Me", false, false, "Owner")} {this.sharingItem("Public", false, true)} {this.sharingItem("Group 1", true, true)} {this.sharingItem("Group 2", true, true)}
; } @computed get fieldsCheckbox() { return ; } @action toggleCheckbox = () => { this.layoutFields = !this.layoutFields; } @computed get editableTitle() { return StrCast(this.selectedDoc?.title)} SetValue={this.setTitle} />; } setTitle = (value: string) => { if (this.dataDoc) { this.selectedDoc && (this.selectedDoc.title = value); KeyValueBox.SetField(this.dataDoc, "title", value, true); return true; } return false; } render() { if (!this.selectedDoc) { return
No Document Selected
; } const novice = Doc.UserDoc().noviceMode; return
Properties
{this.editableTitle}
runInAction(() => { this.openActions = !this.openActions; })}>
Document Actions
{this.openActions ?
: null}
runInAction(() => { this.openSharing = !this.openSharing; })}>
Sharing {"&"} Permissions
{this.openSharing ?
{this.sharingTable}
: null}
runInAction(() => { this.openFields = !this.openFields; })}>
Fields {"&"} Tags
{!novice && this.openFields ?
{this.fieldsCheckbox}
Layout
: null}
{this.openFields ?
{novice ? this.noviceFields : this.expandedField}
: null}
runInAction(() => { this.openLayout = !this.openLayout; })}>
Layout
{this.openLayout ?
{this.layoutPreview}
: null}
; } }