aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/KeywordBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/KeywordBox.tsx')
-rw-r--r--src/client/views/KeywordBox.tsx197
1 files changed, 158 insertions, 39 deletions
diff --git a/src/client/views/KeywordBox.tsx b/src/client/views/KeywordBox.tsx
index d94f011f4..321362299 100644
--- a/src/client/views/KeywordBox.tsx
+++ b/src/client/views/KeywordBox.tsx
@@ -2,17 +2,26 @@ import { Colors, IconButton } from 'browndash-components';
import { action, computed, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import React from 'react';
-import { Doc } from '../../fields/Doc';
+import { returnFalse, setupMoveUpEvents } from '../../ClientUtils';
+import { Doc, DocListCast } from '../../fields/Doc';
import { DocData } from '../../fields/DocSymbols';
import { List } from '../../fields/List';
+import { DocCast, NumCast } from '../../fields/Types';
+import { emptyFunction } from '../../Utils';
+import { Docs } from '../documents/Documents';
+import { DocUtils } from '../documents/DocUtils';
import { DragManager, SetupDrag } from '../util/DragManager';
import { SnappingManager } from '../util/SnappingManager';
+import { CollectionFreeFormView } from './collections/collectionFreeForm';
+import { MainView } from './MainView';
import { DocumentView } from './nodes/DocumentView';
import { ObservableReactComponent } from './ObservableReactComponent';
interface KeywordItemProps {
doc: Doc;
- label: string;
+ keyword: string;
+ keywordDoc: Doc;
+ keywordCollection: Doc[];
setToEditing: () => void;
isEditing: boolean;
}
@@ -25,28 +34,77 @@ export class KeywordItem extends ObservableReactComponent<KeywordItemProps> {
this.ref = React.createRef();
}
- private _dropDisposer?: DragManager.DragDropDisposer;
private ref: React.RefObject<HTMLDivElement>;
- protected createDropTarget = (ele: HTMLDivElement) => {
- this._dropDisposer?.();
- SetupDrag(this.ref, () => undefined);
- //ele && (this._dropDisposer = DragManager. (ele, this.onInternalDrop.bind(this), this.layoutDoc));
- //ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc));
+ getKeywordCollectionDocs = () => {
+ for (const doc of DocListCast(Doc.UserDoc().myKeywordCollections)) {
+ if (doc.title === this._props.keyword) {
+ return doc[DocData].docs;
+ }
+ }
+ return null;
+ };
+
+ createCollection = () => {
+ const selected = DocListCast(this.getKeywordCollectionDocs()!);
+ const newEmbeddings = selected.map(doc => Doc.MakeEmbedding(doc));
+ const newCollection = ((doc: Doc) => {
+ const docData = doc[DocData];
+ docData.data = new List<Doc>(newEmbeddings);
+ docData.title = this._props.keyword;
+ doc._freeform_panX = doc._freeform_panY = 0;
+ return doc;
+ })(Doc.MakeCopy(Doc.UserDoc().emptyCollection as Doc, true));
+ newEmbeddings.forEach(embed => (embed.embedContainer = newCollection));
+ newCollection._width = 900;
+ newCollection._height = 900;
+ newCollection.layout_fitWidth = true;
+ //newCollection[DocData].smartCollection = this._props.keywordDoc;
+
+ this._props.keywordDoc.collections = new List<Doc>([...DocListCast(this._props.keywordDoc.collections), newCollection]);
+ return newCollection;
+ };
+
+ @action
+ handleDragStart = (e: React.PointerEvent) => {
+ if (this._props.isEditing) {
+ const clone = this.ref.current?.cloneNode(true) as HTMLElement;
+ if (!clone) return;
+
+ 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();
+ }
};
@action
removeLabel = () => {
if (this._props.doc[DocData].data_labels) {
- this._props.doc[DocData].data_labels = (this._props.doc[DocData].data_labels as List<string>).filter(label => label !== this._props.label) as List<string>;
- this._props.doc![DocData][`${this._props.label}`] = false;
+ const filtered_docs = new List<Doc>(DocListCast(this.getKeywordCollectionDocs()!).filter(doc => doc !== this._props.doc));
+ this._props.keywordDoc[DocData].docs = filtered_docs;
+
+ this._props.doc[DocData].data_labels = (this._props.doc[DocData].data_labels as List<string>).filter(label => label !== this._props.keyword) as List<string>;
+ this._props.doc![DocData][`${this._props.keyword}`] = false;
+
+ for (const collection of DocListCast(this._props.keywordDoc.collections)) {
+ collection[DocData].data = new List<Doc>(DocListCast(collection[DocData].data).filter(doc => !Doc.AreProtosEqual(this._props.doc, doc)));
+ }
}
};
render() {
return (
- <div className="keyword" onClick={this._props.setToEditing} onPointerDown={() => {}} ref={this.ref}>
- {this._props.label}
+ <div className="keyword" onClick={this._props.setToEditing} onPointerDown={this.handleDragStart} ref={this.ref}>
+ {this._props.keyword}
{this.props.isEditing && <IconButton tooltip={'Remove label'} onPointerDown={this.removeLabel} icon={'X'} style={{ width: '8px', height: '8px', marginLeft: '10px' }} />}
</div>
);
@@ -61,31 +119,39 @@ interface KeywordBoxProps {
@observer
export class KeywordBox extends ObservableReactComponent<KeywordBoxProps> {
@observable _currentInput: string = '';
- //private disposer: () => void;
+ private height: number = 0;
+ private ref: React.RefObject<HTMLDivElement>;
+
+ @computed
+ get currentScale() {
+ return NumCast((this._props.doc.embedContainer as Doc)?._freeform_scale, 1);
+ }
constructor(props: any) {
super(props);
makeObservable(this);
+ this.ref = React.createRef();
}
- // componentDidMount(): void {
- // reaction(
- // () => ({
- // isDragging: SnappingManager.IsDragging,
- // selectedDoc: DocumentView.SelectedDocs().lastElement(),
- // isEditing: this._props.isEditing,
- // }),
- // ({ isDragging, selectedDoc, isEditing }) => {
- // if (isDragging || selectedDoc !== this._props.doc || !isEditing) {
- // this.setToView();
- // }
- // }
- // );
- // }
-
- // componentWillUnmount() {
- // this.disposer();
- // }
+ componentDidMount(): void {
+ this.height = this.ref.current?.getBoundingClientRect().height ? this.ref.current?.getBoundingClientRect().height : 0;
+ this._props.doc._keywordHeight = this.height;
+
+ reaction(
+ () => this.currentScale,
+ () => {
+ if (this.currentScale < 1) {
+ this.height = this.ref.current?.getBoundingClientRect().height ? this.ref.current?.getBoundingClientRect().height : 0;
+ this._props.doc._keywordHeight = this.height;
+ }
+ }
+ );
+ }
+
+ componentDidUpdate(prevProps: Readonly<KeywordBoxProps>): void {
+ this.height = this.ref.current?.getBoundingClientRect().height ? this.ref.current?.getBoundingClientRect().height : 0;
+ this._props.doc._keywordHeight = this.height;
+ }
@action
setToEditing = () => {
@@ -97,14 +163,51 @@ export class KeywordBox extends ObservableReactComponent<KeywordBoxProps> {
this._props.isEditing = false;
};
+ getKeywordCollection = (keyword: string) => {
+ for (const doc of DocListCast(Doc.UserDoc().myKeywordCollections)) {
+ if (doc.title === keyword) {
+ return doc;
+ }
+ }
+
+ const keywordCollection = new Doc();
+ keywordCollection.title = keyword;
+ keywordCollection[DocData].docs = new List<Doc>();
+ keywordCollection.collections = new List<Doc>();
+ Doc.UserDoc().myKeywordCollections = new List<Doc>([...DocListCast(Doc.UserDoc().myKeywordCollections), keywordCollection]);
+
+ return keywordCollection;
+ };
+
submitLabel = () => {
- if (this._currentInput.trim()) {
+ if (!Doc.UserDoc().myKeywordCollections) {
+ Doc.UserDoc().myKeywordCollections = new List<Doc>();
+ }
+
+ const submittedLabel = this._currentInput.trim();
+ if (submittedLabel) {
+ // If the keyword collection is not in the user doc, add it as a new doc, with the keyword as its title.
+ const keywordCollection = this.getKeywordCollection(submittedLabel);
+
+ // If the document has no keywords field, create the field.
if (!this._props.doc[DocData].data_labels) {
this._props.doc[DocData].data_labels = new List<string>();
}
- (this._props.doc![DocData].data_labels! as List<string>).push(this._currentInput.trim());
+ // Add this document to the keyword's collection of associated documents.
+ keywordCollection[DocData].docs = new List<Doc>([...DocListCast(keywordCollection[DocData].docs), this._props.doc]);
+
+ // Push the keyword to the document's keyword list field.
+ (this._props.doc![DocData].data_labels! as List<string>).push(submittedLabel);
this._props.doc![DocData][`${this._currentInput}`] = true;
+
+ // Iterate through the keyword document's collections and add a copy of the document to each collection
+ for (const collection of DocListCast(keywordCollection.collections)) {
+ const newEmbedding = Doc.MakeEmbedding(this._props.doc);
+ collection[DocData].data = new List<Doc>([...DocListCast(collection.data), newEmbedding]);
+ newEmbedding.embedContainer = collection;
+ }
+
this._currentInput = ''; // Clear the input box
}
};
@@ -120,19 +223,35 @@ export class KeywordBox extends ObservableReactComponent<KeywordBoxProps> {
if (SnappingManager.IsDragging || !(seldoc === this._props.doc) || !this._props.isEditing) {
setTimeout(
action(() => {
- if ((keywordsList as List<string>).length === 0) {
- this._props.doc[DocData].showLabels = false;
- }
+ // if ((keywordsList as List<string>).length === 0) {
+ // this._props.doc[DocData].showLabels = false;
+ // }
this.setToView();
})
);
}
return (
- <div className="keywords-container" style={{ backgroundColor: this._props.isEditing ? Colors.LIGHT_GRAY : Colors.TRANSPARENT, borderColor: this._props.isEditing ? Colors.BLACK : Colors.TRANSPARENT }}>
+ <div
+ className="keywords-container"
+ ref={this.ref}
+ style={{
+ transformOrigin: 'top left',
+ transform: `scale(${1 / this.currentScale})`,
+ backgroundColor: this._props.isEditing ? Colors.LIGHT_GRAY : Colors.TRANSPARENT,
+ borderColor: this._props.isEditing ? Colors.BLACK : Colors.TRANSPARENT,
+ }}>
<div className="keywords-list">
- {(keywordsList as List<string>).map(label => {
- return <KeywordItem doc={this._props.doc} label={label} setToEditing={this.setToEditing} isEditing={this._props.isEditing}></KeywordItem>;
+ {(keywordsList as List<string>).map(keyword => {
+ return (
+ <KeywordItem
+ doc={this._props.doc}
+ keyword={keyword}
+ keywordDoc={this.getKeywordCollection(keyword)}
+ keywordCollection={DocListCast(this.getKeywordCollection(keyword))}
+ setToEditing={this.setToEditing}
+ isEditing={this._props.isEditing}></KeywordItem>
+ );
})}
</div>
{this._props.isEditing ? (