From b9f15c10e4cfa1288e176cbd1d312c628c5998ad Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 10 Sep 2024 14:54:44 -0400
Subject: moved TagsView up into DocumentView so that one row of tags will be
 visible. fixed setting pixel size of images to resize annotations so they
 don't appear to change. added vert/horiz centering for stacking views.  fixed
 pres box to not have scroll bars.  fixed resizing properties panel.

---
 src/client/views/nodes/FieldView.tsx | 1 +
 1 file changed, 1 insertion(+)

(limited to 'src/client/views/nodes/FieldView.tsx')

diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index dd71fd946..c269c7bcb 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -82,6 +82,7 @@ export interface FieldViewSharedProps {
     // eslint-disable-next-line no-use-before-define
     onKey?: (e: React.KeyboardEvent, fieldProps: FieldViewProps) => boolean | undefined;
     fitWidth?: (doc: Doc) => boolean | undefined;
+    dontCenter?: 'x' | 'y' | 'xy' | undefined;
     searchFilterDocs: () => Doc[];
     showTitle?: () => string;
     whenChildContentsActiveChanged: (isActive: boolean) => void;
-- 
cgit v1.2.3-70-g09d2


From 4e0ea65c08ff07429cb32f3907268206c80889fa Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 17 Sep 2024 22:11:22 -0400
Subject: linted cardView files after merge.

---
 src/client/apis/gpt/GPT.ts             |  16 +-
 src/client/views/DocumentButtonBar.tsx |  51 ++---
 src/client/views/FilterPanel.tsx       | 352 ++++++++++++++++-----------------
 src/client/views/StyleProvider.tsx     |  10 +-
 src/client/views/nodes/FieldView.tsx   |   4 +-
 5 files changed, 208 insertions(+), 225 deletions(-)

(limited to 'src/client/views/nodes/FieldView.tsx')

diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts
index 2657bf12e..5be9d84ff 100644
--- a/src/client/apis/gpt/GPT.ts
+++ b/src/client/apis/gpt/GPT.ts
@@ -1,4 +1,4 @@
-import { ChatCompletionMessageParam } from 'openai/resources';
+import { ChatCompletionMessageParam, Image } from 'openai/resources';
 import { openai } from './setup';
 
 enum GPTCallType {
@@ -15,7 +15,7 @@ enum GPTCallType {
     RUBRIC = 'rubric',
     TYPE = 'type',
     SUBSET = 'subset',
-    INFO = 'info'
+    INFO = 'info',
 }
 
 type GPTCallOpts = {
@@ -48,7 +48,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = {
         model: 'gpt-4o',
         maxTokens: 2048,
         temp: 0.25,
-        prompt: "The user is going to give you a list of descriptions. Each one is separated by `======` on either side. Descriptions will vary in length, so make sure to only separate when you see `======`. Sort them by the user's specifications. Make sure each description is only in the list once. Each item should be separated by `======`. Immediately afterward, surrounded by `------` on BOTH SIDES, provide some insight into your reasoning for the way you sorted (and mention nothing about the formatting details given in this description). It is VERY important that you format it exactly as described, ensuring the proper number of `=` and `-` (6 of each) and NO commas"
+        prompt: "The user is going to give you a list of descriptions. Each one is separated by `======` on either side. Descriptions will vary in length, so make sure to only separate when you see `======`. Sort them by the user's specifications. Make sure each description is only in the list once. Each item should be separated by `======`. Immediately afterward, surrounded by `------` on BOTH SIDES, provide some insight into your reasoning for the way you sorted (and mention nothing about the formatting details given in this description). It is VERY important that you format it exactly as described, ensuring the proper number of `=` and `-` (6 of each) and NO commas",
     },
     describe: { model: 'gpt-4-vision-preview', maxTokens: 2048, temp: 0, prompt: 'Describe these images in 3-5 words' },
     chatcard: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'Answer the following question as a short flashcard response. Do not include a label.' },
@@ -77,17 +77,15 @@ const callTypeMap: { [type: string]: GPTCallOpts } = {
         model: 'gpt-4-turbo',
         maxTokens: 1024,
         temp: 0,
-        prompt: "I'm going to give you a list of descriptions. Each one is separated by `======` on either side. Descriptions will vary in length, so make sure to only separate when you see `======`. Based on the question the user asks, provide a subset of the given descriptions that best matches the user's specifications. Make sure each description is only in the list once. Each item should be separated by `======`. Immediately afterward, surrounded by `------` on BOTH SIDES, provide some insight into your reasoning in the 2nd person (and mention nothing about the formatting details given in this description). It is VERY important that you format it exactly as described, ensuring the proper number of `=` and `-` (6 of each) and no commas"
+        prompt: "I'm going to give you a list of descriptions. Each one is separated by `======` on either side. Descriptions will vary in length, so make sure to only separate when you see `======`. Based on the question the user asks, provide a subset of the given descriptions that best matches the user's specifications. Make sure each description is only in the list once. Each item should be separated by `======`. Immediately afterward, surrounded by `------` on BOTH SIDES, provide some insight into your reasoning in the 2nd person (and mention nothing about the formatting details given in this description). It is VERY important that you format it exactly as described, ensuring the proper number of `=` and `-` (6 of each) and no commas",
     },
 
     info: {
         model: 'gpt-4-turbo',
         maxTokens: 1024,
         temp: 0,
-        prompt: "Answer the user's question with a short (<100 word) response. If a particular document is selected I will provide that information (which may help with your response)"
+        prompt: "Answer the user's question with a short (<100 word) response. If a particular document is selected I will provide that information (which may help with your response)",
     },
-
-
 };
 
 let lastCall = '';
@@ -98,7 +96,7 @@ let lastResp = '';
  * @param inputText Text to process
  * @returns AI Output
  */
-const gptAPICall = async (inputTextIn: string, callType: GPTCallType, prompt?: any) => {
+const gptAPICall = async (inputTextIn: string, callType: GPTCallType, prompt?: string) => {
     const inputText = [GPTCallType.SUMMARY, GPTCallType.FLASHCARD, GPTCallType.QUIZ].includes(callType) ? inputTextIn + '.' : inputTextIn;
     const opts: GPTCallOpts = callTypeMap[callType];
     if (lastCall === inputText) return lastResp;
@@ -131,7 +129,7 @@ const gptImageCall = async (prompt: string, n?: number) => {
             n: n ?? 1,
             size: '1024x1024',
         });
-        return response.data.map((data: any) => data.url);
+        return response.data.map((data: Image) => data.url);
         // return response.data.data[0].url;
     } catch (err) {
         console.error(err);
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index ccde1de80..87dd5f45a 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -298,16 +298,12 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (
                             key={icon.toString()}
                             size="sm"
                             icon={icon}
-                            onClick={e => {
-                                if (name === 'tags'){
-                                    (targetDoc && (targetDoc[DocData].showIconTags = !targetDoc[DocData].showIconTags))
+                            onClick={() => {
+                                if (name === 'tags') {
+                                    targetDoc && (targetDoc[DocData].showIconTags = !targetDoc[DocData].showIconTags);
                                 } else {
-                                    (targetDoc && (targetDoc[DocData].showLabels = !targetDoc[DocData].showLabels))
+                                    targetDoc && (targetDoc[DocData].showLabels = !targetDoc[DocData].showLabels);
                                 }
-
-
-
-                               
                             }}
                         />
                     </div>
@@ -315,31 +311,24 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (
             );
         };
 
-
-
-
         return !targetDoc ? null : (
-            <div className='documentButtonBar-icon'>
-            <div className="documentButtonBar-pinTypes" style = {{width: '40px'}}>
-                {metaBtn('tags', 'star')}
-                {metaBtn("keywords", 'id-card')}
-             </div>
-
-            <Tooltip title={<div className="dash-keyword-button">Open keyword menu</div>}>
-                <div
-                    className="documentButtonBar-icon"
-                    style={{ color: 'white' }}
-                    onClick={() => {
-                        // targetDoc[DocData].showIconTags = !targetDoc[DocData].showIconTags;
-                    }}
-                    >
-
-                   
-                    <FontAwesomeIcon className="documentdecorations-icon" icon="tag" />
+            <div className="documentButtonBar-icon">
+                <div className="documentButtonBar-pinTypes" style={{ width: '40px' }}>
+                    {metaBtn('tags', 'star')}
+                    {metaBtn('keywords', 'id-card')}
                 </div>
-            </Tooltip>
-            </div>
 
+                <Tooltip title={<div className="dash-keyword-button">Open keyword menu</div>}>
+                    <div
+                        className="documentButtonBar-icon"
+                        style={{ color: 'white' }}
+                        onClick={() => {
+                            // targetDoc[DocData].showIconTags = !targetDoc[DocData].showIconTags;
+                        }}>
+                        <FontAwesomeIcon className="documentdecorations-icon" icon="tag" />
+                    </div>
+                </Tooltip>
+            </div>
         );
     }
 
@@ -519,4 +508,4 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (
             </div>
         );
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx
index 8133a4d0d..3795a4a6d 100644
--- a/src/client/views/FilterPanel.tsx
+++ b/src/client/views/FilterPanel.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable react/jsx-props-no-spreading */
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Tooltip } from '@mui/material';
 import { action, computed, makeObservable, observable, ObservableMap } from 'mobx';
@@ -24,14 +23,186 @@ import { DocumentView } from './nodes/DocumentView';
 import { ButtonType } from './nodes/FontIconBox/FontIconBox';
 import { Handle, Tick, TooltipRail, Track } from './nodes/SliderBox-components';
 import { ObservableReactComponent } from './ObservableReactComponent';
+import { IconProp } from '@fortawesome/fontawesome-svg-core';
 
+interface HotKeyButtonProps {
+    hotKey: string;
+    selected?: Doc;
+}
+
+/**
+ * Renders the buttons that correspond to each icon tag in the properties view. Allows users to change the icon,
+ * title, and delete.
+ */
+const HotKeyIconButton: React.FC<HotKeyButtonProps> = observer(({ hotKey /*, selected */ }) => {
+    const state = useLocalObservable(() => ({
+        isActive: false,
+        isEditing: false,
+        myHotKey: hotKey,
+
+        toggleActive() {
+            this.isActive = !this.isActive;
+        },
+        deactivate() {
+            this.isActive = false;
+        },
+        startEditing() {
+            this.isEditing = true;
+        },
+        stopEditing() {
+            this.isEditing = false;
+        },
+        setHotKey(newHotKey: string) {
+            this.myHotKey = newHotKey;
+        },
+    }));
+
+    const panelRef = useRef<HTMLDivElement>(null);
+    const inputRef = useRef<HTMLInputElement>(null);
+
+    const handleClick = () => {
+        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());
+    };
+
+    /**
+     * Updates the list of hotkeys based on the users input. replaces the old title with the new one and then assigns this new
+     * 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]);
+        Doc.UserDoc()[hotKey] = '';
+        myDoc.title = state.myHotKey;
+        myDoc.toolTip = `Click to toggle the ${state.myHotKey}'s group's visibility`;
+    }, '');
+
+    /**
+     * Deselects if the user clicks outside the button
+     * @param event
+     */
+    const handleClickOutside = (event: MouseEvent) => {
+        if (panelRef.current && !panelRef.current.contains(event.target as Node)) {
+            state.deactivate();
+            if (state.isEditing) {
+                state.stopEditing();
+
+                updateFromInput();
+            }
+        }
+    };
+
+    useEffect(() => {
+        document.addEventListener('mousedown', handleClickOutside);
+        return () => {
+            document.removeEventListener('mousedown', handleClickOutside);
+        };
+    }, []);
+
+    const iconOpts = ['star', 'heart', 'bolt', 'satellite', 'palette', 'robot', 'lightbulb', 'highlighter', 'book', 'chalkboard'] as IconProp[];
+
+    /**
+     * Panel of icons the user can choose from to represent their tag
+     */
+    const iconPanel = iconOpts.map((icon, i) => (
+        <button
+            key={i}
+            onClick={undoable((e: React.MouseEvent) => {
+                e.stopPropagation;
+                Doc.UserDoc()[hotKey] = icon.toString();
+                myHotKeyDoc().icon = icon.toString();
+            }, '')}
+            className="icon-panel-button">
+            <FontAwesomeIcon icon={icon} color={SnappingManager.userColor} />
+        </button>
+    ));
+
+    /**
+     * Actually renders the buttons
+     */
+
+    return (
+        <div
+            className={`filterHotKey-button`}
+            onClick={e => {
+                e.stopPropagation();
+                state.startEditing();
+                setTimeout(() => inputRef.current?.focus(), 0);
+            }}>
+            <div className={`hotKey-icon-button ${state.isActive ? 'active' : ''}`} ref={panelRef}>
+                <Tooltip title={<div className="dash-tooltip">Click to customize this hotkey&apos;s icon</div>}>
+                    <button
+                        type="button"
+                        className="hotKey-icon"
+                        onClick={(e: React.MouseEvent) => {
+                            e.stopPropagation();
+                            handleClick();
+                        }}>
+                        <FontAwesomeIcon icon={Doc.UserDoc()[hotKey] as IconProp} size="2xl" color={SnappingManager.userColor} />
+                    </button>
+                </Tooltip>
+                {state.isActive && <div className="icon-panel">{iconPanel}</div>}
+            </div>
+            {state.isEditing ? (
+                <input
+                    ref={inputRef}
+                    type="text"
+                    value={state.myHotKey.toUpperCase()}
+                    onChange={e => state.setHotKey(e.target.value)}
+                    onBlur={() => {
+                        state.stopEditing();
+                        updateFromInput();
+                    }}
+                    onKeyDown={e => {
+                        if (e.key === 'Enter') {
+                            state.stopEditing();
+                            updateFromInput();
+                        }
+                    }}
+                    className="hotkey-title-input"
+                />
+            ) : (
+                <p className="hotkey-title">{hotKey.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} />
+            </button>
+        </div>
+    );
+});
 interface filterProps {
     Document: Doc;
 }
 
 @observer
 export class FilterPanel extends ObservableReactComponent<filterProps> {
-    @observable _selectedFacetHeaders = new Set<string>();
+    // eslint-disable-next-line no-use-before-define
     public static Instance: FilterPanel;
 
     constructor(props: filterProps) {
@@ -40,6 +211,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
         FilterPanel.Instance = this;
     }
 
+    @observable _selectedFacetHeaders = new Set<string>();
     /**
      * @returns the relevant doc according to the value of FilterBox._filterScope i.e. either the Current Dashboard or the Current Collection
      */
@@ -263,8 +435,8 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
         const hotKeys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles);
 
         // Selecting a button should make it so that the icon on the top filter panel becomes said icon
-        const buttons = hotKeys.map((hotKey, i) => (
-            <Tooltip key={hotKey} title={<div className="dash-tooltip">Click to customize this hotkey's icon</div>}>
+        const buttons = hotKeys.map(hotKey => (
+            <Tooltip key={hotKey} title={<div className="dash-tooltip">Click to customize this hotkey&apos;s icon</div>}>
                 <HotKeyIconButton hotKey={hotKey} selected={selected} />
             </Tooltip>
         ));
@@ -457,175 +629,3 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
         return undefined;
     }
 }
-
-interface HotKeyButtonProps {
-    hotKey: string;
-    selected?: Doc;
-}
-
-/**
- * Renders the buttons that correspond to each icon tag in the properties view. Allows users to change the icon,
- * title, and delete.
- */
-const HotKeyIconButton: React.FC<HotKeyButtonProps> = observer(({ hotKey, selected }) => {
-    const state = useLocalObservable(() => ({
-        isActive: false,
-        isEditing: false,
-        myHotKey: hotKey,
-
-        toggleActive() {
-            this.isActive = !this.isActive;
-        },
-        deactivate() {
-            this.isActive = false;
-        },
-        startEditing() {
-            this.isEditing = true;
-        },
-        stopEditing() {
-            this.isEditing = false;
-        },
-        setHotKey(newHotKey: string) {
-            this.myHotKey = newHotKey;
-        },
-    }));
-
-    const panelRef = useRef<HTMLDivElement>(null);
-    const inputRef = useRef<HTMLInputElement>(null);
-
-    const handleClick = () => {
-        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());
-    };
-
-    /**
-     * Deselects if the user clicks outside the button
-     * @param event
-     */
-    const handleClickOutside = (event: MouseEvent) => {
-        if (panelRef.current && !panelRef.current.contains(event.target as Node)) {
-            state.deactivate();
-            if (state.isEditing) {
-                state.stopEditing();
-
-                updateFromInput();
-            }
-        }
-    };
-
-    /**
-     * Updates the list of hotkeys based on the users input. replaces the old title with the new one and then assigns this new
-     * 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]);
-        Doc.UserDoc()[hotKey] = '';
-        myDoc.title = state.myHotKey;
-        myDoc.toolTip = `Click to toggle the ${state.myHotKey}'s group's visibility`;
-    }, '');
-
-    useEffect(() => {
-        document.addEventListener('mousedown', handleClickOutside);
-        return () => {
-            document.removeEventListener('mousedown', handleClickOutside);
-        };
-    }, []);
-
-    const iconOpts = ['star', 'heart', 'bolt', 'satellite', 'palette', 'robot', 'lightbulb', 'highlighter', 'book', 'chalkboard'];
-
-    /**
-     * Panel of icons the user can choose from to represent their tag
-     */
-    const iconPanel = iconOpts.map((icon, i) => (
-        <button
-            key={i}
-            onClick={undoable((e: React.MouseEvent) => {
-                e.stopPropagation;
-                Doc.UserDoc()[hotKey] = icon;
-                myHotKeyDoc().icon = icon;
-            }, '')}
-            className="icon-panel-button">
-            <FontAwesomeIcon icon={icon as any} color={SnappingManager.userColor} />
-        </button>
-    ));
-
-    /**
-     * Actually renders the buttons
-     */
-
-    return (
-        <div
-            className={`filterHotKey-button`}
-            onClick={e => {
-                e.stopPropagation();
-                state.startEditing();
-                setTimeout(() => inputRef.current?.focus(), 0);
-            }}>
-            <div className={`hotKey-icon-button ${state.isActive ? 'active' : ''}`} ref={panelRef}>
-                <Tooltip title={<div className="dash-tooltip">Click to customize this hotkey's icon</div>}>
-                    <button
-                        type="button"
-                        className="hotKey-icon"
-                        onClick={(e: React.MouseEvent) => {
-                            e.stopPropagation();
-                            handleClick();
-                        }}>
-                        <FontAwesomeIcon icon={Doc.UserDoc()[hotKey] as any} size="2xl" color={SnappingManager.userColor} />
-                    </button>
-                </Tooltip>
-                {state.isActive && <div className="icon-panel">{iconPanel}</div>}
-            </div>
-            {state.isEditing ? (
-                <input
-                    ref={inputRef}
-                    type="text"
-                    value={state.myHotKey.toUpperCase()}
-                    onChange={e => state.setHotKey(e.target.value)}
-                    onBlur={() => {
-                        state.stopEditing();
-                        updateFromInput();
-                    }}
-                    onKeyDown={e => {
-                        if (e.key === 'Enter') {
-                            state.stopEditing();
-                            updateFromInput();
-                        }
-                    }}
-                    className="hotkey-title-input"
-                />
-            ) : (
-                <p className="hotkey-title">{hotKey.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 any} color={SnappingManager.userColor} />
-            </button>
-        </div>
-    );
-});
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 13fef101a..eb434db40 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -326,7 +326,6 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
                             type={Type.TERT}
                             dropdownType={DropdownType.CLICK}
                             fillWidth
-                            // eslint-disable-next-line react/no-unstable-nested-components
                             iconProvider={() => <div className='styleProvider-filterShift'><FaFilter/></div>}
                             closeOnSelect
                             setSelectedVal={((dvValue: unknown) => {
@@ -366,12 +365,9 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
                     </Tooltip>
                 );
             };
-            const tags = () => props?.DocumentView?.() ? <TagsView Views={[props.DocumentView()]}/> :  null;
-
-            const iconTags = () => {
-                if (doc && doc![DocData].showIconTags)
-                    {return (<IconTagBox doc= {doc}></IconTagBox>)}
-            }
+            const tags = () => docView?.() ? <TagsView Views={[docView?.()]}/> :  null;
+            const iconTags = () => doc?.[DocData].showIconTags ? <IconTagBox doc= {doc}/> : null;
+        
             return (
                 <>
                     {paint()}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index c269c7bcb..683edba16 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable react/no-unused-prop-types */
-/* eslint-disable react/require-default-props */
 import { Property } from 'csstype';
 import { computed } from 'mobx';
 import { observer } from 'mobx-react';
@@ -21,6 +19,7 @@ export type FocusFuncType = (doc: Doc, options: FocusViewOptions) => Opt<number>
 // eslint-disable-next-line no-use-before-define
 export type StyleProviderFuncType = (
     doc: Opt<Doc>,
+    // eslint-disable-next-line no-use-before-define
     props: Opt<FieldViewProps>,
     property: string
 ) =>
@@ -65,6 +64,7 @@ export interface FieldViewSharedProps {
     containerViewPath?: () => DocumentView[];
     fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _freeform_fitContentsToBox property on a Document
     isGroupActive?: () => string | undefined; // is this document part of a group that is active
+    // eslint-disable-next-line no-use-before-define
     setContentViewBox?: (view: ViewBoxInterface<FieldViewProps>) => void; // called by rendered field's viewBox so that DocumentView can make direct calls to the viewBox
     PanelWidth: () => number;
     PanelHeight: () => number;
-- 
cgit v1.2.3-70-g09d2

