From 3b17868560090756caf8b9b0f043ea163f2320e8 Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Sun, 20 Oct 2024 12:44:15 -0400 Subject: changes --- src/client/views/MainView.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 7779d339f..7bc211036 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -73,7 +73,7 @@ import { OpenWhere, OpenWhereMod } from './nodes/OpenWhere'; import { TaskCompletionBox } from './nodes/TaskCompletedBox'; import { DashFieldViewMenu } from './nodes/formattedText/DashFieldView'; import { RichTextMenu } from './nodes/formattedText/RichTextMenu'; -import GenerativeFill from './nodes/generativeFill/GenerativeFill'; +import ImageEditorBox from './nodes/imageEditor/ImageEditor'; import { PresBox } from './nodes/trails'; import { AnchorMenu } from './pdf/AnchorMenu'; import { GPTPopup } from './pdf/GPTPopup/GPTPopup'; @@ -446,6 +446,7 @@ export class MainView extends ObservableReactComponent { fa.faAlignRight, fa.faHeading, fa.faRulerCombined, + fa.faFill, fa.faFillDrip, fa.faLink, fa.faUnlink, @@ -1146,7 +1147,7 @@ export class MainView extends ObservableReactComponent { - + ); } -- cgit v1.2.3-70-g09d2 From 89424e0a8efc6cf3364a2fd1ffc85c9d0d837453 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 22 Nov 2024 10:27:33 -0500 Subject: added initial Firefly endpoint and hanged smartDrawHandler to generate an image and an svg. --- src/client/util/bezierFit.ts | 3 +- src/client/views/MainView.tsx | 32 ++++++++++++-- .../nodes/chatbot/chatboxcomponents/ChatBox.tsx | 3 +- src/client/views/pdf/AnchorMenu.tsx | 9 ++-- src/client/views/smartdraw/SmartDrawHandler.tsx | 29 ++++++------ src/server/ApiManagers/DataVizManager.ts | 2 +- src/server/ApiManagers/FireflyManager.ts | 51 ++++++++++++++++++++++ src/server/DashUploadUtils.ts | 3 +- src/server/index.ts | 3 +- webpack.config.js | 7 ++- 10 files changed, 113 insertions(+), 29 deletions(-) create mode 100644 src/server/ApiManagers/FireflyManager.ts (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/util/bezierFit.ts b/src/client/util/bezierFit.ts index d52460023..84b27e84c 100644 --- a/src/client/util/bezierFit.ts +++ b/src/client/util/bezierFit.ts @@ -703,7 +703,6 @@ export function SVGToBezier(name: SVGType, attributes: any): Point[] { coordList.push({ X: parseInt(match[1]), Y: parseInt(match[2]) }); coordList.push({ X: parseInt(match[1]), Y: parseInt(match[2]) }); coordList.push({ X: parseInt(match[3]), Y: parseInt(match[4]) }); - coordList.push({ X: parseInt(match[3]), Y: parseInt(match[4]) }); lastPt = { X: parseInt(match[3]), Y: parseInt(match[4]) }; } else if (match[0].startsWith('C')) { coordList.push({ X: parseInt(match[5]), Y: parseInt(match[6]) }); @@ -720,7 +719,7 @@ export function SVGToBezier(name: SVGType, attributes: any): Point[] { } }); const hasZ = attributes.d.match(/Z/); - if (hasZ) { + if (hasZ || attributes.fill) { coordList.push(lastPt); coordList.push(startPt); coordList.push(startPt); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 7779d339f..0d071fe4f 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -8,7 +8,7 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import ResizeObserver from 'resize-observer-polyfill'; import '../../../node_modules/browndash-components/dist/styles/global.min.css'; -import { ClientUtils, lightOrDark, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents } from '../../ClientUtils'; +import { ClientUtils, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents } from '../../ClientUtils'; import { emptyFunction } from '../../Utils'; import { Doc, DocListCast, GetDocFromUrl, Opt, returnEmptyDoclist } from '../../fields/Doc'; import { DocData } from '../../fields/DocSymbols'; @@ -1023,10 +1023,36 @@ export class MainView extends ObservableReactComponent { {[ ...SnappingManager.HorizSnapLines.map(l => ( - + )), ...SnappingManager.VertSnapLines.map(l => ( - + )), ]} diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx index a61705250..3ef6bdd8b 100644 --- a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx +++ b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx @@ -431,7 +431,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent() { doc = Docs.Create.FunctionPlotDocument([], options); break; case 'dataviz': - case 'data_viz': + case 'data_viz': { const { fileUrl, id } = await Networking.PostToServer('/createCSV', { filename: (options.title as string).replace(/\s+/g, '') + '.csv', data: data, @@ -439,6 +439,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent() { doc = Docs.Create.DataVizDocument(fileUrl, { ...options, text: RTFCast(data) }); this.addCSVForAnalysis(doc, id); break; + } case 'chat': doc = Docs.Create.ChatDocument(options); break; diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index 5ab9b556c..fe03f32a5 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -131,12 +131,15 @@ export class AnchorMenu extends AntimodeMenu { /** * Creates a GPT drawing based on selected text. */ - gptDraw = async (e: React.PointerEvent) => { + gptDraw = (e: React.PointerEvent) => { try { SmartDrawHandler.Instance.AddDrawing = this.createDrawingAnnotation; runInAction(() => (this._isLoading = true)); - await SmartDrawHandler.Instance.drawWithGPT({ X: e.clientX, Y: e.clientY }, this._selectedText, 5, 100, true); - runInAction(() => (this._isLoading = false)); + SmartDrawHandler.Instance.drawWithGPT({ X: e.clientX, Y: e.clientY }, this._selectedText, 5, 100, true)?.then( + action(() => { + this._isLoading = false; + }) + ); } catch (err) { console.error(err); } diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx index d0f6566a5..342b91bd9 100644 --- a/src/client/views/smartdraw/SmartDrawHandler.tsx +++ b/src/client/views/smartdraw/SmartDrawHandler.tsx @@ -13,6 +13,7 @@ import { Doc, DocListCast } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { InkData, InkField, InkTool } from '../../../fields/InkField'; import { BoolCast, ImageCast, NumCast, StrCast } from '../../../fields/Types'; +import { Networking } from '../../Network'; import { GPTCallType, gptAPICall, gptDrawingColor } from '../../apis/gpt/GPT'; import { Docs } from '../../documents/Documents'; import { SettingsManager } from '../../util/SettingsManager'; @@ -21,7 +22,8 @@ import { SVGToBezier, SVGType } from '../../util/bezierFit'; import { InkingStroke } from '../InkingStroke'; import { ObservableReactComponent } from '../ObservableReactComponent'; import { MarqueeView } from '../collections/collectionFreeForm'; -import { ActiveInkArrowEnd, ActiveInkArrowStart, ActiveInkDash, ActiveInkFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, DocumentView } from '../nodes/DocumentView'; +import { ActiveInkArrowEnd, ActiveInkArrowStart, ActiveInkBezierApprox, ActiveInkColor, ActiveInkDash, ActiveInkFillColor, ActiveInkWidth, ActiveIsInkMask, DocumentView, DocumentViewInternal } from '../nodes/DocumentView'; +import { OpenWhere } from '../nodes/OpenWhere'; import './SmartDrawHandler.scss'; export interface DrawingOptions { @@ -230,20 +232,21 @@ export class SmartDrawHandler extends ObservableReactComponent { * Calls GPT API to create a drawing based on user input. */ @action - drawWithGPT = async (startPt: { X: number; Y: number }, input: string, complexity: number, size: number, autoColor: boolean) => { - if (input === '') return; - this._lastInput = { text: input, complexity: complexity, size: size, autoColor: autoColor, x: startPt.X, y: startPt.Y }; - const res = await gptAPICall(`"${input}", "${complexity}", "${size}"`, GPTCallType.DRAW, undefined, true); - if (!res) { - console.error('GPT call failed'); - return; - } - const strokeData = await this.parseSvg(res, startPt, false, autoColor); - const drawingDoc = strokeData && this.CreateDrawingDoc(strokeData.data, strokeData.lastInput, strokeData.lastRes); - drawingDoc && this.AddDrawing(drawingDoc, this._lastInput, res); + drawWithGPT = (startPt: { X: number; Y: number }, prompt: string, complexity: number, size: number, autoColor: boolean) => { + if (prompt === '') return; + this._lastInput = { text: prompt, complexity: complexity, size: size, autoColor: autoColor, x: startPt.X, y: startPt.Y }; + + Networking.PostToServer('/queryFireflyImage', { prompt }).then(img => DocumentViewInternal.addDocTabFunc(Docs.Create.ImageDocument(img, { title: prompt }), OpenWhere.addRight)); + + const result = gptAPICall(`"${prompt}", "${complexity}", "${size}"`, GPTCallType.DRAW, undefined, true).then(res => + this.parseSvg(res, startPt, false, autoColor).then(strokeData => { + const drawingDoc = strokeData && this.CreateDrawingDoc(strokeData.data, strokeData.lastInput, strokeData.lastRes); + drawingDoc && this.AddDrawing(drawingDoc, this._lastInput, res); + }) + ); this._errorOccurredOnce = false; - return strokeData; + return result; }; /** diff --git a/src/server/ApiManagers/DataVizManager.ts b/src/server/ApiManagers/DataVizManager.ts index 88f22992d..d2028f23b 100644 --- a/src/server/ApiManagers/DataVizManager.ts +++ b/src/server/ApiManagers/DataVizManager.ts @@ -9,7 +9,7 @@ export default class DataVizManager extends ApiManager { register({ method: Method.GET, subscription: '/csvData', - secureHandler: async ({ req, res }) => { + secureHandler: ({ req, res }) => { const uri = req.query.uri as string; return new Promise(resolve => { diff --git a/src/server/ApiManagers/FireflyManager.ts b/src/server/ApiManagers/FireflyManager.ts new file mode 100644 index 000000000..04fa8f065 --- /dev/null +++ b/src/server/ApiManagers/FireflyManager.ts @@ -0,0 +1,51 @@ +import { DashUploadUtils } from '../DashUploadUtils'; +import { _invalid, _success, Method } from '../RouteManager'; +import ApiManager, { Registration } from './ApiManager'; + +export default class FireflyManager extends ApiManager { + askFirefly = (prompt: string = 'a realistic illustration of a cat coding') => { + const fetched = fetch('https://ims-na1.adobelogin.com/ims/token/v3', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: `grant_type=client_credentials&client_id=${process.env._CLIENT_FIREFLY_CLIENT_ID}&client_secret=${process.env._CLIENT_FIREFLY_SECRET}&scope=openid,AdobeID,session,additional_info,read_organizations,firefly_api,ff_apis`, + }) + .then(response => response.json()) + .then((data: { access_token: string }) => + fetch('https://firefly-api.adobe.io/v3/images/generate', { + method: 'POST', + headers: [ + ['Content-Type', 'application/json'], + ['Accept', 'application/json'], + ['x-api-key', process.env._CLIENT_FIREFLY_CLIENT_ID ?? ''], + ['Authorization', `Bearer ${data.access_token}`], + ], + body: `{ "prompt": "${prompt}" }`, + }) + .then(response => response.json().then(json => JSON.stringify((json.outputs?.[0] as { image: { url: string } })?.image))) + .catch(error => { + console.error('Error:', error); + return ''; + }) + ) + .catch(error => { + console.error('Error:', error); + return ''; + }); + return fetched; + }; + protected initialize(register: Registration): void { + register({ + method: Method.POST, + subscription: '/queryFireflyImage', + secureHandler: ({ req, res }) => + this.askFirefly(req.body.prompt).then(fire => + DashUploadUtils.UploadImage(JSON.parse(fire).url).then(info => { + if (info instanceof Error) _invalid(res, info.message); + else _success(res, info.accessPaths.agnostic.client); + }) + ), + }); + } +} diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index 1e55a885a..032d13d43 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -369,7 +369,8 @@ export namespace DashUploadUtils { */ export const UploadInspectedImage = async (metadata: Upload.InspectionResults, filename: string, prefix = '', cleanUp = true): Promise => { const { requestable, source, ...remaining } = metadata; - const resolved = filename || `${prefix}upload_${Utils.GenerateGuid()}.${remaining.contentType.split('/')[1].toLowerCase()}`; + const dfltSuffix = remaining.contentType.split('/')[1].toLowerCase(); + const resolved = filename || `${prefix}upload_${Utils.GenerateGuid()}.${dfltSuffix === 'xml' ? 'jpg' : dfltSuffix}`; const { images } = Directory; const information: Upload.ImageInformation = { accessPaths: { diff --git a/src/server/index.ts b/src/server/index.ts index 88dbd232d..1f9af9ee0 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -7,6 +7,7 @@ import AssistantManager from './ApiManagers/AssistantManager'; import DataVizManager from './ApiManagers/DataVizManager'; import DeleteManager from './ApiManagers/DeleteManager'; import DownloadManager from './ApiManagers/DownloadManager'; +import FireflyManager from './ApiManagers/FireflyManager'; import GeneralGoogleManager from './ApiManagers/GeneralGoogleManager'; import SessionManager from './ApiManagers/SessionManager'; import UploadManager from './ApiManagers/UploadManager'; @@ -71,6 +72,7 @@ function routeSetter({ addSupervisedRoute, logRegistrationOutcome }: RouteManage new GeneralGoogleManager(), /* new GooglePhotosManager(), */ new DataVizManager(), new AssistantManager(), + new FireflyManager(), ]; // initialize API Managers @@ -112,7 +114,6 @@ function routeSetter({ addSupervisedRoute, logRegistrationOutcome }: RouteManage }); const serve: PublicHandler = ({ req, res }) => { - // eslint-disable-next-line new-cap const detector = new mobileDetect(req.headers['user-agent'] || ''); const filename = detector.mobile() !== null ? 'mobile/image.html' : 'index.html'; res.sendFile(path.join(__dirname, '../../deploy/' + filename)); diff --git a/webpack.config.js b/webpack.config.js index e1afc64e5..67417fb02 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-require-imports */ const path = require('path'); const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); @@ -36,7 +36,6 @@ function transferEnvironmentVariables() { } const resolvedClientSide = Object.keys(parsed).reduce((mapping, envKey) => { if (envKey.startsWith(prefix)) { - // eslint-disable-next-line mapping[`process.env.${envKey.replace(prefix, '')}`] = JSON.stringify(parsed[envKey]); } return mapping; @@ -112,7 +111,7 @@ module.exports = { test: /\.scss|css$/, exclude: /\.module\.scss$/i, use: [ - { loader: 'style-loader' }, // eslint-disable-next-line prettier/prettier + { loader: 'style-loader' }, // { loader: 'css-loader' }, { loader: 'sass-loader' }, ], @@ -127,7 +126,7 @@ module.exports = { { test: /\.module\.scss$/i, use: [ - { loader: 'style-loader' }, // eslint-disable-next-line prettier/prettier + { loader: 'style-loader' }, // { loader: 'css-loader', options: { modules: true } }, { loader: 'sass-loader' }, ], -- cgit v1.2.3-70-g09d2 From cffb72e762d989eb1219a5736f082f5b656bee37 Mon Sep 17 00:00:00 2001 From: Geireann Lindfield Roberts Date: Wed, 1 Jan 2025 22:45:48 -0800 Subject: Update MainView.tsx --- src/client/views/MainView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 0d071fe4f..65d90a5a0 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -7,7 +7,7 @@ import { action, computed, configure, makeObservable, observable, reaction, runI import { observer } from 'mobx-react'; import * as React from 'react'; import ResizeObserver from 'resize-observer-polyfill'; -import '../../../node_modules/browndash-components/dist/styles/global.min.css'; +import '@dash/components/src/global/globalCssVariables.scss'; import { ClientUtils, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents } from '../../ClientUtils'; import { emptyFunction } from '../../Utils'; import { Doc, DocListCast, GetDocFromUrl, Opt, returnEmptyDoclist } from '../../fields/Doc'; -- cgit v1.2.3-70-g09d2 From 6fa61343a3e63a61747bc7123810190057d0bfe4 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 29 Jan 2025 12:14:12 -0500 Subject: cleaned up filter icons. --- src/client/util/CurrentUserUtils.ts | 38 +++++++++++++++++----- src/client/views/MainView.tsx | 25 +++----------- .../views/collections/CollectionCardDeckView.tsx | 20 +++--------- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 34 +++++++------------ 4 files changed, 48 insertions(+), 69 deletions(-) (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index e806675aa..306914450 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -40,6 +40,7 @@ import { ColorScheme } from "./SettingsManager"; import { SnappingManager } from "./SnappingManager"; import { UndoManager } from "./UndoManager"; import { DocumentView } from "../views/nodes/DocumentView"; +import { IconProp } from "@fortawesome/fontawesome-svg-core"; export interface Button { // DocumentOptions fields a button can set @@ -67,6 +68,21 @@ export interface Button { subMenu?: Button[]; } +// Not really necessary, but for now, all tags should start with a capital first letter +export type TagName = + // eslint-disable-next-line @typescript-eslint/no-unused-vars + T extends `${infer First}${infer Rest}` + ? First extends Uppercase + ? First extends Lowercase + ? never // If it's the same when uppercased and lowercased, it's not a letter. + : T // Otherwise, it's a valid capitalized string. + : never + : never; +export function ToTagName(key: string):"Tag"{ + return ((str => str[0].toUpperCase() + str.slice(1))(key.startsWith('#') ? key.substring(1) : key)) as "Tag"; +} + + export let resolvedPorts: { server: number, socket: number }; export class CurrentUserUtils { @@ -703,18 +719,22 @@ pie title Minerals in my tap water ]}, ] } + + static filterBtnDesc(tag:TagName|"Tag", icon:IconProp):Button { + return { title: tag, isSystem: false, icon: icon.toString(), toolTip:`Click to toggle visibility of ${tag} tagged Docs`, btnType: ButtonType.ToggleButton, expertMode: false, toolType:`#${tag.toLowerCase()}`, funcs: {}, scripts: { onClick: '{ return setTagFilter(this.toolType, _added_, _readOnly_);}'}} + } static filterTools(): Button[] { - const defaultTagButtonDescs = [ - { title: "Star", isSystem: false,icon: "star", toolTip:"Click to toggle visibility of Star tagged Docs", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"#star", funcs: {}, scripts: { onClick: '{ return setTagFilter(this.toolType, _added_, _readOnly_);}'}}, - { title: "Like", isSystem: false,icon: "heart", toolTip:"Click to toggle visibility of Like tagged Docs", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"#like", funcs: {}, scripts: { onClick: '{ return setTagFilter(this.toolType, _added_, _readOnly_);}'}}, - { title: "Todo", isSystem: false,icon: "bolt", toolTip:"Click to toggle visibility of Todo tagged Docs", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"#todo", funcs: {}, scripts: { onClick: '{ return setTagFilter(this.toolType, _added_, _readOnly_);}'}}, - { title: "Idea", isSystem: false,icon: "cloud", toolTip:"Click to toggle visibility of Idea tagged Docs", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"#idea", funcs: {}, scripts: { onClick: '{ return setTagFilter(this.toolType, _added_, _readOnly_);}'}}, + // If there's no active dashboard, then a default set of tags are added, otherwise, the user controls which tags are kept + const tagButtonDescs = Doc.UserDoc().activeDashboard ? [] : [ + this.filterBtnDesc("Star", "star"), + this.filterBtnDesc("Like", "heart"), + this.filterBtnDesc("Todo", "bolt"), + this.filterBtnDesc("Idea", "cloud") ]; - // hack: if there's no dashboard, create default filters. otherwise, just make sure that the Options button is preserved return [ - { title:"Options",isSystem: true,icon: "gear", toolTip:"Click to customize list of filter buttons", btnType: ButtonType.ClickButton, expertMode: false, toolType:"-opts-",funcs: {}, scripts: { onClick: '{ return setTagFilter(this.toolType, false,_readOnly_);}'}}, - ...(Doc.UserDoc().activeDashboard ? [] : defaultTagButtonDescs) + { title:"Options",isSystem: true,icon: "gear", toolTip:"Click to customize list of filter buttons", btnType: ButtonType.ClickButton, expertMode: false, toolType:"-opts-",funcs: {}, scripts: { onClick: '{ return setTagFilter(this.toolType, false,_readOnly_);}'}}, + ...tagButtonDescs ] } static viewTools(): Button[] { @@ -866,7 +886,7 @@ pie title Minerals in my tap water childDontRegisterViews: true, flexGap: 0, _height: 30, _width: 30, ignoreClick: !params.scripts?.onClick, linearView_SubMenu: true, linearView_Expandable: true, embedContainer: menuDoc}; - const items = (menutBtn?:Doc) => !menutBtn ? [] : subMenu.map(sub => this.setupContextMenuBtn(sub, menutBtn) ); + const items = (menuBtn?:Doc) => !menuBtn ? [] : subMenu.map(sub => this.setupContextMenuBtn(sub, menuBtn) ); const creator = params.btnType === ButtonType.MultiToggleButton ? this.multiToggleList : this.linearButtonList; const btnDoc = DocUtils.AssignScripts( DocUtils.AssignDocField(menuDoc, StrCast(params.title), (opts) => creator(opts, items(menuBtnDoc)), reqdSubMenuOpts, items(menuBtnDoc)), params.scripts, params.funcs); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 7abca5197..d748b70ae 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -20,7 +20,7 @@ import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; import { Docs } from '../documents/Documents'; import { CalendarManager } from '../util/CalendarManager'; import { CaptureManager } from '../util/CaptureManager'; -import { Button, CurrentUserUtils } from '../util/CurrentUserUtils'; +import { CurrentUserUtils, ToTagName } from '../util/CurrentUserUtils'; import { DocumentManager } from '../util/DocumentManager'; import { DragManager } from '../util/DragManager'; import { dropActionType } from '../util/DropActionTypes'; @@ -63,7 +63,6 @@ import { DocCreatorMenu } from './nodes/DataVizBox/DocCreatorMenu'; import { SchemaCSVPopUp } from './nodes/DataVizBox/SchemaCSVPopUp'; import { DocButtonState } from './nodes/DocumentLinksButton'; import { DocumentView, DocumentViewInternal } from './nodes/DocumentView'; -import { ButtonType } from './nodes/FontIconBox/FontIconBox'; import { ImageEditorData as ImageEditor } from './nodes/ImageBox'; import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup'; import { LinkDocPreview, LinkInfo } from './nodes/LinkDocPreview'; @@ -874,25 +873,9 @@ export class MainView extends ObservableReactComponent { * @param hotKey tite of the new hotkey */ addHotKey = (hotKey: string) => { - const buttons = DocCast(Doc.UserDoc().myContextMenuBtns); - const filter = DocCast(buttons.Filter); - const title = hotKey.startsWith('#') ? hotKey.substring(1) : hotKey; - - const newKey: Button = { - title, - icon: 'question', - toolTip: `Click to toggle the ${title}'s group's visibility`, - btnType: ButtonType.ToggleButton, - expertMode: false, - toolType: '#' + title, - funcs: {}, - scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}' }, - }; - - const newBtn = CurrentUserUtils.setupContextMenuBtn(newKey, filter); - newBtn.isSystem = newBtn[DocData].isSystem = undefined; - - Doc.AddToFilterHotKeys(newBtn); + const filterIcons = DocCast(DocCast(Doc.UserDoc().myContextMenuBtns)?.Filter); + const menuDoc = CurrentUserUtils.setupContextMenuBtn(CurrentUserUtils.filterBtnDesc(ToTagName(hotKey), 'question'), filterIcons); + Doc.AddToFilterHotKeys(menuDoc); }; @computed get mainInnerContent() { diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 366d0f448..b40aa37de 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -462,24 +462,13 @@ export class CollectionCardView extends CollectionSubView() { case '6': doc.chatIndex = index; break; - case '1': { - const allHotKeys = Doc.MyFilterHotKeys; - let myTag = ''; + case '1': if (tag) { - for (let i = 0; i < allHotKeys.length; i++) { - const keyTag = StrCast(allHotKeys[i].toolType); - if (keyTag.includes(tag)) { - myTag = keyTag; - break; - } - } - - if (myTag) { - TagItem.addTagToDoc(doc, myTag); - } + const hashTag = tag.startsWith('#') ? tag : '#' + tag[0].toLowerCase() + tag.slice(1); + const filterTag = Doc.MyFilterHotKeys.map(key => StrCast(key.toolType)).find(key => key.includes(tag)) ?? hashTag; + TagItem.addTagToDoc(doc, filterTag); } break; - } case '2': case '4': doc.chatFilter = true; @@ -584,7 +573,6 @@ export class CollectionCardView extends CollectionSubView() { * Actually renders all the cards */ @computed get renderCards() { - console.log(this.docDraggedIndex, this.childDocs[0].title, this.childDocs[1].title); // Map sorted documents to their rendered components return this.childDocs.map((doc, index) => { const cardsInRow = this.cardsInRowThatIncludesCardIndex(index); diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index 4028ef479..c33b81eb4 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -188,8 +188,8 @@ export class GPTPopup extends ObservableReactComponent { const selected = DocumentView.SelectedDocs().lastElement(); - const questionText = 'Question: ' + StrCast(selected['gptInputText']); - const rubricText = 'Rubric: ' + StrCast(selected['gptRubric']); + const questionText = 'Question: ' + StrCast(selected.gptInputText); + const rubricText = 'Rubric: ' + StrCast(selected.gptRubric); const queryText = questionText + ' UserAnswer: ' + this.quizAnswer + '. ' + 'Rubric' + rubricText; try { @@ -262,27 +262,15 @@ export class GPTPopup extends ObservableReactComponent { try { const questionType = await gptAPICall(this.chatSortPrompt, GPTCallType.TYPE); - const questionNumber = questionType.split(' ')[0]; - let res = ''; - - switch (questionNumber) { - case '1': - case '2': - case '4': - res = await gptAPICall(this.sortDesc, GPTCallType.SUBSET, this.chatSortPrompt); - break; - case '6': - res = await gptAPICall(this.sortDesc, GPTCallType.SORT, this.chatSortPrompt); - break; - default: - { - const selected = DocumentView.SelectedDocs().lastElement(); - const questionText = StrCast(selected?.gptInputText); - - res = await gptAPICall(questionText, GPTCallType.INFO, this.chatSortPrompt); - } - break; - } + const questionNumber = questionType.split(' ')[0][0]; + const res = await (() => { + switch (questionNumber) { + case '1': + case '2': + case '4': return gptAPICall(this.sortDesc, GPTCallType.SUBSET, this.chatSortPrompt); + case '6': return gptAPICall(this.sortDesc, GPTCallType.SORT, this.chatSortPrompt); + default: return gptAPICall(StrCast(DocumentView.SelectedDocs().lastElement()?.gptInputText), GPTCallType.INFO, this.chatSortPrompt); + }})(); // prettier-ignore // Trigger the callback with the result if (this.onSortComplete) { -- cgit v1.2.3-70-g09d2