From a52cda0a098716c24b3c6aafe23d2bd9267c72d9 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 26 Aug 2024 10:43:43 -0400
Subject: moved KeywordsBox to TagsView.  changed imagellable to use tags

---
 src/client/views/KeywordBox.tsx | 316 ----------------------------------------
 1 file changed, 316 deletions(-)
 delete mode 100644 src/client/views/KeywordBox.tsx

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

diff --git a/src/client/views/KeywordBox.tsx b/src/client/views/KeywordBox.tsx
deleted file mode 100644
index 841c5394b..000000000
--- a/src/client/views/KeywordBox.tsx
+++ /dev/null
@@ -1,316 +0,0 @@
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Button, Colors, IconButton } from 'browndash-components';
-import { action, computed, makeObservable, observable } from 'mobx';
-import { observer } from 'mobx-react';
-import React from 'react';
-import ResizeObserver from 'resize-observer-polyfill';
-import { returnFalse, setupMoveUpEvents } from '../../ClientUtils';
-import { Utils, emptyFunction } from '../../Utils';
-import { Doc, DocListCast, StrListCast } from '../../fields/Doc';
-import { DocData, KeywordsHeight } from '../../fields/DocSymbols';
-import { List } from '../../fields/List';
-import { NumCast, StrCast } from '../../fields/Types';
-import { DocumentType } from '../documents/DocumentTypes';
-import { DragManager } from '../util/DragManager';
-import { SnappingManager } from '../util/SnappingManager';
-import { undoable } from '../util/UndoManager';
-import { ObservableReactComponent } from './ObservableReactComponent';
-import { DocumentView } from './nodes/DocumentView';
-import { FontIconBox } from './nodes/FontIconBox/FontIconBox';
-
-interface KeywordItemProps {
-    doc: Doc;
-    keyword: string;
-    keywordDoc?: Doc;
-    setToEditing: () => void;
-    isEditing: boolean;
-}
-
-/**
- * A component that handles individual keywords.
- */
-@observer
-export class KeywordItem extends ObservableReactComponent<KeywordItemProps> {
-    /**
-     * return list of all Docs that collect Docs with specified keywords
-     */
-    public static get AllKeywordCollections() {
-        return DocListCast(Doc.ActiveDashboard?.myKeywordCollections);
-    }
-    /**
-     * Find Doc that collects all Docs with given keyword
-     * @param keyword keyword string
-     * @returns keyword collection Doc or undefined
-     */
-    public static findKeywordCollectionDoc = (keyword: String) => KeywordItem.AllKeywordCollections.find(doc => doc.title === keyword);
-
-    /**
-     * Creates a Doc that collects Docs with the specified keyword
-     * @param keyword keyword string
-     * @returns collection Doc
-     */
-    public static createKeywordCollectionDoc = (keyword: string) => {
-        const newKeywordCol = new Doc();
-        newKeywordCol.title = keyword;
-        newKeywordCol.collections = new List<Doc>();
-        newKeywordCol[DocData].docs = new List<Doc>();
-        // If the active Dashboard does not have a keyword collection, create it.
-        if (Doc.ActiveDashboard) {
-            if (!Doc.ActiveDashboard.myKeywordCollections) Doc.ActiveDashboard.myKeywordCollections = new List<Doc>();
-            Doc.AddDocToList(Doc.ActiveDashboard, 'myKeywordCollections', newKeywordCol);
-        }
-
-        return newKeywordCol;
-    };
-    /**
-     * Gets all Docs that have the specified keyword
-     * @param keyword keyword string
-     * @returns An array of documents that contain the keyword.
-     */
-    public static allDocsWithKeyword = (keyword: string) => DocListCast(KeywordItem.findKeywordCollectionDoc(keyword)?.[DocData].docs);
-
-    /**
-     * Adds a keyword to the metadata of this document
-     * @param keyword keyword string
-     */
-    public static addLabelToDoc = (doc: Doc, keyword: string) => {
-        // If the keyword collection is not in active Dashboard, add it as a new doc, with the keyword as its title.
-        const keywordCollection = KeywordItem.findKeywordCollectionDoc(keyword) ?? KeywordItem.createKeywordCollectionDoc(keyword);
-
-        // If the document is of type COLLECTION, make it a smart collection, otherwise, add the keyword to the document.
-        if (doc.type === DocumentType.COL) {
-            Doc.AddDocToList(keywordCollection[DocData], 'collections', doc);
-
-            // Iterate through the keyword Doc collections and add a copy of the document to each collection
-            for (const cdoc of DocListCast(keywordCollection[DocData].docs)) {
-                if (!DocListCast(doc[DocData].data).find(d => Doc.AreProtosEqual(d, cdoc))) {
-                    const newEmbedding = Doc.MakeEmbedding(cdoc);
-                    Doc.AddDocToList(doc[DocData], 'data', newEmbedding);
-                    Doc.SetContainer(newEmbedding, doc);
-                }
-            }
-        } else {
-            // Add this document to the keyword's collection of associated documents.
-            Doc.AddDocToList(keywordCollection[DocData], 'docs', doc);
-
-            // Iterate through the keyword document's collections and add a copy of the document to each collection
-            for (const collection of DocListCast(keywordCollection.collections)) {
-                if (!DocListCast(collection[DocData].data).find(d => Doc.AreProtosEqual(d, doc))) {
-                    const newEmbedding = Doc.MakeEmbedding(doc);
-                    Doc.AddDocToList(collection[DocData], 'data', newEmbedding);
-                    Doc.SetContainer(newEmbedding, collection);
-                }
-            }
-        }
-
-        if (!doc[DocData].tags) doc[DocData].tags = new List<string>();
-        const tagList = doc[DocData].tags as List<string>;
-        if (!tagList.includes(keyword)) tagList.push(keyword);
-    };
-
-    public static RemoveLabel = (doc: Doc, keyword: string, keywordDoc?: Doc) => {
-        if (doc[DocData].tags) {
-            if (doc.type === DocumentType.COL) {
-                keywordDoc && Doc.RemoveDocFromList(keywordDoc[DocData], 'collections', doc);
-
-                for (const cur_doc of KeywordItem.allDocsWithKeyword(keyword)) {
-                    doc[DocData].data = new List<Doc>(DocListCast(doc[DocData].data).filter(d => !Doc.AreProtosEqual(cur_doc, d)));
-                }
-            } else {
-                keywordDoc && Doc.RemoveDocFromList(keywordDoc[DocData], 'docs', doc);
-
-                for (const collection of DocListCast(keywordDoc?.collections)) {
-                    collection[DocData].data = new List<Doc>(DocListCast(collection[DocData].data).filter(d => !Doc.AreProtosEqual(doc, d)));
-                }
-            }
-        }
-        doc[DocData].tags = new List<string>((doc[DocData].tags as List<string>).filter(label => label !== keyword));
-    };
-
-    private _ref: React.RefObject<HTMLDivElement>;
-
-    constructor(props: any) {
-        super(props);
-        makeObservable(this);
-        this._ref = React.createRef();
-    }
-
-    /**
-     * Creates a smart collection.
-     * @returns
-     */
-    createCollection = () => {
-        // Get the documents that contain the keyword.
-        const newEmbeddings = KeywordItem.allDocsWithKeyword(this._props.keyword).map(doc => Doc.MakeEmbedding(doc));
-
-        // Create a new collection and set up configurations.
-        const newCollection = ((doc: Doc) => {
-            const docData = doc[DocData];
-            docData.data = new List<Doc>(newEmbeddings);
-            docData.title = this._props.keyword;
-            docData.tags = new List<string>([this._props.keyword]);
-            docData.showLabels = true;
-            docData.freeform_fitContentsToBox = true;
-            doc._freeform_panX = doc._freeform_panY = 0;
-            doc._width = 900;
-            doc._height = 900;
-            doc.layout_fitWidth = true;
-            return doc;
-        })(Doc.MakeCopy(Doc.UserDoc().emptyCollection as Doc, true));
-        newEmbeddings.forEach(embed => Doc.SetContainer(embed, newCollection));
-
-        // Add the collection to the keyword document's list of associated smart collections.
-        this._props.keywordDoc && Doc.AddDocToList(this._props.keywordDoc, 'collections', newCollection);
-        return newCollection;
-    };
-
-    @action
-    handleDragStart = (e: React.PointerEvent) => {
-        setupMoveUpEvents(
-            this,
-            e,
-            () => {
-                const dragData = new DragManager.DocumentDragData([this.createCollection()]);
-                DragManager.StartDocumentDrag([this._ref.current!], dragData, e.clientX, e.clientY, {});
-                return true;
-            },
-            returnFalse,
-            emptyFunction
-        );
-        e.preventDefault();
-    };
-
-    render() {
-        setTimeout(() => KeywordItem.addLabelToDoc(this._props.doc, this._props.keyword)); // bcz: hack to make sure that Docs are added to their keyword Doc collection since metadata can get set anywhere without a guard triggering an add to the collection
-        const keyword = this._props.keyword.replace(/^#/, '');
-        const metadata = keyword.startsWith('@') ? keyword.replace(/^@/, '') : '';
-        return (
-            <div className="keyword" onClick={this._props.setToEditing} onPointerDown={this.handleDragStart} ref={this._ref} key={Utils.GenerateGuid()}>
-                {metadata ? (
-                    <span>
-                        <b style={{ fontSize: 'smaller' }}>{keyword}&nbsp;</b>
-                        {this._props.doc[metadata] as string}
-                    </span>
-                ) : (
-                    keyword
-                )}
-                {this.props.isEditing && (
-                    <IconButton
-                        tooltip="Remove label"
-                        onPointerDown={undoable(() => KeywordItem.RemoveLabel(this._props.doc, this._props.keyword, this._props.keywordDoc), `remove label ${this._props.keyword}`)}
-                        icon={<FontAwesomeIcon icon="times" size="sm" />}
-                        style={{ width: '8px', height: '8px', marginLeft: '10px' }}
-                    />
-                )}
-            </div>
-        );
-    }
-}
-
-interface KeywordBoxProps {
-    View: DocumentView;
-}
-
-/**
- * A component that handles the keyword display for documents.
- */
-@observer
-export class KeywordBox extends ObservableReactComponent<KeywordBoxProps> {
-    private _ref: React.RefObject<HTMLDivElement>;
-
-    constructor(props: any) {
-        super(props);
-        makeObservable(this);
-        this._ref = React.createRef();
-    }
-
-    @observable _currentInput = '';
-    @observable _isEditing = !StrListCast(this._props.View.dataDoc.tags).length;
-
-    @computed get currentScale() {
-        return NumCast((this._props.View.Document.embedContainer as Doc)?._freeform_scale, 1);
-    }
-    @computed get isEditing() {
-        return this._isEditing && DocumentView.SelectedDocs().includes(this._props.View.Document);
-    }
-
-    @action
-    setToEditing = (editing = true) => {
-        this._isEditing = editing;
-        editing && this._props.View.select(false);
-    };
-
-    /**
-     * Adds the keyword to the document.
-     * @param keyword
-     */
-    submitLabel = undoable((keyword: string) => {
-        const submittedLabel = keyword.trim();
-        submittedLabel && KeywordItem.addLabelToDoc(this._props.View.Document, '#' + submittedLabel.replace(/^#/, ''));
-        this._currentInput = ''; // Clear the input box
-    }, 'added doc label');
-
-    render() {
-        const keywordsList = StrListCast(this._props.View.dataDoc.tags);
-
-        return !this._props.View.Document.showLabels ? null : (
-            <div
-                className="keywords-container"
-                ref={r => r && new ResizeObserver(action(() => (this._props.View.Document[KeywordsHeight] = r?.getBoundingClientRect().height ?? 0))).observe(r)}
-                style={{
-                    transformOrigin: 'top left',
-                    maxWidth: `${100 * this.currentScale}%`,
-                    width: 'max-content',
-                    transform: `scale(${1 / this.currentScale})`,
-                    backgroundColor: this.isEditing ? Colors.LIGHT_GRAY : Colors.TRANSPARENT,
-                    borderColor: this.isEditing ? Colors.BLACK : Colors.TRANSPARENT,
-                }}>
-                <div className="keywords-content" style={{ width: '100%' }}>
-                    <div className="keywords-list">
-                        {!keywordsList.length ? null : ( //
-                            <IconButton style={{ width: '8px' }} tooltip="Close Menu" onPointerDown={() => this.setToEditing(!this._isEditing)} icon={<FontAwesomeIcon icon={this._isEditing ? 'chevron-up' : 'chevron-down'} size="sm" />} />
-                        )}
-                        {keywordsList.map(keyword => (
-                            <KeywordItem key={keyword} doc={this._props.View.Document} keyword={keyword} keywordDoc={KeywordItem.findKeywordCollectionDoc(keyword)} setToEditing={this.setToEditing} isEditing={this.isEditing} />
-                        ))}
-                    </div>
-                    {this.isEditing ? (
-                        <div className="keyword-editing-box">
-                            <div className="keyword-input-box">
-                                <input
-                                    value={this._currentInput}
-                                    autoComplete="off"
-                                    onChange={action(e => (this._currentInput = e.target.value))}
-                                    onKeyDown={e => {
-                                        e.key === 'Enter' ? this.submitLabel(this._currentInput) : null;
-                                        e.stopPropagation();
-                                    }}
-                                    type="text"
-                                    placeholder="Input keywords for document..."
-                                    aria-label="keyword-input"
-                                    className="keyword-input"
-                                    style={{ width: '100%', borderRadius: '5px' }}
-                                />
-                            </div>
-                            <div className="keyword-suggestions-box">
-                                {KeywordItem.AllKeywordCollections.map(doc => {
-                                    const keyword = StrCast(doc.title);
-                                    return (
-                                        <Button
-                                            style={{ margin: '2px 2px', border: '1px solid black', backgroundColor: 'lightblue', color: 'black' }}
-                                            text={keyword}
-                                            color={SnappingManager.userVariantColor}
-                                            tooltip={'Add existing keyword'}
-                                            onClick={() => this.submitLabel(keyword)}
-                                            key={Utils.GenerateGuid()}
-                                        />
-                                    );
-                                })}
-                            </div>
-                        </div>
-                    ) : null}
-                </div>
-            </div>
-        );
-    }
-}
-- 
cgit v1.2.3-70-g09d2

