aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/DocumentButtonBar.tsx10
-rw-r--r--src/client/views/KeywordBox.tsx51
-rw-r--r--src/client/views/StyleProvider.tsx5
-rw-r--r--src/client/views/nodes/formattedText/RichTextRules.ts3
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}&nbsp;</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