diff options
Diffstat (limited to 'src/client/views/PropertiesView.tsx')
-rw-r--r-- | src/client/views/PropertiesView.tsx | 150 |
1 files changed, 45 insertions, 105 deletions
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 6582c3f2a..fff8390b3 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -7,7 +7,7 @@ import { intersection } from 'lodash'; import { action, computed, Lambda, observable } from 'mobx'; import { observer } from 'mobx-react'; import { ColorState, SketchPicker } from 'react-color'; -import { AclAdmin, AclSym, DataSym, Doc, Field, HeightSym, HierarchyMapping, NumListCast, Opt, StrListCast, WidthSym } from '../../fields/Doc'; +import { AclAdmin, AclSym, DataSym, Doc, Field, FieldResult, HeightSym, HierarchyMapping, NumListCast, Opt, StrListCast, WidthSym } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; import { InkField } from '../../fields/InkField'; import { List } from '../../fields/List'; @@ -152,116 +152,55 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { return 0; }; - @computed get expandedField() { + editableFields = (filter: (key: string) => boolean, reqdKeys: string[]) => { + const rows: JSX.Element[] = []; 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)); - 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> - ); - } 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 ids = new Set<string>(reqdKeys); + const docs: Doc[] = 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 => doc[key] !== ComputedField.undefined && ids.add(key))); + + // prettier-ignore + Array.from(ids).filter(filter).sort().map(key => { + const multiple = Array.from(docs.reduce((set,doc) => set.add(doc[key]), new Set<FieldResult>()).keys()).length > 1; + const editableContents = multiple ? '-multiple-' : Field.toKeyValueString(docs[0], key); + const displayContents = multiple ? '-multiple-' : Field.toString(docs[0][key] as Field); + const contentElement = key[0] === '#' ? <></> : ( + <EditableView + key="editableView" + contents={displayContents} + height={13} + fontSize={10} + GetValue={() => editableContents} + SetValue={(value: string) => { + value !== '-multiple-' && 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' }}> + <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; } + return rows; + }; + + @computed get expandedField() { + return this.editableFields(returnTrue, []); } @computed get noviceFields() { - if (this.dataDoc) { - const ids: { [key: string]: string } = {}; - 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]; - 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> - ); - } 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> - ); - } 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; - }} - /> - ); - - 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> - ); - return rows; - } + const noviceReqFields = ['author', 'creationDate', 'tags', '_curPage']; + return this.editableFields(key => key[0] === '#' || key.indexOf('lastModified') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('acl')), noviceReqFields); } @undoBatch @@ -280,9 +219,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } else if (value[0] === '#') { const newVal = value + `:'${value}'`; doc[DataSym][value] = value; - const tags = StrCast(doc.tags, ':'); - if (!tags.includes(`${value}:`)) { - doc[DataSym].tags = `${tags + value + ':'}`; + const tags = StrListCast(doc.tags); + if (!tags.includes(value)) { + tags.push(value); + doc[DataSym].tags = tags.length ? new List<string>(tags) : undefined; } return true; } |