diff options
author | bobzel <zzzman@gmail.com> | 2024-08-23 11:50:49 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2024-08-23 11:50:49 -0400 |
commit | dc7bb2ff07139c45efd3bf66ace0042b76c91ccf (patch) | |
tree | 38304ea860618de3759a40b4e086ea247389c74a | |
parent | add4926f62b397fc6c655be31a711dd7b83b469a (diff) |
modified keywordsBox to use tags instead data_labels. made text #tags trigger keywords box. made keywords box fit contents.
-rw-r--r-- | src/client/views/DocumentButtonBar.tsx | 10 | ||||
-rw-r--r-- | src/client/views/KeywordBox.tsx | 51 | ||||
-rw-r--r-- | src/client/views/StyleProvider.tsx | 5 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/RichTextRules.ts | 3 |
4 files changed, 30 insertions, 39 deletions
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index d42a18e4e..eb157b9ab 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -282,15 +282,9 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => ( @computed get keywordButton() { - const targetDoc = this.view0?.Document; - return !targetDoc ? null : ( + return !DocumentView.Selected().length ? null : ( <Tooltip title={<div className="dash-keyword-button">Open keyword menu</div>}> - <div - className="documentButtonBar-icon" - style={{ color: 'white' }} - onClick={() => { - targetDoc[DocData].showLabels = !targetDoc[DocData].showLabels; - }}> + <div className="documentButtonBar-icon" style={{ color: 'white' }} onClick={() => DocumentView.Selected().map(dv => (dv.dataDoc.showLabels = !dv.dataDoc.showLabels))}> <FontAwesomeIcon className="documentdecorations-icon" icon="tag" /> </div> </Tooltip> diff --git a/src/client/views/KeywordBox.tsx b/src/client/views/KeywordBox.tsx index 703299ae6..1460501db 100644 --- a/src/client/views/KeywordBox.tsx +++ b/src/client/views/KeywordBox.tsx @@ -18,7 +18,7 @@ import { ObservableReactComponent } from './ObservableReactComponent'; interface KeywordItemProps { doc: Doc; keyword: string; - keywordDoc: Doc; + keywordDoc?: Doc; setToEditing: () => void; isEditing: boolean; } @@ -100,29 +100,28 @@ export class KeywordItem extends ObservableReactComponent<KeywordItemProps> { } } - if (!doc[DocData].data_labels) doc[DocData].data_labels = new List<string>(); - (doc[DocData].data_labels as List<string>).push(keyword); - doc[DocData][keyword] = true; + 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].data_labels) { + public static RemoveLabel = (doc: Doc, keyword: string, keywordDoc?: Doc) => { + if (doc[DocData].tags) { if (doc.type === DocumentType.COL) { - Doc.RemoveDocFromList(keywordDoc[DocData], 'collections', doc); + 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 { - Doc.RemoveDocFromList(keywordDoc[DocData], 'docs', doc); + keywordDoc && Doc.RemoveDocFromList(keywordDoc[DocData], 'docs', doc); - for (const collection of DocListCast(keywordDoc.collections)) { + 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].data_labels = new List<string>((doc[DocData].data_labels as List<string>).filter(label => label !== keyword)); - doc[DocData][keyword] = undefined; + doc[DocData].tags = new List<string>((doc[DocData].tags as List<string>).filter(label => label !== keyword)); }; private _ref: React.RefObject<HTMLDivElement>; @@ -146,9 +145,9 @@ export class KeywordItem extends ObservableReactComponent<KeywordItemProps> { const docData = doc[DocData]; docData.data = new List<Doc>(newEmbeddings); docData.title = this._props.keyword; - docData.data_labels = new List<string>([this._props.keyword]); - docData[`${this._props.keyword}`] = true; + 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; @@ -158,7 +157,7 @@ export class KeywordItem extends ObservableReactComponent<KeywordItemProps> { newEmbeddings.forEach(embed => Doc.SetContainer(embed, newCollection)); // Add the collection to the keyword document's list of associated smart collections. - Doc.AddDocToList(this._props.keywordDoc, 'collections', newCollection); + this._props.keywordDoc && Doc.AddDocToList(this._props.keywordDoc, 'collections', newCollection); return newCollection; }; @@ -181,14 +180,15 @@ export class KeywordItem extends ObservableReactComponent<KeywordItemProps> { }; render() { - const keyword = this._props.keyword.replace(/^@/, ''); - const metadata = this._props.keyword.startsWith('@'); + 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} </b> - {this._props.doc[keyword] as string} + {this._props.doc[metadata] as string} </span> ) : ( keyword @@ -232,7 +232,7 @@ export class KeywordBox extends ObservableReactComponent<KeywordBoxProps> { } @observable _currentInput = ''; - @observable _isEditing = !StrListCast(this._props.Document[DocData].data_labels).length; + @observable _isEditing = !StrListCast(this._props.Document[DocData].tags).length; @computed get currentScale() { return NumCast((this._props.Document.embedContainer as Doc)?._freeform_scale, 1); @@ -267,14 +267,12 @@ export class KeywordBox extends ObservableReactComponent<KeywordBoxProps> { */ submitLabel = undoable((keyword: string) => { const submittedLabel = keyword.trim(); - if (submittedLabel && !this._props.Document[DocData][submittedLabel]) { - KeywordItem.addLabelToDoc(this._props.Document, submittedLabel); - this._currentInput = ''; // Clear the input box - } + submittedLabel && KeywordItem.addLabelToDoc(this._props.Document, '#' + submittedLabel.replace(/^#/, '')); + this._currentInput = ''; // Clear the input box }, 'added doc label'); render() { - const keywordsList = StrListCast(this._props.Document[DocData].data_labels); + const keywordsList = StrListCast(this._props.Document[DocData].tags); return !this._props.Document.showLabels ? null : ( <div @@ -290,10 +288,9 @@ export class KeywordBox extends ObservableReactComponent<KeywordBoxProps> { }}> <div className="keywords-content" style={{ width: '100%' }}> <div className="keywords-list"> - {keywordsList.map(keyword => { - const keywordDoc = KeywordItem.findKeywordCollectionDoc(keyword); - return !keywordDoc ? null : <KeywordItem key={Utils.GenerateGuid()} doc={this._props.Document} keyword={keyword} keywordDoc={keywordDoc} setToEditing={this.setToEditing} isEditing={this.isEditing} />; - })} + {keywordsList.map(keyword => ( + <KeywordItem key={keyword} doc={this._props.Document} keyword={keyword} keywordDoc={KeywordItem.findKeywordCollectionDoc(keyword)} setToEditing={this.setToEditing} isEditing={this.isEditing} /> + ))} </div> {this.isEditing ? ( <div className="keyword-editing-box"> diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 1e80e7ee5..0fb4f7dd1 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -9,9 +9,7 @@ import { BsArrowDown, BsArrowDownUp, BsArrowUp } from 'react-icons/bs'; import { FaFilter } from 'react-icons/fa'; import { ClientUtils, DashColor, lightOrDark } from '../../ClientUtils'; import { Doc, Opt, StrListCast } from '../../fields/Doc'; -import { DocData } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; -import { List } from '../../fields/List'; import { ScriptField } from '../../fields/ScriptField'; import { BoolCast, Cast, DocCast, ImageCast, NumCast, ScriptCast, StrCast } from '../../fields/Types'; import { AudioAnnoState } from '../../server/SharedMediaTypes'; @@ -22,6 +20,7 @@ import { undoable, UndoManager } from '../util/UndoManager'; import { TreeSort } from './collections/TreeSort'; import { Colors } from './global/globalEnums'; import { KeywordBox } from './KeywordBox'; +import { CollectionFreeFormDocumentView } from './nodes/CollectionFreeFormDocumentView'; import { DocumentView, DocumentViewProps } from './nodes/DocumentView'; import { FieldViewProps } from './nodes/FieldView'; import { StyleProp } from './StyleProp'; @@ -364,7 +363,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps & </Tooltip> ); }; - const keywords = () => doc ? <KeywordBox Document={doc}/> : null; + const keywords = () => doc && CollectionFreeFormDocumentView.from(props?.DocumentView?.()) ? <KeywordBox Document={doc}/> : null; return ( <> {paint()} diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index 39f589b1e..79c118490 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -396,7 +396,7 @@ export class RichTextRules { }), // create an inline view of a tag stored under the '#' field - new InputRule(/#([a-zA-Z_-]+[a-zA-Z_\-0-9]*)\s$/, (state, match, start, end) => { + new InputRule(/#(@?[a-zA-Z_-]+[a-zA-Z_\-0-9]*)\s$/, (state, match, start, end) => { const tag = match[1]; if (!tag) return state.tr; // this.Document[DocData]['#' + tag] = '#' + tag; @@ -404,6 +404,7 @@ export class RichTextRules { if (!tags.includes(tag)) { tags.push(tag); this.Document[DocData].tags = new List<string>(tags); + this.Document[DocData].showLabels = true; } const fieldView = state.schema.nodes.dashField.create({ fieldKey: '#' + tag }); return state.tr |