aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/DictationButton.tsx33
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx53
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx536
-rw-r--r--src/client/views/nodes/ImageBox.tsx1
-rw-r--r--src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss1
-rw-r--r--src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx53
-rw-r--r--src/client/views/nodes/chatbot/tools/DocumentMetadataTool.ts15
-rw-r--r--src/client/views/nodes/chatbot/utils/AgentDocumentManager.ts86
-rw-r--r--src/client/views/pdf/GPTPopup/GPTPopup.tsx27
9 files changed, 425 insertions, 380 deletions
diff --git a/src/client/views/DictationButton.tsx b/src/client/views/DictationButton.tsx
index fc3165f67..882e857c5 100644
--- a/src/client/views/DictationButton.tsx
+++ b/src/client/views/DictationButton.tsx
@@ -1,9 +1,10 @@
-import { makeObservable, observable, action } from 'mobx';
+import { Toggle, ToggleType } from '@dash/components';
+import { action, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import './DictationButton.scss';
import { DictationManager } from '../util/DictationManager';
import { SnappingManager } from '../util/SnappingManager';
+import './DictationButton.scss';
export interface DictationButtonProps {
setInput: (val: string) => void;
@@ -26,9 +27,21 @@ export class DictationButton extends React.Component<DictationButtonProps> {
render() {
return (
- <button
- className={`dictation-button ${this._isRecording ? 'recording' : ''}`}
- title="Record"
+ <Toggle
+ // className={`dictation-button ${this._isRecording ? 'recording' : ''}`}
+ // title="Record"
+ tooltip={`Dictation: ${this._isRecording ? 'on' : 'off'}`}
+ icon={
+ <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+ <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path>
+ <path d="M19 10v2a7 7 0 0 1-14 0v-2"></path>
+ <line x1="12" y1="19" x2="12" y2="23"></line>
+ <line x1="8" y1="23" x2="16" y2="23"></line>
+ </svg>
+ }
+ color={SnappingManager.userVariantColor}
+ toggleType={ToggleType.BUTTON}
+ toggleStatus={this._isRecording}
onClick={action(() => {
if (!this._isRecording) {
this._isRecording = true;
@@ -49,14 +62,8 @@ export class DictationButton extends React.Component<DictationButtonProps> {
} else {
this.stopDictation();
}
- })}>
- <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
- <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path>
- <path d="M19 10v2a7 7 0 0 1-14 0v-2"></path>
- <line x1="12" y1="19" x2="12" y2="23"></line>
- <line x1="8" y1="23" x2="16" y2="23"></line>
- </svg>
- </button>
+ })}
+ />
);
}
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx
index 8ed3e8e30..48cab9c7b 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx
@@ -3,16 +3,24 @@ import { IReactionDisposer, action, makeObservable, observable, reaction } from
import { observer } from 'mobx-react';
import * as React from 'react';
import { SettingsManager } from '../../../util/SettingsManager';
+import { ButtonType } from '../../nodes/FontIconBox/FontIconBox';
import { ObservableReactComponent } from '../../ObservableReactComponent';
import './CollectionFreeFormView.scss';
-import { Button } from '../../../util/CurrentUserUtils';
+export interface InfoButton {
+ targetState?: infoState;
+ // DocumentOptions fields a button can set
+ title?: string;
+ toolTip?: string;
+ btnType?: ButtonType;
+ // fields that do not correspond to DocumentOption fields
+ scripts?: { script?: string; onClick?: string; onDoubleClick?: string };
+}
/**
* An Fsa Arc. The first array element is a test condition function that will be observed.
* The second array element is a function that will be invoked when the first test function
* returns a truthy value
*/
-// eslint-disable-next-line no-use-before-define
export type infoArc = [() => unknown, (res?: unknown) => infoState];
export const StateMessage = Symbol('StateMessage');
@@ -22,19 +30,13 @@ export const StateMessageButton = Symbol('StateMessageButton');
export class infoState {
[StateMessage]: string = '';
[StateMessageGIF]?: string = '';
- [StateMessageButton]?: Button[];
+ [StateMessageButton]?: InfoButton[];
[StateEntryFunc]?: () => unknown;
[key: string]: infoArc;
- constructor(
- message: string,
- arcs: { [key: string]: infoArc },
- messageGif?: string,
- buttons?: Button[],
- entryFunc?: () => unknown
- ) {
+ constructor(message: string, arcs?: { [key: string]: infoArc }, messageGif?: string, buttons?: InfoButton[], entryFunc?: () => unknown) {
this[StateMessage] = message;
- Object.assign(this, arcs);
+ Object.assign(this, arcs ?? {});
this[StateMessageGIF] = messageGif;
this[StateEntryFunc] = entryFunc;
this[StateMessageButton] = buttons;
@@ -53,9 +55,9 @@ export class infoState {
*/
export function InfoState(
msg: string, //
- arcs: { [key: string]: infoArc },
+ arcs?: { [key: string]: infoArc },
gif?: string,
- button?: Button[],
+ button?: InfoButton[],
entryFunc?: () => unknown
) {
return new infoState(msg, arcs, gif, button, entryFunc);
@@ -63,7 +65,7 @@ export function InfoState(
export interface CollectionFreeFormInfoStateProps {
infoState: infoState;
- next: (state: infoState) => unknown; // Ensure it's properly defined
+ next: (state: infoState) => unknown; // Ensure it's properly defined
close: () => void;
}
@@ -114,8 +116,8 @@ export class CollectionFreeFormInfoState extends ObservableReactComponent<Collec
render() {
const gif = this.State?.[StateMessageGIF];
const buttons = this.State?.[StateMessageButton];
- console.log("Rendering CollectionFreeFormInfoState with state:", this.props.infoState);
- console.log(buttons)
+ console.log('Rendering CollectionFreeFormInfoState with state:', this.props.infoState);
+ console.log(buttons);
return (
<div className="collectionFreeform-infoUI">
<p className="collectionFreeform-infoUI-msg">
@@ -129,11 +131,11 @@ export class CollectionFreeFormInfoState extends ObservableReactComponent<Collec
{this._expanded ? 'Less...' : 'More...'}
</button>
</p>
-
+
<div className={'collectionFreeform-' + (!this._expanded || !gif ? 'hidden' : 'infoUI-gif-container')}>
<img src={`/assets/${gif}`} alt="state message gif" />
</div>
-
+
{/* Render the buttons for skipping */}
<div className={'collectionFreeform-' + (!buttons || buttons.length === 0 ? 'hidden' : 'infoUI-button-container')}>
{buttons?.map((button, index) => (
@@ -142,23 +144,16 @@ export class CollectionFreeFormInfoState extends ObservableReactComponent<Collec
type="button"
className="collectionFreeform-infoUI-skip-button"
onClick={action(() => {
- console.log("Attempting transition to:", button.targetState);
+ console.log('Attempting transition to:', button.targetState);
this.props.next(button.targetState as infoState); // ✅ Use the prop instead
- })}>
+ })}>
{button.title}
</button>
))}
</div>
-
+
<div className="collectionFreeform-infoUI-close">
- <IconButton
- icon="x"
- color={SettingsManager.userColor}
- size={Size.XSMALL}
- type={Type.TERT}
- background={SettingsManager.userBackgroundColor}
- onClick={action(() => this.props.close())}
- />
+ <IconButton icon="x" color={SettingsManager.userColor} size={Size.XSMALL} type={Type.TERT} background={SettingsManager.userBackgroundColor} onClick={action(() => this.props.close())} />
</div>
</div>
);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx
index efc22f523..147c900be 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx
@@ -1,17 +1,13 @@
-import { makeObservable, observable, runInAction } from 'mobx';
+import { action, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Doc } from '../../../../fields/Doc';
-import { ObservableReactComponent } from '../../ObservableReactComponent';
-import { CollectionFreeFormInfoState, infoState } from './CollectionFreeFormInfoState';
-import { Button } from '../../../util/CurrentUserUtils';
-import { InfoState } from './CollectionFreeFormInfoState';
-import { DocButtonState } from '../../nodes/DocumentLinksButton';
-import { InkTool } from '../../../../fields/InkField';
-import { DocumentLinksButton } from '../../nodes/DocumentLinksButton';
import { CollectionFreeFormView } from '.';
-import { DocListCast } from '../../../../fields/Doc';
+import { Doc, DocListCast } from '../../../../fields/Doc';
+import { InkTool } from '../../../../fields/InkField';
+import { DocButtonState, DocumentLinksButton } from '../../nodes/DocumentLinksButton';
import { ButtonType } from '../../nodes/FontIconBox/FontIconBox';
+import { ObservableReactComponent } from '../../ObservableReactComponent';
+import { CollectionFreeFormInfoState, InfoButton, infoState, InfoState } from './CollectionFreeFormInfoState';
export interface CollectionFreeFormInfoUIProps {
Document: Doc;
@@ -22,28 +18,19 @@ export interface CollectionFreeFormInfoUIProps {
@observer
export class CollectionFreeFormInfoUI extends ObservableReactComponent<CollectionFreeFormInfoUIProps> {
- _originalBackground: string | undefined;
- private tutorialStates: { [key: string]: infoState } = {};
+ private _originalBackground: string | undefined;
+ private _tutorialStates: { [key: string]: infoState } = {};
public static Init() {
- CollectionFreeFormView.SetInfoUICreator(
- (doc: Doc, layout: Doc, childDocs: () => Doc[], close: () => void) =>
- <CollectionFreeFormInfoUI
- Document={doc}
- LayoutDoc={layout}
- childDocs={childDocs}
- close={close}
- />
- );
+ CollectionFreeFormView.SetInfoUICreator((doc: Doc, layout: Doc, childDocs: () => Doc[], close: () => void) => <CollectionFreeFormInfoUI Document={doc} LayoutDoc={layout} childDocs={childDocs} close={close} />);
}
constructor(props: CollectionFreeFormInfoUIProps) {
super(props);
makeObservable(this);
- this.tutorialStates = {}; // Initialize an empty object
+ this._tutorialStates = {}; // Initialize an empty object
this.currState = this.setupStates(); // Call setupStates() here
}
-
@observable _currState: infoState | undefined = undefined;
@observable _nextState: infoState | undefined = undefined; // Track next state
@@ -51,52 +38,47 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
get currState() {
return this._currState;
}
-
+
set currState(val) {
- runInAction(() => {
- this._currState = val;
- });
+ runInAction(() => (this._currState = val));
}
- componentWillUnmount(): void {
+ componentWillUnmount() {
this._props.Document.backgroundColor = this._originalBackground;
}
- skipToState = (newState: infoState) => {
- runInAction(() => {
- if (!this._currState) {
- this._currState = newState; // Assign directly if undefined
- } else {
- this._currState = newState;
- }
- });
- };
+ skipToState = action((newState: infoState) => (this._currState = newState));
createNextButton = (newState: ReturnType<typeof InfoState>) => {
return {
- title: "Next",
- toolTip: "Next",
+ title: 'Next',
+ toolTip: 'Next',
btnType: ButtonType.ClickButton,
scripts: {
- onClick: `this.skipToState(${newState})`
+ onClick: `this.skipToState(${newState})`,
},
- targetState: newState
+ targetState: newState,
};
};
setupStates = () => {
let docCounter = this._props.childDocs().length;
- let lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1]
+ let lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1];
let linkCounter = Doc.Links(lastDocCreated)?.length;
- let presentationCounter = DocListCast(Doc.ActivePresentation?.data).length
+ let presentationCounter = DocListCast(Doc.ActivePresentation?.data).length;
this._originalBackground = this._props.Document.backgroundColor as string;
-
- this.tutorialStates.multipleDocs = InfoState("Let's create a new link! Click the link icon on one document and connect it to another.", {
- // eslint-disable-next-line no-use-before-define
- linkStarted: [() => DocumentLinksButton.StartLink, () => {
- linkCounter = Doc.Links(lastDocCreated).length
- // eslint-disable-next-line no-use-before-define
- return startedLink}],
+
+ this._tutorialStates.multipleDocs = InfoState(
+ "Let's create a new link! Click the link icon on one document and connect it to another.",
+ {
+ linkStarted: [
+ () => DocumentLinksButton.StartLink,
+ () => {
+ linkCounter = Doc.Links(lastDocCreated).length;
+ // eslint-disable-next-line no-use-before-define
+ return startedLink;
+ },
+ ],
// docCreated: [() => this._props.childDocs().length > docCounter, () => {
// docCounter += 1
// lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1]
@@ -106,238 +88,306 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
'dash-create-link-board.gif'
);
- this.tutorialStates.presentDocs = InfoState("Select a document then click the 'pin' button in the top left to create your presentation.", {
- // eslint-disable-next-line no-use-before-define
- docPinned: [() => DocListCast(Doc.ActivePresentation?.data).length > presentationCounter, () => {
- presentationCounter++
- // eslint-disable-next-line no-use-before-define
- return pinnedDoc}],
+ this._tutorialStates.presentDocs = InfoState(
+ "Select a document then click the 'pin' button in the top left to create your presentation.",
+ {
+ docPinned: [
+ () => DocListCast(Doc.ActivePresentation?.data).length > presentationCounter,
+ () => {
+ presentationCounter++;
+ // eslint-disable-next-line no-use-before-define
+ return pinnedDoc;
+ },
+ ],
},
- 'pin-explanation.gif');
-
- this.tutorialStates.nestedCollections = InfoState("Want to learn how to create a nested collection? Click the : button and add a 'collection' doc", {
- // eslint-disable-next-line no-use-before-define
- docCreated: [() => this._props.childDocs().length > docCounter, () => {
- docCounter += 1
- lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1]
- // eslint-disable-next-line no-use-before-define
- return marqueeSelection}]
- },
- 'dash-nested-collection.gif')
-
-
- this.tutorialStates.makePresentation = InfoState("Add a new document to create a presentation!", {
- docCreated: [() => this._props.childDocs().length > docCounter, () => {
- docCounter += 1
- lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1]
- // eslint-disable-next-line no-use-before-define
- return this.tutorialStates.presentDocs}],
- });
-
- const skipToLinksButton: Button = {
- title: "Links Tutorial",
- toolTip: "Skip",
- btnType: ButtonType.ClickButton,
- scripts: {
- onClick: "this.skipToState(this.tutorialStates.multipleDocs)"
+ 'pin-explanation.gif'
+ );
+
+ this._tutorialStates.nestedCollections = InfoState(
+ "Want to learn how to create a nested collection? Click the : button and add a 'collection' doc",
+ {
+ docCreated: [
+ () => this._props.childDocs().length > docCounter,
+ () => {
+ docCounter += 1;
+ lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1];
+ // eslint-disable-next-line no-use-before-define
+ return marqueeSelection;
+ },
+ ],
},
- targetState: this.tutorialStates.multipleDocs
- };
+ 'dash-nested-collection.gif'
+ );
+
+ this._tutorialStates.makePresentation = InfoState('Add a new document to create a presentation!', {
+ docCreated: [
+ () => this._props.childDocs().length > docCounter,
+ () => {
+ docCounter += 1;
+ lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1];
+ return this._tutorialStates.presentDocs;
+ },
+ ],
+ });
- const skipToPinsButton: Button = {
- title: "Pins Tutorial",
- toolTip: "Skip",
+ const skipToLinksButton: InfoButton = {
+ title: 'Links Tutorial',
+ toolTip: 'Skip',
btnType: ButtonType.ClickButton,
scripts: {
- onClick: "this.skipToState(this.tutorialStates.makePresentation)"
+ onClick: 'this.skipToState(this.tutorialStates.multipleDocs)',
},
- targetState: this.tutorialStates.makePresentation
+ targetState: this._tutorialStates.multipleDocs,
};
- const skipToPresentationButton: Button = {
- title: "Collections Tutorial",
- toolTip: "Skip",
+ const skipToPinsButton: InfoButton = {
+ title: 'Pins Tutorial',
+ toolTip: 'Skip',
btnType: ButtonType.ClickButton,
scripts: {
- onClick: "this.skipToState(this.tutorialStates.nestedCollections)"
+ onClick: 'this.skipToState(this.tutorialStates.makePresentation)',
},
- targetState: this.tutorialStates.nestedCollections
+ targetState: this._tutorialStates.makePresentation,
};
- const ending = InfoState("If you have any more questions, feel free to ask Dash's AI Bot!")
+ // const skipToPresentationButton: Button = {
+ // title: "Collections Tutorial",
+ // toolTip: "Skip",
+ // btnType: ButtonType.ClickButton,
+ // scripts: {
+ // onClick: "this.skipToState(this.tutorialStates.nestedCollections)"
+ // },
+ // targetState: this.tutorialStates.nestedCollections
+ // };
+
+ const ending = InfoState("If you have any more questions, feel free to ask Dash's AI Bot!");
// Traditional tutorial
- const completed = InfoState(
- "Eager to learn more? Click the ? icon in the top right corner to read our full documentation.",
- { docRemoved: [() => this._props.childDocs().length === 1, () => this.tutorialStates.start] },
- 'documentation.png',
- );
+ const completed = InfoState('Eager to learn more? Click the ? icon in the top right corner to read our full documentation.', { docRemoved: [() => this._props.childDocs().length === 1, () => this._tutorialStates.start] }, 'documentation.png');
const penMode = InfoState("You're in pen mode! Click and drag to draw your first masterpiece, then click the Ink button once you're done.", {
activePen: [() => Doc.ActiveTool !== InkTool.Ink, () => completed],
});
-
+
const briefArtisticFeature = InfoState("Finally, want to explore the art feature of Dash? Click the 'Ink' button on the hotbar then click the pen button.", {
penModeActivated: [() => Doc.ActiveTool === InkTool.Ink, () => penMode],
});
-
- const activatePresentation = InfoState("Lastly, click the linked node and start the presentation!", {
- presentation: [() => Doc.ActivePresentation?.presentation_status === "auto", () => briefArtisticFeature],
+
+ const activatePresentation = InfoState('Lastly, click the linked node and start the presentation!', {
+ presentation: [() => Doc.ActivePresentation?.presentation_status === 'auto', () => briefArtisticFeature],
});
-
- const deletePresentation = InfoState("Cool! Click 'setOnClick to follow primary link' for your non-presentation doc and try deleting the presentation.", {
- docRemoved: [() => this._props.childDocs().length < docCounter, () => {
- docCounter -= 1
- return activatePresentation}],
- },
- 'onclick-node.gif');
-
- const trailedPresentation = InfoState("Try linking your presentation to the last doc you created (now highlighted).", {
- linkAdd: [() => Doc.Links(lastDocCreated)?.length > linkCounter, () => {
- linkCounter += 1
- return deletePresentation
- }],
- docAdded: [() => this._props.childDocs().length > docCounter, () => {
- docCounter += 1
- // Last doc that is not the presentation
- lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 2]
- linkCounter = Doc.Links(lastDocCreated)?.length
- return deletePresentation}]
- },
- 'link-presentation.gif');
-
- const pinnedPresentation = InfoState("Want to see something cool? Zoom out, click the trail button on the presentation, and drag it inside the canvas.", {
- docAdded: [() => this._props.childDocs().length > docCounter, () => {
- docCounter += 1
- // Last doc that is not the presentation
- lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 2]
- Doc.HighlightDoc(lastDocCreated)
- linkCounter = Doc.Links(lastDocCreated)?.length
- return trailedPresentation}],
- },
- 'dash-trail-explanation.gif');
-
- const pinnedDoc2 = InfoState("You pinned another doc. Press autoplay to the right to show your presentation!", {
- autoPresentation: [() => Doc.ActivePresentation?.presentation_status === "auto", () => pinnedPresentation],
+
+ const deletePresentation = InfoState(
+ "Cool! Click 'setOnClick to follow primary link' for your non-presentation doc and try deleting the presentation.",
+ {
+ docRemoved: [
+ () => this._props.childDocs().length < docCounter,
+ () => {
+ docCounter -= 1;
+ return activatePresentation;
+ },
+ ],
+ },
+ 'onclick-node.gif'
+ );
+
+ const trailedPresentation = InfoState(
+ 'Try linking your presentation to the last doc you created (now highlighted).',
+ {
+ linkAdd: [
+ () => Doc.Links(lastDocCreated)?.length > linkCounter,
+ () => {
+ linkCounter += 1;
+ return deletePresentation;
+ },
+ ],
+ docAdded: [
+ () => this._props.childDocs().length > docCounter,
+ () => {
+ docCounter += 1;
+ // Last doc that is not the presentation
+ lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 2];
+ linkCounter = Doc.Links(lastDocCreated)?.length;
+ return deletePresentation;
+ },
+ ],
+ },
+ 'link-presentation.gif'
+ );
+
+ const pinnedPresentation = InfoState(
+ 'Want to see something cool? Zoom out, click the trail button on the presentation, and drag it inside the canvas.',
+ {
+ docAdded: [
+ () => this._props.childDocs().length > docCounter,
+ () => {
+ docCounter += 1;
+ // Last doc that is not the presentation
+ lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 2];
+ Doc.HighlightDoc(lastDocCreated);
+ linkCounter = Doc.Links(lastDocCreated)?.length;
+ return trailedPresentation;
+ },
+ ],
+ },
+ 'dash-trail-explanation.gif'
+ );
+
+ const pinnedDoc2 = InfoState('You pinned another doc. Press autoplay to the right to show your presentation!', {
+ autoPresentation: [() => Doc.ActivePresentation?.presentation_status === 'auto', () => pinnedPresentation],
});
- const pinnedDoc = InfoState("You just pinned your doc. Pin another doc to add to the presentation!", {
- // eslint-disable-next-line no-use-before-define
- addedDoc: [() => this._props.childDocs().length > docCounter, () => {
- docCounter += 1
- lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1]
- return pinnedDoc}],
- docPinned: [() => DocListCast(Doc.ActivePresentation?.data).length > presentationCounter, () => {
- presentationCounter++
- // eslint-disable-next-line no-use-before-define
- return pinnedDoc2}],
+ const pinnedDoc = InfoState('You just pinned your doc. Pin another doc to add to the presentation!', {
+ addedDoc: [
+ () => this._props.childDocs().length > docCounter,
+ () => {
+ docCounter += 1;
+ lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1];
+ return pinnedDoc;
+ },
+ ],
+ docPinned: [
+ () => DocListCast(Doc.ActivePresentation?.data).length > presentationCounter,
+ () => {
+ presentationCounter++;
+ return pinnedDoc2;
+ },
+ ],
});
-
- const editLink = InfoState("Want to make your link visible? Click 'show link'.", {
- docCreated: [() => this._props.childDocs().length > docCounter, () => {
- docCounter += 1
- lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1]
- return this.tutorialStates.makePresentation}],
- },
- 'show-link.gif');
-
- const madeLink = InfoState("You made your first link! You can view your links by selecting the blue dot.", {
- linkViewed: [() => DocButtonState.Instance.LinkEditorDocView, () => {
- docCounter = this._props.childDocs().length
- return editLink}],
- },
- 'dash-following-link.gif');
-
- const startedLink = InfoState("Now click the highlighted link icon on your other document.", {
- linkAdd: [() => Doc.Links(lastDocCreated)?.length > linkCounter, () => {
- linkCounter += 1
- return madeLink
- }]
- },
- 'dash-create-link-board.gif');
-
- this.tutorialStates.movedDoc = InfoState("Great moves! Try creating a second document.", {
- docCreated: [() => this._props.childDocs().length > docCounter, () => {
- docCounter += 1
- lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1]
- return this.tutorialStates.multipleDocs}],
- },
- 'dash-colon-menu.gif'); // prettier-ignore
-
- this.tutorialStates.start = InfoState("Welcome to Dash! Click anywhere and begin typing ':' to create your first document.", {
- docCreated: [() => this._props.childDocs().length > docCounter, () => {
- docCounter += 1
- lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1]
- return this.tutorialStates.movedDoc}]
- },
- undefined,
- [skipToLinksButton, skipToPinsButton])
-
+
+ const editLink = InfoState(
+ "Want to make your link visible? Click 'show link'.",
+ {
+ docCreated: [
+ () => this._props.childDocs().length > docCounter,
+ () => {
+ docCounter += 1;
+ lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1];
+ return this._tutorialStates.makePresentation;
+ },
+ ],
+ },
+ 'show-link.gif'
+ );
+
+ const madeLink = InfoState(
+ 'You made your first link! You can view your links by selecting the blue dot.',
+ {
+ linkViewed: [
+ () => DocButtonState.Instance.LinkEditorDocView,
+ () => {
+ docCounter = this._props.childDocs().length;
+ return editLink;
+ },
+ ],
+ },
+ 'dash-following-link.gif'
+ );
+
+ const startedLink = InfoState(
+ 'Now click the highlighted link icon on your other document.',
+ {
+ linkAdd: [
+ () => Doc.Links(lastDocCreated)?.length > linkCounter,
+ () => {
+ linkCounter += 1;
+ return madeLink;
+ },
+ ],
+ },
+ 'dash-create-link-board.gif'
+ );
+
+ this._tutorialStates.movedDoc = InfoState(
+ "Great moves! Try creating a second document.",
+ {
+ docCreated: [
+ () => this._props.childDocs().length > docCounter,
+ () => {
+ docCounter += 1
+ lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1]
+ return this._tutorialStates.multipleDocs
+ }
+ ],
+ },
+ 'dash-colon-menu.gif'); // prettier-ignore
+
+ this._tutorialStates.start = InfoState(
+ "Welcome to Dash! Click anywhere and begin typing ':' to create your first document.",
+ {
+ docCreated: [
+ () => this._props.childDocs().length > docCounter,
+ () => {
+ docCounter += 1;
+ lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1];
+ return this._tutorialStates.movedDoc;
+ },
+ ],
+ },
+ undefined,
+ [skipToLinksButton, skipToPinsButton]
+ );
+
// Information on created nested collections
- const createdMarquee = InfoState("Next, right click and drag a square to create the collection", {
- // eslint-disable-next-line no-use-before-define
- marqueeMade: [() => this._props.childDocs().length < docCounter, () => {
- docCounter -= 1
- return ending}],
- },
- 'dash-create-collection-marquee.gif')
-
- const marqueeSelection = InfoState("Want an easier way to make a collection of docs? First add two docs you want to make a collection of", {
- marqueeMade: [() => this._props.childDocs().length > docCounter, () => {
- docCounter += 1
- lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1]
- return createdMarquee}]
- })
+ const createdMarquee = InfoState(
+ 'Next, right click and drag a square to create the collection',
+ {
+ marqueeMade: [
+ () => this._props.childDocs().length < docCounter,
+ () => {
+ docCounter -= 1;
+ return ending;
+ },
+ ],
+ },
+ 'dash-create-collection-marquee.gif'
+ );
+
+ const marqueeSelection = InfoState('Want an easier way to make a collection of docs? First add two docs you want to make a collection of', {
+ marqueeMade: [
+ () => this._props.childDocs().length > docCounter,
+ () => {
+ docCounter += 1;
+ lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1];
+ return createdMarquee;
+ },
+ ],
+ });
// Explanation of importing
- const easierImport = InfoState("Or, for easier access, you can drag any of the accepted file types from your computer or a webpage and drop it into your dashboard. This includes images, videos, audio, pdfs, and more!", {
- },
- 'dash-',
- [this.createNextButton(ending)])
-
- this.tutorialStates.importFile = InfoState("Want to learn how to import a file? Import using the import menu on the left hand side", {
- },
- 'dash-import.gif',
- [this.createNextButton(easierImport)])
+ const easierImport = InfoState('Or, for easier access, you can drag any of the accepted file types from your computer or a webpage and drop it into your dashboard. This includes images, videos, audio, pdfs, and more!', {}, 'dash-', [
+ this.createNextButton(ending),
+ ]);
+
+ this._tutorialStates.importFile = InfoState('Want to learn how to import a file? Import using the import menu on the left hand side', {}, 'dash-import.gif', [this.createNextButton(easierImport)]);
// Editing documents
// Accessed by right-clicking anywhere on the target document or selecting the three bars menu at the bottom of the document chrome
- const extraContentsOfDoc = InfoState("Lastly, all documents also have a context-sensitive toolbar. The toolbar contents vary depending on the document type.", {
- },
- 'context-toolbar.png',
- [this.createNextButton(ending)])
-
- const contentsofDoc = InfoState("You can access the context of a doc through right-clicking anywhere on the target document or selecting the three bars menu at the bottom of the document chrome", {
- },
- 'dash-context-menu.gif',
- [this.createNextButton(extraContentsOfDoc)])
-
- const propertiesofDoc = InfoState("You can also access the properties of a doc through the double arrows in the top right or the single arrow on the right edge of the screen", {
- },
- 'dash-properties-pane.gif',
- [this.createNextButton(contentsofDoc)])
-
- this.tutorialStates.editingDocuments = InfoState("Want to learn how to edit a document? Either left or right click the document", {
- },
- 'document-chrome.png',
- [this.createNextButton(propertiesofDoc)])
- return this.tutorialStates.start
- };
+ const extraContentsOfDoc = InfoState('Lastly, all documents also have a context-sensitive toolbar. The toolbar contents vary depending on the document type.', {}, 'context-toolbar.png', [this.createNextButton(ending)]);
+
+ const contentsofDoc = InfoState('You can access the context of a doc through right-clicking anywhere on the target document or selecting the three bars menu at the bottom of the document chrome', {}, 'dash-context-menu.gif', [
+ this.createNextButton(extraContentsOfDoc),
+ ]);
+ const propertiesofDoc = InfoState('You can also access the properties of a doc through the double arrows in the top right or the single arrow on the right edge of the screen', {}, 'dash-properties-pane.gif', [
+ this.createNextButton(contentsofDoc),
+ ]);
+
+ this._tutorialStates.editingDocuments = InfoState('Want to learn how to edit a document? Either left or right click the document', {}, 'document-chrome.png', [this.createNextButton(propertiesofDoc)]);
+ return this._tutorialStates.start;
+ };
render() {
- if (!this.currState) return null;
-
- return (
- <CollectionFreeFormInfoState
- next={this.skipToState} // This ensures skipToState is passed correctly
- close={this._props.close}
- infoState={this.currState}
+ return !this.currState ? null : (
+ <CollectionFreeFormInfoState
+ next={this.skipToState} // This ensures skipToState is passed correctly
+ close={this._props.close}
+ infoState={this.currState}
/>
);
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 78bacdcac..fb2346bd1 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -49,7 +49,6 @@ import { gptImageLabel } from '../../apis/gpt/GPT';
const DefaultPath = '/assets/unknown-file-icon-hi.png';
export class ImageEditorData {
- // eslint-disable-next-line no-use-before-define
private static _instance: ImageEditorData;
private static get imageData() { return (ImageEditorData._instance ?? new ImageEditorData()).imageData; } // prettier-ignore
@observable imageData: { rootDoc: Doc | undefined; open: boolean; source: string; addDoc: Opt<(doc: Doc | Doc[], annotationKey?: string) => boolean> } = observable({ rootDoc: undefined, open: false, source: '', addDoc: undefined });
diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss
index 4a916e86c..0bacc70c2 100644
--- a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss
+++ b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss
@@ -183,7 +183,6 @@ $font-size-xlarge: 18px;
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.05);
position: relative;
align-items: center;
- gap: 12px;
z-index: 5;
transition: padding 0.2s ease;
diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
index 19459b025..636b77b38 100644
--- a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
+++ b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
@@ -7,10 +7,12 @@
* with support for follow-up questions and citation management.
*/
+import { Button, Size, Type } from '@dash/components';
import { ObservableSet, action, computed, makeObservable, observable, observe, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import OpenAI, { ClientOptions } from 'openai';
import * as React from 'react';
+import { AiOutlineSend } from 'react-icons/ai';
import { v4 as uuidv4 } from 'uuid';
import { ClientUtils, OmitKeys } from '../../../../../ClientUtils';
import { Doc, DocListCast, Opt } from '../../../../../fields/Doc';
@@ -18,7 +20,9 @@ import { DocData, DocViews } from '../../../../../fields/DocSymbols';
import { Id } from '../../../../../fields/FieldSymbols';
import { RichTextField } from '../../../../../fields/RichTextField';
import { ScriptField } from '../../../../../fields/ScriptField';
-import { CsvCast, DocCast, PDFCast, RTFCast, StrCast, VideoCast, AudioCast } from '../../../../../fields/Types';
+import { AudioCast, CsvCast, DocCast, NumCast, PDFCast, RTFCast, StrCast, VideoCast } from '../../../../../fields/Types';
+import { Upload } from '../../../../../server/SharedMediaTypes';
+import { DocServer } from '../../../../DocServer';
import { DocUtils } from '../../../../documents/DocUtils';
import { CollectionViewType, DocumentType } from '../../../../documents/DocumentTypes';
import { Docs, DocumentOptions } from '../../../../documents/Documents';
@@ -26,23 +30,23 @@ import { DocumentManager } from '../../../../util/DocumentManager';
import { ImageUtils } from '../../../../util/Import & Export/ImageUtils';
import { LinkManager } from '../../../../util/LinkManager';
import { CompileError, CompileScript } from '../../../../util/Scripting';
+import { SnappingManager } from '../../../../util/SnappingManager';
import { DictationButton } from '../../../DictationButton';
import { ViewBoxAnnotatableComponent } from '../../../DocComponent';
import { AudioBox } from '../../AudioBox';
import { DocumentView, DocumentViewInternal } from '../../DocumentView';
import { FieldView, FieldViewProps } from '../../FieldView';
+import { OpenWhere } from '../../OpenWhere';
import { PDFBox } from '../../PDFBox';
import { ScriptingBox } from '../../ScriptingBox';
import { VideoBox } from '../../VideoBox';
import { Agent } from '../agentsystem/Agent';
import { supportedDocTypes } from '../types/tool_types';
import { ASSISTANT_ROLE, AssistantMessage, CHUNK_TYPE, Citation, ProcessingInfo, SimplifiedChunk, TEXT_TYPE } from '../types/types';
+import { AgentDocumentManager } from '../utils/AgentDocumentManager';
import { Vectorstore } from '../vectorstore/Vectorstore';
import './ChatBox.scss';
import MessageComponentBox from './MessageComponent';
-import { OpenWhere } from '../../OpenWhere';
-import { Upload } from '../../../../../server/SharedMediaTypes';
-import { AgentDocumentManager } from '../utils/AgentDocumentManager';
export type parsedDocData = {
doc_type: string;
@@ -555,8 +559,8 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
})();
if (ndoc) {
- ndoc.x = NumCast((options.x as number) ?? 0) + (insideCol ? 0 : NumCast(this.layoutDoc.x) + NumCast(this.layoutDoc.width)) + 100;
- ndoc.y = NumCast(options.y as number) + (insideCol ? 0 : NumCast(this.layoutDoc.y));
+ ndoc.x = ((options.x as number) ?? 0) + (insideCol ? 0 : NumCast(this.layoutDoc.x) + NumCast(this.layoutDoc.width)) + 100;
+ ndoc.y = ((options.y as number) ?? 0) + (insideCol ? 0 : NumCast(this.layoutDoc.y));
}
return ndoc;
};
@@ -655,8 +659,8 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
} else {
console.warn(`Chunk not found for chunk ID: ${chunkId}`);
}
- return;
- }
+ return;
+ }
console.log(`Found chunk in document:`, foundChunk);
@@ -665,7 +669,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
const directMatchSegmentStart = this.getDirectMatchingSegmentStart(doc, citation.direct_text || '', foundChunk.indexes || []);
if (directMatchSegmentStart) {
await this.goToMediaTimestamp(doc, directMatchSegmentStart, foundChunk.chunkType);
- } else {
+ } else {
console.error('No direct matching segment found for the citation.');
}
} else if (foundChunk.chunkType === CHUNK_TYPE.TABLE || foundChunk.chunkType === CHUNK_TYPE.IMAGE) {
@@ -710,7 +714,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// If specific indexes are provided, filter segments by those indexes
if (indexesOfSegments && indexesOfSegments.length > 0) {
- segments = original_segments.filter((segment: any) => indexesOfSegments.includes(segment.index));
+ segments = original_segments.filter(segment => indexesOfSegments.includes(segment.index));
}
// If no segments match the indexes, use all segments
@@ -719,7 +723,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
// First try to find an exact match
- const exactMatch = segments.find((segment: any) => segment.text && segment.text.includes(citationText));
+ const exactMatch = segments.find(segment => segment.text && segment.text.includes(citationText));
if (exactMatch) {
return exactMatch.start;
@@ -828,7 +832,8 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
existingDoc._width = x2 - x1;
existingDoc._height = y2 - y1;
}
- const highlightDoc = existingDoc ?? this.createImageCitationHighlight(x1, y1, x2, y2, citation, annotationKey, doc);
+ // const highlightDoc =
+ existingDoc ?? this.createImageCitationHighlight(x1, y1, x2, y2, citation, annotationKey, doc);
//doc.layout_scroll = y1;
doc._layout_curPage = foundChunk.startPage + 1;
@@ -922,7 +927,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
console.error(`Maximum verification attempts (${attempt}) reached for document ${doc.id}`);
// Last resort: force re-creation of the document view
- if (isPDF) {
+ if (isPDF) {
console.log('Forcing document recreation as last resort');
DocumentManager.Instance.showDocument(doc, {
willZoomCentered: true,
@@ -950,7 +955,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return;
}
- this.processPDFDocumentView(doc, isPDF, citation, foundChunk);
+ this.processPDFDocumentView(doc, isPDF, citation, foundChunk);
} catch (error) {
console.error(`Error on verification attempt ${attempt}:`, error);
if (attempt < 5) {
@@ -1454,16 +1459,16 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
disabled={this._isLoading}
/>
</div>
- <button className="submit-button" onClick={() => this._dictation?.stopDictation()} type="submit" disabled={this._isLoading || !this._inputValue.trim()}>
- {this._isLoading ? (
- <div className="spinner"></div>
- ) : (
- <svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round">
- <line x1="22" y1="2" x2="11" y2="13"></line>
- <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
- </svg>
- )}
- </button>
+ <Button
+ // className="submit-button"
+ onClick={() => this._dictation?.stopDictation()}
+ type={Type.PRIM}
+ tooltip="Send to AI"
+ color={SnappingManager.userVariantColor}
+ inactive={this._isLoading || !this._inputValue.trim()}
+ icon={<AiOutlineSend />}
+ size={Size.LARGE}
+ />
<DictationButton ref={this.setDictationRef} setInput={this.setChatInput} inputRef={this._textInputRef} />
</form>
{/* Popup for citation */}
diff --git a/src/client/views/nodes/chatbot/tools/DocumentMetadataTool.ts b/src/client/views/nodes/chatbot/tools/DocumentMetadataTool.ts
index a55f901e1..da4a4ae29 100644
--- a/src/client/views/nodes/chatbot/tools/DocumentMetadataTool.ts
+++ b/src/client/views/nodes/chatbot/tools/DocumentMetadataTool.ts
@@ -1,16 +1,7 @@
-import { Doc, FieldType } from '../../../../../fields/Doc';
-import { DocData } from '../../../../../fields/DocSymbols';
+import { Parameter, ParametersType, supportedDocTypes, ToolInfo } from '../types/tool_types';
import { Observation } from '../types/types';
-import { ParametersType, ToolInfo, Parameter } from '../types/tool_types';
-import { BaseTool } from './BaseTool';
-import { DocumentOptions } from '../../../../documents/Documents';
-import { CollectionFreeFormDocumentView } from '../../../nodes/CollectionFreeFormDocumentView';
-import { v4 as uuidv4 } from 'uuid';
-import { LinkManager } from '../../../../util/LinkManager';
-import { DocCast, StrCast } from '../../../../../fields/Types';
-import { supportedDocTypes } from '../types/tool_types';
-import { parsedDoc } from '../chatboxcomponents/ChatBox';
import { AgentDocumentManager } from '../utils/AgentDocumentManager';
+import { BaseTool } from './BaseTool';
// Define the parameters for the DocumentMetadataTool
const parameterDefinitions: ReadonlyArray<Parameter> = [
@@ -598,7 +589,7 @@ export class DocumentMetadataTool extends BaseTool<DocumentMetadataToolParamsTyp
message: string;
fieldName?: string;
originalFieldName?: string;
- newValue?: any;
+ newValue?: string | number | boolean | object;
warning?: string;
}[] = [];
diff --git a/src/client/views/nodes/chatbot/utils/AgentDocumentManager.ts b/src/client/views/nodes/chatbot/utils/AgentDocumentManager.ts
index 3c8b49f33..dcb708450 100644
--- a/src/client/views/nodes/chatbot/utils/AgentDocumentManager.ts
+++ b/src/client/views/nodes/chatbot/utils/AgentDocumentManager.ts
@@ -1,7 +1,5 @@
import { action, computed, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx';
-import { observer } from 'mobx-react';
-import { v4 as uuidv4 } from 'uuid';
-import { Doc, StrListCast } from '../../../../../fields/Doc';
+import { Doc, FieldResult, StrListCast } from '../../../../../fields/Doc';
import { DocData } from '../../../../../fields/DocSymbols';
import { Id } from '../../../../../fields/FieldSymbols';
import { List } from '../../../../../fields/List';
@@ -30,7 +28,7 @@ export class AgentDocumentManager {
@observable private documentsById: ObservableMap<string, AgentDocument>;
private chatBox: ChatBox;
private chatBoxDocument: Doc | null = null;
- private fieldMetadata: Record<string, any> = {};
+ private fieldMetadata: Record<string, any> = {}; // bcz: CHANGE any to a proper type!
@observable private simplifiedChunks: ObservableMap<string, SimplifiedChunk>;
/**
@@ -103,6 +101,7 @@ export class AgentDocumentManager {
for (const [fieldName, fieldInfo] of documentOptionsEntries) {
// Extract field information
const fieldData: Record<string, any> = {
+ // bcz: CHANGE any to a proper type!
name: fieldName,
withoutUnderscore: fieldName.startsWith('_') ? fieldName.substring(1) : fieldName,
description: '',
@@ -223,6 +222,7 @@ export class AgentDocumentManager {
const dataDoc = agentDoc.dataDoc;
const metadata: Record<string, any> = {
+ // bcz: CHANGE any to a proper type!
id: layoutDoc[Id] || dataDoc[Id] || '',
title: layoutDoc.title || '',
type: layoutDoc.type || '',
@@ -235,7 +235,7 @@ export class AgentDocumentManager {
// Process all known field definitions
Object.keys(this.fieldMetadata).forEach(fieldName => {
- const fieldDef = this.fieldMetadata[fieldName];
+ // const fieldDef = this.fieldMetadata[fieldName];
const strippedName = fieldName.startsWith('_') ? fieldName.substring(1) : fieldName;
// Check if field exists on layout document
@@ -307,7 +307,7 @@ export class AgentDocumentManager {
* @param value The field value to format
* @returns A JSON-friendly representation of the field value
*/
- private formatFieldValue(value: any): any {
+ private formatFieldValue(value: FieldResult | undefined) {
if (value === undefined || value === null) {
return null;
}
@@ -330,12 +330,12 @@ export class AgentDocumentManager {
if (rtfObj.doc && rtfObj.doc.content) {
// Recursively extract text from the content
let plainText = '';
- const extractText = (node: any) => {
+ const extractText = (node: { text: string; content?: unknown[] }) => {
if (node.text) {
plainText += node.text;
}
if (node.content && Array.isArray(node.content)) {
- node.content.forEach((child: any) => extractText(child));
+ node.content.forEach(child => extractText(child as { text: string; content?: unknown[] }));
}
};
@@ -351,7 +351,7 @@ export class AgentDocumentManager {
};
}
}
- } catch (e) {
+ } catch {
// If parsing fails, just treat as a regular string
}
}
@@ -366,7 +366,7 @@ export class AgentDocumentManager {
try {
// Try to convert to JSON string
return JSON.stringify(value);
- } catch (e) {
+ } catch {
return '[Complex Object]';
}
}
@@ -381,26 +381,24 @@ export class AgentDocumentManager {
* @param fieldValue The string value to convert
* @returns The converted value with the appropriate type
*/
- private convertFieldValue(fieldName: string, fieldValue: any): any {
+ private convertFieldValue(fieldName: string, fieldValueIn: string | number | boolean): FieldResult | undefined {
// If fieldValue is already a number or boolean, we don't need to convert it from string
- if (typeof fieldValue === 'number' || typeof fieldValue === 'boolean') {
- return fieldValue;
+ if (typeof fieldValueIn === 'number' || typeof fieldValueIn === 'boolean') {
+ return fieldValueIn;
}
// If fieldValue is a string "true" or "false", convert to boolean
- if (typeof fieldValue === 'string') {
- if (fieldValue.toLowerCase() === 'true') {
+ if (typeof fieldValueIn === 'string') {
+ if (fieldValueIn.toLowerCase() === 'true') {
return true;
}
- if (fieldValue.toLowerCase() === 'false') {
+ if (fieldValueIn.toLowerCase() === 'false') {
return false;
}
}
- // If fieldValue is not a string (and not a number or boolean), convert it to string
- if (typeof fieldValue !== 'string') {
- fieldValue = String(fieldValue);
- }
+ // coerce fieldvValue to a string
+ const fieldValue = typeof fieldValueIn !== 'string' ? String(fieldValueIn) : fieldValueIn;
// Special handling for text field - convert to proper RichTextField format
if (fieldName === 'text') {
@@ -408,7 +406,7 @@ export class AgentDocumentManager {
// Check if it's already a valid JSON RichTextField
JSON.parse(fieldValue);
return fieldValue;
- } catch (e) {
+ } catch {
// It's a plain text string, so convert it to RichTextField format
const rtf = {
doc: {
@@ -462,21 +460,21 @@ export class AgentDocumentManager {
// Try to convert to date (stored as number timestamp)
try {
return new Date(fieldValue).getTime();
- } catch (e) {
+ } catch {
return fieldValue;
}
} else if (fieldType.includes('list') || fieldType.includes('array')) {
// Try to parse as JSON array
try {
- return JSON.parse(fieldValue);
- } catch (e) {
+ return JSON.parse(fieldValue) as FieldResult; // bcz: this needs to be typed properly. Dash fields can't accept a generic 'objext'
+ } catch {
return fieldValue;
}
} else if (fieldType === 'json' || fieldType === 'object') {
// Try to parse as JSON object
try {
- return JSON.parse(fieldValue);
- } catch (e) {
+ return JSON.parse(fieldValue) as FieldResult; // bcz: this needs to be typed properly. Dash fields can't accept a generic 'objext'
+ } catch {
return fieldValue;
}
}
@@ -492,6 +490,7 @@ export class AgentDocumentManager {
public getAllFieldMetadata() {
// Start with our already populated fieldMetadata from the DocumentOptions class
const result: Record<string, any> = {
+ // bcz: CHANGE any to a proper type!
fieldCount: Object.keys(this.fieldMetadata).length,
fields: {},
fieldsByType: {
@@ -526,6 +525,7 @@ export class AgentDocumentManager {
// Create structured field metadata
const fieldData: Record<string, any> = {
+ // bcz: CHANGE any to a proper type!
name: fieldName,
displayName: strippedName,
description: fieldInfo.description || '',
@@ -618,12 +618,12 @@ export class AgentDocumentManager {
message: string;
fieldName?: string;
originalFieldName?: string;
- newValue?: any;
+ newValue?: string | number | boolean | object;
warning?: string;
} {
// Normalize field name (handle with/without underscore)
let normalizedFieldName = fieldName.startsWith('_') ? fieldName : fieldName;
- const strippedFieldName = fieldName.startsWith('_') ? fieldName.substring(1) : fieldName;
+ // const strippedFieldName = fieldName.startsWith('_') ? fieldName.substring(1) : fieldName;
// Handle common field name aliases (width → _width, height → _height)
// Many document fields use '_' prefix for layout properties
@@ -690,7 +690,7 @@ export class AgentDocumentManager {
}
// Set the field value on the target document
- targetDoc[normalizedFieldName] = convertedValue;
+ targetDoc[normalizedFieldName] = convertedValue; // bcz: converteValue needs to be typed properly. Dash fields can't accept a generic 'objext'
return {
success: true,
@@ -712,19 +712,19 @@ export class AgentDocumentManager {
* @param documentId Optional ID of a specific document to get metadata for
* @returns Document metadata or metadata for all documents
*/
- public getDocumentMetadata(documentId?: string): any {
+ public getDocumentMetadata(documentId?: string) {
if (documentId) {
console.log(`Returning document metadata for docID, ${documentId}:`, this.extractDocumentMetadata(documentId));
return this.extractDocumentMetadata(documentId);
} else {
// Get metadata for all documents
- const documentsMetadata: Record<string, Record<string, any>> = {};
- for (const documentId of this.documentsById.keys()) {
- const metadata = this.extractDocumentMetadata(documentId);
+ const documentsMetadata: Record<string, Record<string, any>> = {}; // bcz: CHANGE any to a proper type!
+ for (const docid of this.documentsById.keys()) {
+ const metadata = this.extractDocumentMetadata(docid);
if (metadata) {
- documentsMetadata[documentId] = metadata;
+ documentsMetadata[docid] = metadata;
} else {
- console.warn(`No metadata found for document with ID: ${documentId}`);
+ console.warn(`No metadata found for document with ID: ${docid}`);
}
}
return {
@@ -842,7 +842,7 @@ export class AgentDocumentManager {
* @returns The ID of the created document
*/
- public async createDocInDash(docType: string, data: string, options?: any): Promise<string> {
+ public async createDocInDash(docType: string, data: string, options?: DocumentOptions): Promise<string> {
// Validate doc_type
if (!this.isValidDocType(docType)) {
throw new Error(`Invalid document type: ${docType}`);
@@ -1054,13 +1054,13 @@ export class AgentDocumentManager {
endPage: chunk.metadata.end_page,
location: chunk.metadata.location,
} as SimplifiedChunk);
- } else if (docType === 'csv') {
+ } else if (docType === 'csv' && 'row_start' in chunk.metadata && 'row_end' in chunk.metadata && 'col_start' in chunk.metadata && 'col_end' in chunk.metadata) {
simplifiedChunks.push({
...baseChunk,
- rowStart: (chunk.metadata as any).row_start,
- rowEnd: (chunk.metadata as any).row_end,
- colStart: (chunk.metadata as any).col_start,
- colEnd: (chunk.metadata as any).col_end,
+ rowStart: chunk.metadata.row_start,
+ rowEnd: chunk.metadata.row_end,
+ colStart: chunk.metadata.col_start,
+ colEnd: chunk.metadata.col_end,
} as SimplifiedChunk);
} else {
// Default for other document types
@@ -1077,7 +1077,7 @@ export class AgentDocumentManager {
* @returns The simplified chunk if found, undefined otherwise
*/
@action
- public getSimplifiedChunkById(chunkId: string): any | undefined {
+ public getSimplifiedChunkById(chunkId: string) {
return { foundChunk: this.simplifiedChunks.get(chunkId), doc: this.getDocument(this.simplifiedChunks.get(chunkId)?.doc_id || chunkId), dataDoc: this.getDataDocument(this.simplifiedChunks.get(chunkId)?.doc_id || chunkId) };
}
@@ -1098,7 +1098,7 @@ export class AgentDocumentManager {
* @param doc The document containing original media segments
* @returns Array of media segments or empty array if none exist
*/
- public getOriginalSegments(doc: Doc): any[] {
+ public getOriginalSegments(doc: Doc): { text: string; index: string; start: number }[] {
if (!doc || !doc.original_segments) {
return [];
}
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
index 9c37428ee..6e0d58932 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
@@ -1,4 +1,4 @@
-import { Button, IconButton, Toggle, ToggleType, Type } from '@dash/components';
+import { Button, IconButton, Size, Toggle, ToggleType, Type } from '@dash/components';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
@@ -9,7 +9,10 @@ import ReactLoading from 'react-loading';
import { TypeAnimation } from 'react-type-animation';
import { ClientUtils } from '../../../../ClientUtils';
import { Doc } from '../../../../fields/Doc';
+import { List } from '../../../../fields/List';
import { NumCast, StrCast } from '../../../../fields/Types';
+import { ImageField } from '../../../../fields/URLField';
+import { Upload } from '../../../../server/SharedMediaTypes';
import { Networking } from '../../../Network';
import { DataSeperator, DescriptionSeperator, DocSeperator, GPTCallType, GPTDocCommand, gptAPICall, gptImageCall } from '../../../apis/gpt/GPT';
import { DocUtils } from '../../../documents/DocUtils';
@@ -21,17 +24,14 @@ import { DictationButton } from '../../DictationButton';
import { ObservableReactComponent } from '../../ObservableReactComponent';
import { TagItem } from '../../TagsView';
import { ChatSortField, docSortings } from '../../collections/CollectionSubView';
+import { ComparisonBox } from '../../nodes/ComparisonBox';
import { DocumentView, DocumentViewInternal } from '../../nodes/DocumentView';
+import { OpenWhere } from '../../nodes/OpenWhere';
+import { DrawingFillHandler } from '../../smartdraw/DrawingFillHandler';
+import { FireflyImageDimensions } from '../../smartdraw/FireflyConstants';
import { SmartDrawHandler } from '../../smartdraw/SmartDrawHandler';
import { AnchorMenu } from '../AnchorMenu';
import './GPTPopup.scss';
-import { FireflyImageDimensions } from '../../smartdraw/FireflyConstants';
-import { Upload } from '../../../../server/SharedMediaTypes';
-import { OpenWhere } from '../../nodes/OpenWhere';
-import { DrawingFillHandler } from '../../smartdraw/DrawingFillHandler';
-import { ImageField } from '../../../../fields/URLField';
-import { List } from '../../../../fields/List';
-import { ComparisonBox } from '../../nodes/ComparisonBox';
export enum GPTPopupMode {
SUMMARY, // summary of seleted document text
@@ -45,7 +45,6 @@ export enum GPTPopupMode {
@observer
export class GPTPopup extends ObservableReactComponent<object> {
- // eslint-disable-next-line no-use-before-define
static Instance: GPTPopup;
static ChatTag = '#chat'; // tag used by GPT popup to filter docs
private _askDictation: DictationButton | null = null;
@@ -530,14 +529,14 @@ export class GPTPopup extends ObservableReactComponent<object> {
style={{ color: 'black' }}
placeholder={placeholder}
/>
- <Button //
- text="Send"
- type={Type.TERT}
+ <Button //\
+ type={Type.PRIM}
+ tooltip="Send to AI"
icon={<AiOutlineSend />}
iconPlacement="right"
- color={SettingsManager.userColor}
- background={SettingsManager.userVariantColor}
+ background={SnappingManager.userVariantColor}
onClick={() => this.callGpt(this._mode)}
+ size={Size.LARGE}
/>
<DictationButton ref={this.setDictationRef} setInput={onChange} />
</div>