From 3c8af89e3d5370b748fea27c411b3e62758b9a45 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 19 Sep 2024 17:50:48 -0400
Subject: changed backend for filtering buttons to store only one list - the
 list of icon buttons in Doc.MyFilterHotKeys.

---
 src/client/views/FilterPanel.tsx | 86 +++++++++++++++++++---------------------
 1 file changed, 41 insertions(+), 45 deletions(-)

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

diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx
index b6bea1d4b..a3c8fc383 100644
--- a/src/client/views/FilterPanel.tsx
+++ b/src/client/views/FilterPanel.tsx
@@ -26,7 +26,7 @@ import { ObservableReactComponent } from './ObservableReactComponent';
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 
 interface HotKeyButtonProps {
-    hotKey: string;
+    hotKey: Doc;
     selected?: Doc;
 }
 
@@ -53,7 +53,7 @@ const HotKeyIconButton: React.FC<HotKeyButtonProps> = observer(({ hotKey /*, sel
             this.isEditing = false;
         },
         setHotKey(newHotKey: string) {
-            this.myHotKey = newHotKey;
+            this.myHotKey.title = newHotKey;
         },
     }));
 
@@ -64,24 +64,13 @@ const HotKeyIconButton: React.FC<HotKeyButtonProps> = observer(({ hotKey /*, sel
         state.toggleActive();
     };
 
-    const hotKeys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles);
     const buttons = DocCast(Doc.UserDoc().myContextMenuBtns);
-    const filter = DocCast(buttons.Filter);
-
-    /**
-     * The doc of the button in the context menu that corresponds to the current hotkey
-     * @returns
-     */
-    const myHotKeyDoc = () => {
-        const hotKeyDocs = DocListCast(filter.data);
-        return hotKeyDocs.filter(k => StrCast(k.title) === hotKey)[0];
-    };
 
     /**
      * Removes a hotkey from list
      */
     const removeHotKey = () => {
-        Doc.RemoveDocFromList(filter, 'data', myHotKeyDoc());
+        Doc.RemFromFilterHotKeys(hotKey);
     };
 
     /**
@@ -89,11 +78,8 @@ const HotKeyIconButton: React.FC<HotKeyButtonProps> = observer(({ hotKey /*, sel
      * hotkey with the current icon
      */
     const updateFromInput = undoable(() => {
-        const myDoc = myHotKeyDoc();
-        Doc.UserDoc().myFilterHotKeyTitles = new List<string>(hotKeys.map(k => (k === hotKey ? state.myHotKey : k)));
-        Doc.UserDoc()[state.myHotKey] = StrCast(Doc.UserDoc()[hotKey]);
-        myDoc.title = state.myHotKey;
-        myDoc.toolTip = `Click to toggle the ${state.myHotKey}'s group's visibility`;
+        hotKey.title = StrCast(state.myHotKey.title);
+        hotKey.toolTip = `Click to toggle the ${StrCast(hotKey.title)}'s group's visibility`;
     }, '');
 
     /**
@@ -123,13 +109,12 @@ const HotKeyIconButton: React.FC<HotKeyButtonProps> = observer(({ hotKey /*, sel
     /**
      * Panel of icons the user can choose from to represent their tag
      */
-    const iconPanel = iconOpts.map((icon, i) => (
+    const iconPanel = iconOpts.map(icon => (
         <button
-            key={i}
-            onClick={undoable((e: React.MouseEvent) => {
+            key={icon.toString()}
+            onClick={undoable(e => {
                 e.stopPropagation;
-                Doc.UserDoc()[hotKey] = icon.toString();
-                myHotKeyDoc().icon = icon.toString();
+                hotKey[DocData].icon = icon.toString();
             }, '')}
             className="icon-panel-button">
             <FontAwesomeIcon icon={icon} color={SnappingManager.userColor} />
@@ -157,7 +142,7 @@ const HotKeyIconButton: React.FC<HotKeyButtonProps> = observer(({ hotKey /*, sel
                             e.stopPropagation();
                             handleClick();
                         }}>
-                        <FontAwesomeIcon icon={Doc.UserDoc()[hotKey] as IconProp} size="2xl" color={SnappingManager.userColor} />
+                        <FontAwesomeIcon icon={hotKey.icon as IconProp} size="2xl" color={SnappingManager.userColor} />
                     </button>
                 </Tooltip>
                 {state.isActive && <div className="icon-panel">{iconPanel}</div>}
@@ -166,7 +151,7 @@ const HotKeyIconButton: React.FC<HotKeyButtonProps> = observer(({ hotKey /*, sel
                 <input
                     ref={inputRef}
                     type="text"
-                    value={state.myHotKey.toUpperCase()}
+                    value={StrCast(state.myHotKey.title).toUpperCase()}
                     onChange={e => state.setHotKey(e.target.value)}
                     onBlur={() => {
                         state.stopEditing();
@@ -181,13 +166,12 @@ const HotKeyIconButton: React.FC<HotKeyButtonProps> = observer(({ hotKey /*, sel
                     className="hotkey-title-input"
                 />
             ) : (
-                <p className="hotkey-title">{hotKey.toUpperCase()}</p>
+                <p className="hotkey-title">{StrCast(hotKey.title).toUpperCase()}</p>
             )}
             <button
                 className="hotKey-close"
                 onClick={(e: React.MouseEvent) => {
                     e.stopPropagation();
-                    Doc.UserDoc().myFilterHotKeyTitles = new List<string>(hotKeys.filter(k => k !== hotKey));
                     removeHotKey();
                 }}>
                 <FontAwesomeIcon icon={'x' as IconProp} color={SnappingManager.userColor} />
@@ -310,7 +294,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
     @computed get activeRenderedFacetInfos() {
         return new Set(
             Array.from(new Set(Array.from(this._selectedFacetHeaders).concat(this.activeFacetHeaders))).map(facetHeader => {
-                const facetValues = FilterPanel.gatherFieldValues(this.targetDocChildren, facetHeader, StrListCast(this.Document.childFilters));
+                const facetValues = facetHeader.startsWith('#') ? { strings: [] } : FilterPanel.gatherFieldValues(this.targetDocChildren, facetHeader, StrListCast(this.Document.childFilters));
 
                 let nonNumbers = 0;
                 let minVal = Number.MAX_VALUE;
@@ -328,7 +312,10 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
                 if (facetHeader === 'text') {
                     return { facetHeader, renderType: 'text' };
                 }
-                if (facetHeader !== 'tags' && nonNumbers / facetValues.strings.length < 0.1) {
+                if (facetHeader.startsWith('#')) {
+                    return { facetHeader, renderType: 'togglebox' };
+                }
+                if (facetHeader !== 'tags' && !facetHeader.startsWith('#') && nonNumbers / facetValues.strings.length < 0.1) {
                     const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1));
                     const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05)));
                     const ranged: number[] | undefined = Doc.readDocRangeFilter(this.Document, facetHeader); // not the filter range, but the zooomed in range on the filter
@@ -400,30 +387,23 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
     addHotkey = (hotKey: string) => {
         const buttons = DocCast(Doc.UserDoc().myContextMenuBtns);
         const filter = DocCast(buttons.Filter);
+        const title = hotKey.startsWith('#') ? hotKey.substring(1) : hotKey;
 
         const newKey: Button = {
-            title: hotKey,
-            icon: 'bolt',
-            toolTip: `Click to toggle the ${hotKey}'s group's visibility`,
+            title,
+            icon: 'question',
+            toolTip: `Click to toggle the ${title}'s group's visibility`,
             btnType: ButtonType.ToggleButton,
             expertMode: false,
-            toolType: 'bolt',
+            toolType: '#' + title,
             funcs: {},
             scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}' },
         };
 
-        const currHotKeys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles);
-
-        Doc.UserDoc().myFilterHotKeyTitles = new List<string>(currHotKeys.concat(hotKey));
-
-        Doc.UserDoc()[hotKey] = 'bolt';
-
         const newBtn = CurrentUserUtils.setupContextMenuBtn(newKey, filter);
         newBtn.isSystem = newBtn[DocData].isSystem = undefined;
 
-        const subDocs = DocListCast(filter.data);
-        const opts = subDocs[subDocs.length - 1];
-        Doc.AddDocToList(filter, 'data', newBtn, opts, true);
+        Doc.AddToFilterHotKeys(newBtn);
     };
 
     /**
@@ -432,11 +412,11 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
      */
     hotKeyButtons = () => {
         const selected = DocumentView.SelectedDocs().lastElement();
-        const hotKeys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles);
+        const hotKeys = Doc.MyFilterHotKeys;
 
         // Selecting a button should make it so that the icon on the top filter panel becomes said icon
         const buttons = hotKeys.map(hotKey => (
-            <Tooltip key={hotKey} title={<div className="dash-tooltip">Click to customize this hotkey&apos;s icon</div>}>
+            <Tooltip key={StrCast(hotKey.title)} title={<div className="dash-tooltip">Click to customize this hotkey&apos;s icon</div>}>
                 <HotKeyIconButton hotKey={hotKey} selected={selected} />
             </Tooltip>
         ));
@@ -561,6 +541,22 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
                         </div>
                     );
                 });
+            case 'togglebox':
+                return (
+                    <div>
+                        <input
+                            style={{ width: 20, marginLeft: 20 }}
+                            checked={['check', 'exists'].includes(
+                                StrListCast(this.Document._childFilters)
+                                    .find(filter => filter.split(Doc.FilterSep)[0] === 'tags' && filter.split(Doc.FilterSep)[1] === facetHeader)
+                                    ?.split(Doc.FilterSep)[2] ?? ''
+                            )}
+                            type={'checkbox'}
+                            onChange={undoable(e => Doc.setDocFilter(this.Document, 'tags', facetHeader, e.target.checked ? 'check' : 'remove'), 'set filter')}
+                        />
+                        -set-
+                    </div>
+                );
 
             case 'range':
                 {
-- 
cgit v1.2.3-70-g09d2

