From 2255f2ffd4d9c5818d8d26f1814b315ad914eaa9 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 8 May 2023 11:34:29 -0400
Subject: fixed dragging inkMask strokes.  fixed background color/fill for
 strokes.  fixed send to back.  changed #tags to be a list

---
 src/client/views/PropertiesView.tsx | 150 +++++++++++-------------------------
 1 file changed, 45 insertions(+), 105 deletions(-)

(limited to 'src/client/views/PropertiesView.tsx')

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>
-                            &nbsp;
-                        </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>
-                            &nbsp;
-                            {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>
+                        &nbsp;
+                        {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>
-                            &nbsp;
-                        </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>
-                                &nbsp;
-                                {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;
             }
-- 
cgit v1.2.3-70-g09d2

