From 57501970d9b56ed39c6b29680286d66a536df5f1 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 8 Sep 2021 18:55:32 -0400
Subject: added showTitle prop to allow sidebarAnnos to have a custom title

---
 src/client/views/SidebarAnnos.tsx | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

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

diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index 01b79ffd2..dd851c764 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -83,13 +83,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
     moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument(doc, targetCollection, addDocument, this.sidebarKey);
     removeDocument = (doc: Doc | Doc[]) => this.props.removeDocument(doc, this.sidebarKey);
     docFilters = () => [...StrListCast(this.props.layoutDoc._docFilters), ...StrListCast(this.props.layoutDoc[this.filtersKey])];
-
-    sidebarStyleProvider = (doc: Opt<Doc>, props: Opt<FieldViewProps | DocumentViewProps>, property: string) => {
-        if (property === StyleProp.ShowTitle) {
-            return doc === this.props.rootDoc ? undefined : StrCast(this.props.layoutDoc["sidebar-childShowTitle"], "title");
-        }
-        return this.props.styleProvider?.(doc, props, property);
-    }
+    showTitle = () => "title";
     setHeightCallback = (height: number) => this.props.setHeight(height + this.filtersHeight());
     render() {
         const renderTag = (tag: string) => {
@@ -125,13 +119,13 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
                         NativeHeight={returnZero}
                         PanelHeight={this.panelHeight}
                         PanelWidth={this.panelWidth}
-                        styleProvider={this.sidebarStyleProvider}
                         docFilters={this.docFilters}
                         scaleField={this.sidebarKey + "-scale"}
                         setHeight={this.setHeightCallback}
                         isAnnotationOverlay={false}
                         select={emptyFunction}
                         scaling={returnOne}
+                        childShowTitle={this.showTitle}
                         whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
                         childHideDecorationTitle={returnTrue}
                         removeDocument={this.removeDocument}
-- 
cgit v1.2.3-70-g09d2


From d95f1f9808d88ce1a808684f82b5f9e4ff9b254b Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 10 Sep 2021 00:32:06 -0400
Subject: fixed sidebar annos to filter on metdata as well as hashtags.

---
 src/client/documents/Documents.ts   | 10 +++++++---
 src/client/util/CurrentUserUtils.ts |  2 +-
 src/client/views/SidebarAnnos.tsx   | 15 +++++++++++----
 src/fields/Doc.ts                   |  2 +-
 4 files changed, 20 insertions(+), 9 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 9a45da440..f50f306a3 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -959,12 +959,16 @@ export namespace DocUtils {
                 // facets that have a check next to them
                 const checks = Object.keys(facet).filter(value => facet[value] === "check");
 
+                // metadata facets that exist
+                const exists = Object.keys(facet).filter(value => facet[value] === "exists");
+
                 // facets that have an x next to them
                 const xs = Object.keys(facet).filter(value => facet[value] === "x");
 
-                if (!xs.length && !checks.length && !matches.length) return true;
+                if (!exists.length && !xs.length && !checks.length && !matches.length) return true;
                 const failsNotEqualFacets = !xs.length ? false : xs.some(value => Doc.matchFieldValue(d, facetKey, value));
                 const satisfiesCheckFacets = !checks.length ? true : checks.some(value => Doc.matchFieldValue(d, facetKey, value));
+                const satisfiesExistsFacets = !exists.length ? true : exists.some(value => d[facetKey] !== undefined);
                 const satisfiesMatchFacets = !matches.length ? true : matches.some(value => {
                     if (facetKey.startsWith("*")) { //  fields starting with a '*' are used to match families of related fields.  ie, *lastModified will match text-lastModified, data-lastModified, etc
                         const allKeys = Array.from(Object.keys(d));
@@ -976,11 +980,11 @@ export namespace DocUtils {
                 });
                 // if we're ORing them together, the default return is false, and we return true for a doc if it satisfies any one set of criteria
                 if ((parentCollection?.currentFilter as Doc)?.filterBoolean === "OR") {
-                    if (satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true;
+                    if (satisfiesExistsFacets && satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true;
                 }
                 // if we're ANDing them together, the default return is true, and we return false for a doc if it doesn't satisfy any set of criteria
                 else {
-                    if (!satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false;
+                    if (!satisfiesExistsFacets || !satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false;
                 }
 
             }
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 60bb375c8..d58917704 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -455,7 +455,7 @@ export class CurrentUserUtils {
                 "<HTMLdiv transformOrigin='top left' width='{100/scale}%' height='{100/scale}%' transform='scale({scale})'>" +
                 `    <FormattedTextBox {...props} dontScale='true' fieldKey={'text'}  height='calc(100% - ${headerBtnHgt}px - {this._headerHeight||0}px)'/>` +
                 "    <FormattedTextBox {...props} dontScale='true' fieldKey={'header'}  dontSelectOnLoad='true' ignoreAutoHeight='true' fontSize='{this._headerFontSize||9}px' height='{(this._headerHeight||0)}px' background='{this._headerColor || MySharedDocs().userColor||`lightGray`}' />" +
-                `    <HTMLdiv fontSize='${headerBtnHgt - 1}px' height='${headerBtnHgt}px' background='yellow' onClick={‘(this._headerHeight=scale*Math.min(Math.max(0,this._height-30),this._headerHeight===0?50:0)) && (this._autoHeightMargins=this._headerHeight+${headerBtnHgt})’}  >Metadata</HTMLdiv>` +
+                `    <HTMLdiv fontSize='${headerBtnHgt - 1}px' height='${headerBtnHgt}px' background='yellow' onClick={‘(this._headerHeight=scale*Math.min(Math.max(0,this._height-30),this._headerHeight===0?50:0)) + (this._autoHeightMargins=this._headerHeight ? this._headerHeight+${headerBtnHgt}:0)’}  >Metadata</HTMLdiv>` +
                 "</HTMLdiv>";
 
             // "<div style={'height:100%'}>" +
diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index dd851c764..659eb86d1 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -38,10 +38,10 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
         // this.props.dataDoc[this.sidebarKey] = new List<Doc>();  // bcz: can't do this here.  it blows away existing things and isn't a robust solution for making sure the field exists -- instead this should happen when the document is created and/or shared
     }
     _stackRef = React.createRef<CollectionStackingView>();
-    @computed get allHashtags() {
+    @computed get allMetadata() {
         const keys = new Set<string>();
         DocListCast(this.props.rootDoc[this.sidebarKey]).forEach(doc => SearchBox.documentKeys(doc).forEach(key => keys.add(key)));
-        return Array.from(keys.keys()).filter(key => key[0]).filter(key => !key.startsWith("_") && (key[0] === "#" || key[0] === key[0].toUpperCase())).sort();
+        return Array.from(keys.keys()).filter(key => key[0]).filter(key => key[0] !== "_" && (key[0] === key[0].toUpperCase())).sort();
     }
     @computed get allUsers() {
         const keys = new Set<string>();
@@ -59,7 +59,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
         });
         FormattedTextBox.SelectOnLoad = target[Id];
         FormattedTextBox.DontSelectInitialText = true;
-        this.allHashtags.map(tag => target[tag] = tag);
+        this.allMetadata.map(tag => target[tag] = tag);
         DocUtils.MakeLink({ doc: anchor }, { doc: target }, "inline markup", "annotation");
         this.addDocument(target);
         this._stackRef.current?.focusDocument(target);
@@ -93,6 +93,13 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
                 {tag}
             </div>;
         };
+        const renderMeta = (tag: string) => {
+            const active = StrListCast(this.props.rootDoc[this.filtersKey]).includes(`${tag}:${tag}:exists`);
+            return <div key={tag} className={`sidebarAnnos-filterTag${active ? "-active" : ""}`}
+                onClick={e => Doc.setDocFilter(this.props.rootDoc, tag, tag, "exists", true, this.sidebarKey, e.shiftKey)}>
+                {tag}
+            </div>;
+        };
         const renderUsers = (user: string) => {
             const active = StrListCast(this.props.rootDoc[this.filtersKey]).includes(`author:${user}:check`);
             return <div key={user} className={`sidebarAnnos-filterUser${active ? "-active" : ""}`}
@@ -111,7 +118,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
                 <div className="sidebarAnnos-tagList" style={{ height: this.filtersHeight(), width: this.panelWidth() }}
                     onWheel={e => e.stopPropagation()}>
                     {this.allUsers.map(renderUsers)}
-                    {this.allHashtags.map(renderTag)}
+                    {this.allMetadata.map(renderMeta)}
                 </div>
                 <div style={{ width: "100%", height: this.panelHeight(), position: "relative" }}>
                     <CollectionStackingView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit} ref={this._stackRef}
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index b09ff93d0..4d040f3bc 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1136,7 +1136,7 @@ export namespace Doc {
     // filters document in a container collection:
     // all documents with the specified value for the specified key are included/excluded
     // based on the modifiers :"check", "x", undefined
-    export function setDocFilter(container: Opt<Doc>, key: string, value: any, modifiers: "remove" | "match" | "check" | "x", toggle?: boolean, fieldSuffix?: string, append: boolean = true) {
+    export function setDocFilter(container: Opt<Doc>, key: string, value: any, modifiers: "remove" | "match" | "check" | "x" | "exists", toggle?: boolean, fieldSuffix?: string, append: boolean = true) {
         if (!container) return;
         const filterField = "_" + (fieldSuffix ? fieldSuffix + "-" : "") + "docFilters";
         const docFilters = Cast(container[filterField], listSpec("string"), []);
-- 
cgit v1.2.3-70-g09d2

