From 6bfa2fd696a306a984b29c6ea11fa66e93e0474c Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Tue, 4 Jun 2024 12:48:41 -0400 Subject: changes --- src/client/util/CurrentUserUtils.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index e095bc659..0d241650a 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -667,25 +667,25 @@ pie title Minerals in my tap water } static labelTools(): Button[] { return [ - { title: "AI", icon:"robot", toolTip:"Add AI labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {hidden:`showFreeform ("chat", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "AIs", icon:"AI Sort", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("chat"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + { title: "Smart", icon:"robot", toolTip:"Have ChatGPT Label and sort your cards for you!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {hidden:`showFreeform ("chat", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "AIs", icon:"AI Sort", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("robot"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, { title: "Like", icon:"heart", toolTip:"Add Like labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"like", funcs: {hidden:`showFreeform ("like", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Likes", icon:"Likes", toolTip:"Filter likes", width: 10, subMenu: this.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("like", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, { title: "Star", icon:"star", toolTip:"Add Star labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {hidden:`showFreeform ("star", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Stars", icon:"Stars", toolTip:"Filter stars", width: 80, subMenu: this.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("star", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - { title: "Idea", icon:"satellite", toolTip:"Add Idea labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"idea", funcs: {hidden:`showFreeform ("idea", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Ideas", icon:"Ideas", toolTip:"Filter ideas", width: 80, subMenu: this.cardGroupTools("satellite"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + { title: "Idea", icon:"cloud", toolTip:"Add Idea labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"idea", funcs: {hidden:`showFreeform ("idea", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Ideas", icon:"Ideas", toolTip:"Filter ideas", width: 80, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, ] } static cardGroupTools(icon: string): Button[] { return [ - { title: "1", icon, toolTip:"Click to toggle visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"1", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "2", icon, toolTip:"Click to toggle visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"2", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "3", icon, toolTip:"Click to toggle visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"3", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "4", icon, toolTip:"Click to toggle visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"4", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "5", icon, toolTip:"Click to toggle visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"5", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "6", icon, toolTip:"Click to toggle visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"6", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "7", icon, toolTip:"Click to toggle visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"7", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "", icon, toolTip:"Click to toggle group 1's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"1", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "", icon, toolTip:"Click to toggle group 2's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"2", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "", icon, toolTip:"Click to toggle group 3's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"3", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "", icon, toolTip:"Click to toggle group 4's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"4", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "", icon, toolTip:"Click to toggle group 5's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"5", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "", icon, toolTip:"Click to toggle group 6's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"6", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "", icon, toolTip:"Click to toggle group 7's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"7", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, ] } static viewTools(): Button[] { -- cgit v1.2.3-70-g09d2 From d3d2abbb011fe9c2a7d14b2a4b3016d55033aae8 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Thu, 6 Jun 2024 11:33:14 -0400 Subject: hm --- src/client/util/CurrentUserUtils.ts | 51 ++++++++++++++++------ .../views/collections/CollectionCardDeckView.scss | 2 +- .../views/collections/CollectionCardDeckView.tsx | 4 +- src/client/views/global/globalScripts.ts | 42 +++++++++--------- 4 files changed, 63 insertions(+), 36 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 0d241650a..f2ef9b943 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -660,21 +660,32 @@ pie title Minerals in my tap water } static cardTools(): Button[] { return [ - { title: "Time", icon:"hourglass-half", toolTip:"Sort by most recent document creation", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"time", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Type", icon:"eye", toolTip:"Sort by document type", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"docType",funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { btnList: new List(["Time", "Type", "Color", "ChatGPT", "Custom 1", "Custom 2", "Custom 3" ]), + title: "Sort Type", toolTip: "Card Sort Type", btnType: ButtonType.DropdownList, ignoreClick: true, width: 150, scripts: { script: '{ return showFreeform(value, _readOnly_); }'}}, + // { title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, toolType:"font", ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'}, + // btnList: new List(["Roboto", "Roboto Mono", "Nunito", "Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]) }, + // { title: "Time", icon:"hourglass-half", toolTip:"Sort by most recent document creation", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"time", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "Type", icon:"eye", toolTip:"Sort by document type", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"docType",funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "AIs", icon:"AI Sort", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("robot"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // { title: "Custom", icon:"heart", toolTip:"Add Like labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"like", funcs: {hidden:`showFreeform ("like", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "1st", icon:"1st", toolTip:"Filter likes", width: 10, subMenu: this.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("like", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // { title: "Custom", icon:"star", toolTip:"Add Star labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {hidden:`showFreeform ("star", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "2nd", icon:"2nd", toolTip:"Filter stars", width: 80, subMenu: this.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("star", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // { title: "Custom", icon:"cloud", toolTip:"Add Idea labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"idea", funcs: {hidden:`showFreeform ("idea", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "3rd", icon:"3rd", toolTip:"Filter ideas", width: 80, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, ] } static labelTools(): Button[] { return [ - { title: "Smart", icon:"robot", toolTip:"Have ChatGPT Label and sort your cards for you!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {hidden:`showFreeform ("chat", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "Smart", icon:"robot", toolTip:"Have ChatGPT Label and sort your cards for you!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {hidden:`showFreeform ("chat", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "AIs", icon:"AI Sort", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("robot"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - { title: "Like", icon:"heart", toolTip:"Add Like labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"like", funcs: {hidden:`showFreeform ("like", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Likes", icon:"Likes", toolTip:"Filter likes", width: 10, subMenu: this.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("like", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - { title: "Star", icon:"star", toolTip:"Add Star labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {hidden:`showFreeform ("star", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Stars", icon:"Stars", toolTip:"Filter stars", width: 80, subMenu: this.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("star", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - { title: "Idea", icon:"cloud", toolTip:"Add Idea labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"idea", funcs: {hidden:`showFreeform ("idea", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Ideas", icon:"Ideas", toolTip:"Filter ideas", width: 80, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // { title: "Custom", icon:"heart", toolTip:"Add Like labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"like", funcs: {hidden:`showFreeform ("like", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "1st", icon:"1st", toolTip:"Filter likes", width: 10, subMenu: this.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("like", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // { title: "Custom", icon:"star", toolTip:"Add Star labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {hidden:`showFreeform ("star", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "2nd", icon:"2nd", toolTip:"Filter stars", width: 80, subMenu: this.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("star", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // { title: "Custom", icon:"cloud", toolTip:"Add Idea labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"idea", funcs: {hidden:`showFreeform ("idea", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "3rd", icon:"3rd", toolTip:"Filter ideas", width: 80, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, ] } static cardGroupTools(icon: string): Button[] { @@ -794,8 +805,22 @@ pie title Minerals in my tap water { title: "Doc", icon: "Doc", toolTip: "Freeform Doc tools", subMenu: CurrentUserUtils.freeTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode, true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available { title: "View", icon: "View", toolTip: "View tools", subMenu: CurrentUserUtils.viewTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available { title: "Stack", icon: "View", toolTip: "Stacking tools", subMenu: CurrentUserUtils.stackTools(), expertMode: false, toolType:CollectionViewType.Stacking, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available - { title: "Card", icon: "Sort", toolTip: "Card sort", subMenu: CurrentUserUtils.cardTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available - { title: "Label", icon: "Label", toolTip: "Assign card labels", subMenu: CurrentUserUtils.labelTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available + + + // { title: "SortType", btnList: new List(["Time", "Type", "Color", "ChatGPT", "Custom 1", "Custom 2", "Custom 3" ]), + // toolTip: "Card Sort Type", btnType: ButtonType.DropdownList, ignoreClick: true, width: 100, scripts: { script: '{ return showFreeform(value, _readOnly_); }' }, + // // funcs: {hidden: `!SelectedDocType("card", this.expertMode)`} + // }, + // { title: "Visibility", icon:"Visibility", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("robot"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, width: 100, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // // { title: "Custom", icon:"heart", toolTip:"Add Like labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"like", funcs: {hidden:`showFreeform ("like", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "Visibility", icon:"Visibility", toolTip:"Filter likes", width: 10, subMenu: this.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("like", true)`, width: 100, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // // { title: "Custom", icon:"star", toolTip:"Add Star labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {hidden:`showFreeform ("star", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "Visibility", icon:"Visibility", toolTip:"Filter stars", width: 80, subMenu: this.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("star", true)`, width: 100, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // // { title: "Custom", icon:"cloud", toolTip:"Add Idea labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"idea", funcs: {hidden:`showFreeform ("idea", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "Visibility", icon:"Visibility", toolTip:"Filter ideas", width: 80, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`,width: 100, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + + { title: "Card", icon: "Card", toolTip: "Card View Tools", subMenu: CurrentUserUtils.cardTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available + // { title: "Create", icon: "Create", toolTip: "Assign card labels", subMenu: CurrentUserUtils.labelTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available { title: "Web", icon: "Web", toolTip: "Web functions", subMenu: CurrentUserUtils.webTools(), expertMode: false, toolType:DocumentType.WEB, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when Web is selected { title: "Video", icon: "Video", toolTip: "Video functions", subMenu: CurrentUserUtils.videoTools(), expertMode: false, toolType:DocumentType.VID, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when video is selected { title: "Image", icon: "Image", toolTip: "Image functions", subMenu: CurrentUserUtils.imageTools(), expertMode: false, toolType:DocumentType.IMG, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when image is selected @@ -1109,4 +1134,4 @@ ScriptingGlobals.add(function importDocument() { return CurrentUserUtils.import // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function setInkToolDefaults() { Doc.ActiveTool = InkTool.None; }); // eslint-disable-next-line prefer-arrow-callback -ScriptingGlobals.add(function getSharingDoc() { return Doc.SharingDoc() }); +ScriptingGlobals.add(function getSharingDoc() { return Doc.SharingDoc() }); \ No newline at end of file diff --git a/src/client/views/collections/CollectionCardDeckView.scss b/src/client/views/collections/CollectionCardDeckView.scss index a089b248d..8a721a626 100644 --- a/src/client/views/collections/CollectionCardDeckView.scss +++ b/src/client/views/collections/CollectionCardDeckView.scss @@ -28,7 +28,7 @@ // width: 300px; background-color: rgb(218, 218, 218); /* Background color of the container */ border-radius: 50px; /* Rounds the corners of the container */ - transform: translateY(75px); + transform: translateY(25px); // box-shadow: 0 4px 8px rgba(0,0,0,0.1); /* Optional: Adds shadow for depth */ align-items: center; /* Centers buttons vertically */ justify-content: start; /* Centers buttons horizontally */ diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 0ca3c5a44..127c4dc48 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -254,8 +254,8 @@ export class CollectionCardView extends CollectionSubView() { } // prettier-ignore })(); - console.log(ClientUtils.hexToHsv(StrCast(docA.backgroundColor)) ?? 9999 + "docA col") - console.log(ClientUtils.hexToHsv(StrCast(docB.backgroundColor)) ?? 9999 + "docB col") + // console.log(ClientUtils.hexToHsv(StrCast(docA.backgroundColor)) ?? 9999 + "docA col") + // console.log(ClientUtils.hexToHsv(StrCast(docB.backgroundColor)) ?? 9999 + "docB col") const out = typeA < typeB ? -1 : typeA > typeB ? 1 : 0; diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 7730ed385..107e21e08 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -135,10 +135,10 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { }); // eslint-disable-next-line prefer-arrow-callback -ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' | 'clusters' | 'viewAll' | 'fitOnce', checkResult?: boolean, persist?: boolean) { +ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' | 'clusters' | 'viewAll' | 'fitOnce', checkResult?: boolean, persist?: boolean, ) { const selected = DocumentView.SelectedDocs().lastElement(); // prettier-ignore - const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'like' | 'star' | 'idea' | 'chat' | '1' | '2' | '3' | '4', + const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | "Time" | "Type"| "Color"| "ChatGPT"| "Custom 1"| "Custom 2"| "Custom 3" , { waitForRender?: boolean; checkResult: (doc: Doc) => any; @@ -173,48 +173,49 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' checkResult: (doc: Doc) => BoolCast(Doc.UserDoc().defaultToFlashcards, false), setDoc: (doc: Doc, dv: DocumentView) => Doc.UserDoc().defaultToFlashcards = !Doc.UserDoc().defaultToFlashcards, }], - ['time', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "time", + ['Time', { + checkResult: (doc: Doc) => {StrCast(doc?.cardSort); + console.log(StrCast(doc?.cardSort + "card sort"))}, setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "time", }], - ['docType', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "type", + ['Type', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort), setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "type", }], - ['color', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "color", + ['Color', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort), setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "color", }], - ['links', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "links", - setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "links", - }], - ['like', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "like", + // ['links', { + // checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "links", + // setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "links", + // }], + ['Custom 1', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) + " 1", setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; doc.cardSort_customField = "like"; doc.cardSort_visibleSortGroups = new List(); } }], - ['star', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "star", + ['Custom 2', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) + " 2", setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; doc.cardSort_customField = "star"; doc.cardSort_visibleSortGroups = new List(); } }], - ['idea', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "idea", + ['Custom 3', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) + " 3", setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; doc.cardSort_customField = "idea"; doc.cardSort_visibleSortGroups = new List(); } }], - ['chat', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "chat", + ['ChatGPT', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort_customField), setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; doc.cardSort_customField = "chat"; @@ -233,6 +234,7 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' } if (checkResult) { + console.log("HIIIIII") return map.get(attr)?.checkResult(selected); } const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; -- cgit v1.2.3-70-g09d2 From c5b806c3b449cd81aee673a01238c4dae9402cf3 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Thu, 6 Jun 2024 14:59:04 -0400 Subject: lol --- src/client/util/CurrentUserUtils.ts | 46 +++--- src/client/views/global/globalScripts.ts | 182 ++++++++++++++++++--- src/client/views/nodes/FontIconBox/FontIconBox.tsx | 2 +- 3 files changed, 184 insertions(+), 46 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index f2ef9b943..438867eeb 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -660,40 +660,40 @@ pie title Minerals in my tap water } static cardTools(): Button[] { return [ - { btnList: new List(["Time", "Type", "Color", "ChatGPT", "Custom 1", "Custom 2", "Custom 3" ]), - title: "Sort Type", toolTip: "Card Sort Type", btnType: ButtonType.DropdownList, ignoreClick: true, width: 150, scripts: { script: '{ return showFreeform(value, _readOnly_); }'}}, - // { title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, toolType:"font", ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'}, + { btnList: new List(["Time", "Type", "Color", "Chat GPT", "Custom 1", "Custom 2", "Custom 3" ]), + title: "Sort Type", toolTip: "Card Sort Type", btnType: ButtonType.DropdownList, ignoreClick: true, width: 150, scripts: { script: '{ return setCardSort(value, _readOnly_); }'}}, + // { title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, toolType:"font", ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'}, // btnList: new List(["Roboto", "Roboto Mono", "Nunito", "Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]) }, // { title: "Time", icon:"hourglass-half", toolTip:"Sort by most recent document creation", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"time", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // { title: "Type", icon:"eye", toolTip:"Sort by document type", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"docType",funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "AIs", icon:"AI Sort", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("robot"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + { title: "AIs", icon:"Visibility", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("robot"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // { title: "Custom", icon:"heart", toolTip:"Add Like labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"like", funcs: {hidden:`showFreeform ("like", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "1st", icon:"1st", toolTip:"Filter likes", width: 10, subMenu: this.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("like", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + { title: "1st", icon:"Visibility", toolTip:"Filter likes", width: 150, subMenu: this.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("like", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // { title: "Custom", icon:"star", toolTip:"Add Star labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {hidden:`showFreeform ("star", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "2nd", icon:"2nd", toolTip:"Filter stars", width: 80, subMenu: this.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("star", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + { title: "2nd", icon:"Visibility", toolTip:"Filter stars", width: 150, subMenu: this.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("star", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // { title: "Custom", icon:"cloud", toolTip:"Add Idea labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"idea", funcs: {hidden:`showFreeform ("idea", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "3rd", icon:"3rd", toolTip:"Filter ideas", width: 80, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + { title: "3rd", icon:"Visibility", toolTip:"Filter ideas", width: 150, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, ] } - static labelTools(): Button[] { - return [ - // { title: "Smart", icon:"robot", toolTip:"Have ChatGPT Label and sort your cards for you!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {hidden:`showFreeform ("chat", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "AIs", icon:"AI Sort", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("robot"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - // { title: "Custom", icon:"heart", toolTip:"Add Like labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"like", funcs: {hidden:`showFreeform ("like", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "1st", icon:"1st", toolTip:"Filter likes", width: 10, subMenu: this.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("like", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - // { title: "Custom", icon:"star", toolTip:"Add Star labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {hidden:`showFreeform ("star", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "2nd", icon:"2nd", toolTip:"Filter stars", width: 80, subMenu: this.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("star", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - // { title: "Custom", icon:"cloud", toolTip:"Add Idea labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"idea", funcs: {hidden:`showFreeform ("idea", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "3rd", icon:"3rd", toolTip:"Filter ideas", width: 80, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - ] - } + // static labelTools(): Button[] { + // return [ + // // { title: "Smart", icon:"robot", toolTip:"Have ChatGPT Label and sort your cards for you!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {hidden:`showFreeform ("chat", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "AIs", icon:"AI Sort", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("robot"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // // { title: "Custom", icon:"heart", toolTip:"Add Like labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"like", funcs: {hidden:`showFreeform ("like", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "1st", icon:"1st", toolTip:"Filter likes", width: 10, subMenu: this.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("like", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // // { title: "Custom", icon:"star", toolTip:"Add Star labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {hidden:`showFreeform ("star", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "2nd", icon:"2nd", toolTip:"Filter stars", width: 80, subMenu: this.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("star", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // // { title: "Custom", icon:"cloud", toolTip:"Add Idea labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"idea", funcs: {hidden:`showFreeform ("idea", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "3rd", icon:"3rd", toolTip:"Filter ideas", width: 80, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // ] + // } static cardGroupTools(icon: string): Button[] { return [ - { title: "", icon, toolTip:"Click to toggle group 1's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"1", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "", icon, toolTip:"Click to toggle group 2's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"2", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "", icon, toolTip:"Click to toggle group 3's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"3", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "", icon, toolTip:"Click to toggle group 4's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"4", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Group 1", icon, toolTip:"Click to toggle group 1's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"1", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Group 2", icon, toolTip:"Click to toggle group 2's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"2", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Group 3", icon, toolTip:"Click to toggle group 3's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"3", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Group 4", icon, toolTip:"Click to toggle group 4's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"4", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "", icon, toolTip:"Click to toggle group 5's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"5", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "", icon, toolTip:"Click to toggle group 6's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"6", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "", icon, toolTip:"Click to toggle group 7's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"7", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 107e21e08..0a6f78e2e 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -135,10 +135,10 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { }); // eslint-disable-next-line prefer-arrow-callback -ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' | 'clusters' | 'viewAll' | 'fitOnce', checkResult?: boolean, persist?: boolean, ) { +ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' | 'clusters' | 'viewAll' | 'fitOnce', checkResult?: boolean, persist?: boolean) { const selected = DocumentView.SelectedDocs().lastElement(); // prettier-ignore - const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | "Time" | "Type"| "Color"| "ChatGPT"| "Custom 1"| "Custom 2"| "Custom 3" , + const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'like' | 'star' | 'idea' | 'chat' | '1' | '2' | '3' | '4', { waitForRender?: boolean; checkResult: (doc: Doc) => any; @@ -173,49 +173,48 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' checkResult: (doc: Doc) => BoolCast(Doc.UserDoc().defaultToFlashcards, false), setDoc: (doc: Doc, dv: DocumentView) => Doc.UserDoc().defaultToFlashcards = !Doc.UserDoc().defaultToFlashcards, }], - ['Time', { - checkResult: (doc: Doc) => {StrCast(doc?.cardSort); - console.log(StrCast(doc?.cardSort + "card sort"))}, + ['time', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "time", setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "time", }], - ['Type', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort), + ['docType', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "type", setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "type", }], - ['Color', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort), + ['color', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "color", setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "color", }], - // ['links', { - // checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "links", - // setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "links", - // }], - ['Custom 1', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) + " 1", + ['links', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "links", + setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "links", + }], + ['like', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "like", setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; doc.cardSort_customField = "like"; doc.cardSort_visibleSortGroups = new List(); } }], - ['Custom 2', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) + " 2", + ['star', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "star", setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; doc.cardSort_customField = "star"; doc.cardSort_visibleSortGroups = new List(); } }], - ['Custom 3', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) + " 3", + ['idea', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "idea", setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; doc.cardSort_customField = "idea"; doc.cardSort_visibleSortGroups = new List(); } }], - ['ChatGPT', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort_customField), + ['chat', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "chat", setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; doc.cardSort_customField = "chat"; @@ -234,7 +233,7 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' } if (checkResult) { - console.log("HIIIIII") + // console.log("HIIIIII") return map.get(attr)?.checkResult(selected); } const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; @@ -249,6 +248,144 @@ ScriptingGlobals.add(function cardHasLabel(label: string) { return labelNum < 4 || (selected && DocListCast(selected[Doc.LayoutFieldKey(selected)]).some(doc => doc[StrCast(selected.cardSort_customField)] == labelNum)); }, ''); +// ScriptingGlobals.add(function setCardSort(attr: "Time" | "Type"| "Color"| "ChatGPT"| "Custom 1"| "Custom 2"| "Custom 3", value?: any, checkResult?: boolean) { +// // const editorView = RichTextMenu.Instance?.TextView?.EditorView; +// const selected = DocumentView.SelectedDocs().lastElement(); + +// // prettier-ignore +// const map: Map<"Time" | "Type"| "Color"| "ChatGPT"| "Custom 1"| "Custom 2"| "Custom 3", { checkResult: (doc: Doc) => any; setDoc: (doc: Doc) => void;}> = new Map([ +// ['Time', { + +// checkResult: (doc: Doc) => {StrCast(doc?.cardSort); +// console.log(StrCast(doc?.cardSort + "card sort"))}, +// setDoc: (doc: Doc) => {doc.cardSort = "time" +// console.log("hewwo")} + +// , +// }], +// ['Type', { +// checkResult: (doc: Doc) => StrCast(doc?.cardSort), +// setDoc: (doc: Doc) => doc.cardSort = "type", +// }], +// ['Color', { +// checkResult: (doc: Doc) => StrCast(doc?.cardSort), +// setDoc: (doc: Doc) => doc.cardSort = "color", +// }], +// // ['links', { +// // checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "links", +// // setDoc: (doc: Doc) => doc.cardSort = "links", +// // }], +// ['Custom 1', { +// checkResult: (doc: Doc) => StrCast(doc?.cardSort) + " 1", +// setDoc: (doc: Doc) => { +// doc.cardSort = "custom"; +// doc.cardSort_customField = "like"; +// doc.cardSort_visibleSortGroups = new List(); +// } +// }], +// ['Custom 2', { +// checkResult: (doc: Doc) => StrCast(doc?.cardSort) + " 2", +// setDoc: (doc: Doc) => { +// doc.cardSort = "custom"; +// doc.cardSort_customField = "star"; +// doc.cardSort_visibleSortGroups = new List(); +// } +// }], +// ['Custom 3', { +// checkResult: (doc: Doc) => StrCast(doc?.cardSort) + " 3", +// setDoc: (doc: Doc) => { +// doc.cardSort = "custom"; +// doc.cardSort_customField = "idea"; +// doc.cardSort_visibleSortGroups = new List(); +// } +// }], +// ['ChatGPT', { +// checkResult: (doc: Doc) => StrCast(doc?.cardSort_customField), +// setDoc: (doc: Doc) => { +// doc.cardSort = "custom"; +// doc.cardSort_customField = "chat"; +// doc.cardSort_visibleSortGroups = new List(); +// }, +// }], +// ]); + +// for (let i = 0; i < 8; i++) { +// map.set((i + 1 + '') as any, { +// checkResult: (doc: Doc) => NumListCast(doc?.cardSort_visibleSortGroups).includes(i), +// setDoc: (doc: Doc) => { +// const list = NumListCast(doc.cardSort_visibleSortGroups); +// doc.cardSort_visibleSortGroups = new List(list.includes(i) ? list.filter(d => d !== i) : [...list, i]); +// }, +// }); +// } + +// if (checkResult) { +// console.log(attr + "attricute") +// console.log(map.get(attr)?.checkResult(selected) + "check result") +// return map.get(attr)?.checkResult(selected); +// } + +// console.log(attr + "attricute lol") + +// // const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; +// DocumentView.Selected().map(dv => map.get(attr)?.setDoc(dv.layoutDoc)); +// // setTimeout(() => batch.end(), 100); +// return undefined; + +// // map.get(attr)?.setDoc?.(); +// // return undefined; +// }); + +ScriptingGlobals.add(function setCardSort(value?: any, checkResult?: boolean) { + // const editorView = RichTextMenu.Instance?.TextView?.EditorView; + const selected = DocumentView.SelectedDocs().lastElement(); + + if (checkResult) { + // console.log(attr + "attricute") + // console.log(map.get(attr)?.checkResult(selected) + "check result") + console.log(StrCast(selected?.cardSort) + "check") + return StrCast(selected?.cardSort); + } + + function docFields(doc: Doc): void { + switch(value){ + case 'Custom 1': + doc.cardSort_customField = "like"; + doc.cardSort_visibleSortGroups = new List(); + break; + case 'Custom 2': + doc.cardSort_customField = "star"; + doc.cardSort_visibleSortGroups = new List(); + break; + case 'Custom 3': + doc.cardSort_customField = "idea"; + doc.cardSort_visibleSortGroups = new List(); + break; + case 'Chat GPT': + doc.cardSort = "custom"; + doc.cardSort_customField = "chat"; + doc.cardSort_visibleSortGroups = new List(); + break; + default: + break; + } + } + + // const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; + DocumentView.Selected().map(dv => { + if (value != 'Chat GPT') { + + dv.Document.cardSort = value.trim().split(/\s+/)[0].toLowerCase(); + } + docFields(dv.Document); + }); + + return undefined; + + // map.get(attr)?.setDoc?.(); + // return undefined; +}); + // ScriptingGlobals.add(function setCardSortAttr(attr: 'time' | 'docType' | 'color', value: any, checkResult?: boolean) { // // const editorView = RichTextMenu.Instance?.TextView?.EditorView; // const selected = SelectionManager.Docs.lastElement(); @@ -315,6 +452,7 @@ ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highligh ]); if (checkResult) { + // console.log(map.get(attr)?.checkResult() + "font check result") return map.get(attr)?.checkResult(); } map.get(attr)?.setDoc?.(); diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index ffb668b03..8317d62a6 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -192,7 +192,7 @@ export class FontIconBox extends ViewBoxBaseComponent() { } else { text = script?.script.run({ this: this.Document, value: '', _readOnly_: true }).result; // text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily); - getStyle = (val: string) => ({ fontFamily: val }); + // getStyle = (val: string) => ({ fontFamily: val }); } // Get items to place into the list -- cgit v1.2.3-70-g09d2 From cca4b5bbc32ccfaafbaba9306545eaddc6953954 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Mon, 10 Jun 2024 12:32:20 -0400 Subject: hm --- src/client/documents/Documents.ts | 1 + src/client/util/CurrentUserUtils.ts | 2 +- src/client/views/collections/CollectionCardDeckView.tsx | 13 +++++++++++++ src/client/views/global/globalScripts.ts | 6 ++++-- src/client/views/pdf/PDFViewer.tsx | 2 +- 5 files changed, 20 insertions(+), 4 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index a67e6b4f6..34407c641 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -479,6 +479,7 @@ export class DocumentOptions { userColor?: STRt = new StrInfo('color associated with a Dash user (seen in header fields of shared documents)'); cardSort?: STRt = new StrInfo('way cards are sorted in deck view'); + cardSortForDropDown?: STRt = new StrInfo('needed for dropdown and i dont know why') cardSort_customField?: STRt = new StrInfo('field key used for sorting cards'); cardSort_visibleSortGroups?: List; // which sorting values are being filtered (shown) } diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 438867eeb..2ca2ce9c9 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -661,7 +661,7 @@ pie title Minerals in my tap water static cardTools(): Button[] { return [ { btnList: new List(["Time", "Type", "Color", "Chat GPT", "Custom 1", "Custom 2", "Custom 3" ]), - title: "Sort Type", toolTip: "Card Sort Type", btnType: ButtonType.DropdownList, ignoreClick: true, width: 150, scripts: { script: '{ return setCardSort(value, _readOnly_); }'}}, + title: "Sort Type", toolTip: "Card Sort Type", btnType: ButtonType.DropdownList, ignoreClick: true, width: 100, scripts: { script: '{ return setCardSort(value, _readOnly_); }'}}, // { title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, toolType:"font", ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'}, // btnList: new List(["Roboto", "Roboto Mono", "Nunito", "Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]) }, // { title: "Time", icon:"hourglass-half", toolTip:"Sort by most recent document creation", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"time", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 127c4dc48..d68fb57f8 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -19,6 +19,7 @@ import { DocumentView } from '../nodes/DocumentView'; import { GPTPopup, GPTPopupMode } from '../pdf/GPTPopup/GPTPopup'; import './CollectionCardDeckView.scss'; import { CollectionSubView } from './CollectionSubView'; +import { FieldsDropdown } from '../FieldsDropdown'; enum cardSortings { Time = 'time', @@ -384,6 +385,8 @@ export class CollectionCardView extends CollectionSubView() { return response; // Return the response from gptImageLabel } catch (error) { console.log('bad things have happened'); + + console.log(error) } return ''; }; @@ -517,6 +520,16 @@ export class CollectionCardView extends CollectionSubView() { onMouseLeave={() => this.setHoveredNodeIndex(-1)}> {this.renderCards()} +
+ { + this.layoutDoc._pivotField = fieldKey; + // this.removeEmptyColumns(); + }, 'change pivot field')} + placeholder={StrCast(this.layoutDoc._pivotField)} + /> +
); } diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 0a6f78e2e..549cb5c8f 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -344,7 +344,8 @@ ScriptingGlobals.add(function setCardSort(value?: any, checkResult?: boolean) { // console.log(attr + "attricute") // console.log(map.get(attr)?.checkResult(selected) + "check result") console.log(StrCast(selected?.cardSort) + "check") - return StrCast(selected?.cardSort); + const hi = StrCast(selected?.cardSort) + return StrCast(selected?.cardSortForDropDown) ?? "Time"; } function docFields(doc: Doc): void { @@ -373,8 +374,9 @@ ScriptingGlobals.add(function setCardSort(value?: any, checkResult?: boolean) { // const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; DocumentView.Selected().map(dv => { + dv.Document.cardSortForDropDown = value + if (value != 'Chat GPT') { - dv.Document.cardSort = value.trim().split(/\s+/)[0].toLowerCase(); } docFields(dv.Document); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index db47a84e1..72448e851 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -33,7 +33,7 @@ import './PDFViewer.scss'; // pdfjsLib.GlobalWorkerOptions.workerSrc = `/assets/pdf.worker.js`; // The workerSrc property shall be specified. -Pdfjs.GlobalWorkerOptions.workerSrc = 'https://unpkg.com/pdfjs-dist@4.3.136/build/pdf.worker.mjs'; +Pdfjs.GlobalWorkerOptions.workerSrc = 'https://unpkg.com/pdfjs-dist@4.2.67/build/pdf.worker.mjs'; interface IViewerProps extends FieldViewProps { pdfBox: PDFBox; -- cgit v1.2.3-70-g09d2 From 3f940bd45fd1bf72f6c16edc188f754b01f689ba Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Fri, 21 Jun 2024 15:11:23 -0400 Subject: yay dragging --- src/client/documents/Documents.ts | 3 +- src/client/util/CurrentUserUtils.ts | 12 +- src/client/views/MainView.tsx | 3 +- .../views/collections/CollectionCardDeckView.tsx | 231 ++++++++++++--------- 4 files changed, 149 insertions(+), 100 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 34407c641..a190fe11b 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -479,8 +479,9 @@ export class DocumentOptions { userColor?: STRt = new StrInfo('color associated with a Dash user (seen in header fields of shared documents)'); cardSort?: STRt = new StrInfo('way cards are sorted in deck view'); - cardSortForDropDown?: STRt = new StrInfo('needed for dropdown and i dont know why') + // cardSortForDropDown?: STRt = new StrInfo('needed for dropdown and i dont know why') cardSort_customField?: STRt = new StrInfo('field key used for sorting cards'); + cardSort_activeIcons?: List; cardSort_visibleSortGroups?: List; // which sorting values are being filtered (shown) } diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 2ca2ce9c9..94eee6711 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -660,13 +660,15 @@ pie title Minerals in my tap water } static cardTools(): Button[] { return [ - { btnList: new List(["Time", "Type", "Color", "Chat GPT", "Custom 1", "Custom 2", "Custom 3" ]), - title: "Sort Type", toolTip: "Card Sort Type", btnType: ButtonType.DropdownList, ignoreClick: true, width: 100, scripts: { script: '{ return setCardSort(value, _readOnly_); }'}}, + // { btnList: new List(["Time", "Type", "Color", "Chat GPT", "Custom 1", "Custom 2", "Custom 3" ]), + // title: "Sort Type", toolTip: "Card Sort Type", btnType: ButtonType.DropdownList, ignoreClick: true, width: 100, scripts: { script: '{ return setCardSort(value, _readOnly_); }'}}, // { title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, toolType:"font", ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'}, // btnList: new List(["Roboto", "Roboto Mono", "Nunito", "Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]) }, - // { title: "Time", icon:"hourglass-half", toolTip:"Sort by most recent document creation", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"time", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "Type", icon:"eye", toolTip:"Sort by document type", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"docType",funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Time", icon:"hourglass-half", toolTip:"Sort by most recent document creation", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"time", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Type", icon:"eye", toolTip:"Sort by document type", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"docType",funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "AI Sort", icon:"palette", toolTip:"Have Chat GPT sort your cards for you !", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "AIs", icon:"Visibility", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("robot"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // { title: "Custom", icon:"heart", toolTip:"Add Like labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"like", funcs: {hidden:`showFreeform ("like", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "1st", icon:"Visibility", toolTip:"Filter likes", width: 150, subMenu: this.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("like", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f61c784df..b06d785e1 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -548,7 +548,8 @@ export class MainView extends ObservableReactComponent<{}> { fa.faRobot, fa.faSatellite, fa.faStar, - fa.faCloud + fa.faCloud, + fa.faBolt ] ); } diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 76536ed48..2ad7f0ed1 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -3,7 +3,7 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { ClientUtils, DashColor, returnFalse, returnZero } from '../../../ClientUtils'; import { emptyFunction, numberRange } from '../../../Utils'; -import { Doc, NumListCast } from '../../../fields/Doc'; +import { Doc, NumListCast, StrListCast } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { BoolCast, Cast, DateCast, NumCast, RTFCast, ScriptCast, StrCast } from '../../../fields/Types'; @@ -27,12 +27,14 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { SettingsManager } from '../../util/SettingsManager'; import { Tooltip } from '@mui/material'; import { dropActionType } from '../../util/DropActionTypes'; +import { List } from '../../../fields/List'; enum cardSortings { Time = 'time', Type = 'type', Color = 'color', Custom = 'custom', + Drag = 'drag', None = '', } @observer @@ -48,7 +50,7 @@ export class CollectionCardView extends CollectionSubView() { @observable _docRefs = new ObservableMap(); _draggerRef = React.createRef(); @observable _maxRowCount = 10; - @observable _docsDraggedIndex: number[] = []; + @observable _docDraggedIndex: number = -1; @observable _isACardBeingDragged: boolean = false; @observable overIndex: number = -1; @@ -73,12 +75,6 @@ export class CollectionCardView extends CollectionSubView() { } }; - protected createDashEventsTarget = (ele: HTMLDivElement | null) => { - this._dropDisposer?.(); - if (ele) { - this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc); - } - }; constructor(props: any) { super(props); @@ -145,12 +141,7 @@ export class CollectionCardView extends CollectionSubView() { return regularDocs; } - /** - * Determines the order in which the cards will be rendered depending on the current sort type - */ - @computed get sortedDocs() { - return this.sort(this.childDocsWithoutLinks, this.cardSort, BoolCast(this.layoutDoc.sortDesc)); - } + /** * Number of rows of cards to be rendered @@ -226,27 +217,71 @@ export class CollectionCardView extends CollectionSubView() { return Math.abs(stepMag * (apex - index - 1)) - rowOffset; }; - /** - * Translates the selected node to the middle fo the screen - * @param index - * @returns - */ - // translateSelected = (index: number): number => { - // // if (this.isSelected(index)) { - // const middleOfPanel = this._props.PanelWidth() / 2; - // const scaledNodeWidth = this.panelWidth() * 1.25; + findCardDropIndex = (mouseX: number, mouseY: number) => { + + const amCardsTotal = this.sortedDocs.length + let index = 0; + const cardWidth = amCardsTotal < this._maxRowCount ? this._props.PanelWidth() / amCardsTotal : this._props.PanelWidth() / this._maxRowCount; + + // Calculate the adjusted X position accounting for the initial offset + let adjustedX = mouseX + + const amRows = Math.ceil(amCardsTotal / this._maxRowCount); + const rowHeight = this._props.PanelHeight( ) / amRows + const currRow = Math.floor((mouseY - 100) / rowHeight) //rows start at 0 + + if (adjustedX < 0) { + return 0; // Before the first column + } + + if (amCardsTotal < this._maxRowCount) { + index = Math.floor(adjustedX / cardWidth); + } + + else if (currRow != amRows -1 ){ + index = Math.floor(adjustedX / cardWidth) + (currRow * this._maxRowCount) + } - // // Calculate the position of the node's left edge before scaling - // const nodeLeftEdge = index * this.panelWidth(); - // // Find the center of the node after scaling - // const scaledNodeCenter = nodeLeftEdge + scaledNodeWidth / 2; + else { + // console.log(amRows + "am rows") + const rowAmCards = amCardsTotal - (currRow * this._maxRowCount) + const offset = ((this._maxRowCount - rowAmCards ) / 2) * cardWidth + adjustedX = mouseX - offset - // // Calculate the translation needed to align the scaled node's center with the panel's center - // const translation = middleOfPanel - scaledNodeCenter - scaledNodeWidth - scaledNodeWidth / 4; + index = Math.floor(adjustedX / cardWidth) + (currRow * this._maxRowCount); + } + return index; + }; - // return translation; - // }; + @action + onPointerMove = (e: React.PointerEvent) => { + if (DragManager.docsBeingDragged.length != 0 ) { + this._isACardBeingDragged = true + + const newIndex = this.findCardDropIndex(e.clientX, e.clientY); + + if (newIndex !== this._docDraggedIndex && newIndex != -1) { + this._docDraggedIndex = newIndex; + } + } + }; + + onInternalDrop = (e: Event, de: DragManager.DropEvent) => { + if (de.complete.docDragData) { + this._isACardBeingDragged = false; + this._docDraggedIndex = -1; + e.stopPropagation() + const draggedDocs = de.complete.docDragData?.draggedDocuments; + return true; + } + return false; + }; + + @computed get sortedDocs() { + // console.log("hi hi hi") + return this.sort(this.childDocsWithoutLinks, this.cardSort, BoolCast(this.layoutDoc.sortDesc), this._docDraggedIndex); + } /** * Called in the sortedDocsType method. Compares the cards' value in regards to the desired sort type-- earlier cards are move to the * front, latter cards to the back @@ -255,7 +290,8 @@ export class CollectionCardView extends CollectionSubView() { * @param isDesc * @returns */ - sort = (docs: Doc[], sortType: cardSortings, isDesc: boolean) => { + sort = (docs: Doc[], sortType: cardSortings, isDesc: boolean, dragIndex: number) => { + // console.log('HIIIIIIIII') if (sortType === cardSortings.None) return docs; docs.sort((docA, docB) => { const [typeA, typeB] = (() => { @@ -281,9 +317,25 @@ export class CollectionCardView extends CollectionSubView() { return isDesc ? -out : out; // Reverse the sort order if descending is true }); + if (dragIndex != -1){ + // console.log("what what") + + const draggedDoc = DragManager.docsBeingDragged[0] + const originalIndex = docs.findIndex(doc => doc === draggedDoc); + + + // Remove the dragged document from its original position + docs.splice(originalIndex, 1); + // Insert the dragged document at the new position + docs.splice(dragIndex, 0, draggedDoc); + // } + } + return docs; }; + + displayDoc = (doc: Doc, screenToLocalTransform: () => Transform) => ( { - this.cardSort_customField && (doc[this.cardSort_customField] = buttonID); - }, 'toggle custom button'); - + /** * A list of the text content of all the child docs. RTF documents will have just their text and pdf documents will have the first 50 words. * Image documents are converted to bse64 and gpt generates a description for them. all other documents use their title. This string is @@ -456,27 +499,37 @@ export class CollectionCardView extends CollectionSubView() { * @returns */ renderButtons = (doc: Doc, cardSort: cardSortings): JSX.Element | null => { - if (cardSort !== cardSortings.Custom) return null; + // if (cardSort !== cardSortings.Custom) return null; - const amButtons = Math.max( - 4, - this.childDocs?.reduce((set, d) => { - if (this.cardSort_customField) { - set.add(NumCast(d[this.cardSort_customField])); - } - return set; - }, new Set()).size ?? 0 - ); + const amButtons = 4 + + // const amButtons = Math.max( + // 4, + // this.childDocs?.reduce((set, d) => { + // if (this.cardSort_customField) { + // set.add(NumCast(d[this.cardSort_customField])); + // } + // return set; + // }, new Set()).size ?? 0 + // ); const activeButtonIndex = CollectionCardView.getButtonGroup(this.cardSort_customField, doc); + const totalWidth = amButtons * 72 + amButtons * 2 * 5 + 6; + const iconMap: { [key: number]: any } = { + 0: 'star', + 1: 'heart', + 2: 'cloud', + 3: 'bolt' + }; + return (
{numberRange(amButtons).map(i => ( - Click to add/remove this card from group {i + 1}
}> - ))} @@ -484,53 +537,44 @@ export class CollectionCardView extends CollectionSubView() { ); }; - getButtonIcon = (isActive: boolean): JSX.Element => { - const iconMap: { [key: string]: any } = { - like: 'heart', - chat: 'robot', - idea: 'cloud', - }; + /** + * Toggles the buttons between on and off when creating custom sort groupings/changing those created by gpt + * @param childPairIndex + * @param buttonID + * @param doc + */ + toggleButton = undoable((doc: Doc, icon: string) => { + + + + // this.cardSort_customField && (doc[this.cardSort_customField] = buttonID); + + // doc.cardSort_activeIcons = new List() + - const icon = iconMap[this.cardSort_customField ?? ''] || 'star'; + const list = StrListCast(doc.cardSort_activeIcons); + doc.cardSort_activeIcons = new List(list.includes(icon) ? list.filter(d => d !== icon) : [...list, icon]); + + + + // StrListCast(doc.cardSort_activeIcons).push(iconMap[buttonID]) + }, 'toggle card tag'); + + + getButtonIcon = (doc: Doc, icon: any): JSX.Element => { + + const isActive = StrListCast(doc.cardSort_activeIcons).includes(icon) + + console.log(StrListCast(doc.cardSort_activeIcons)) const color = isActive ? '#4476f7' : '#323232'; return ; }; - // @action - // onDragStart = (index: number) => { - // this.draggedIndex = index; - // }; - - // @action - // onDragOver = (index: number) => { - // if (this.draggedIndex !== index) { - // this.overIndex = index; - // } - // }; - - // @action - // onDrop = () => { - // if (this.draggedIndex !== -1 && this.overIndex !== -1) { - // const draggedDoc = this.sortedDocs[this.draggedIndex]; - // this.sortedDocs.splice(this.draggedIndex, 1); - // this.sortedDocs.splice(this.overIndex, 0, draggedDoc); - // this.draggedIndex = -1; - // this.overIndex = -1; - // } - // }; - - // @action - // onDragEnd = () => { - // this.draggedIndex = -1; - // this.overIndex = -1; - // }; - /** * Actually renders all the cards */ renderCards = () => { - console.log(DragManager.docsBeingDragged.length + 'drag ha'); const anySelected = this.childDocs.some(doc => DocumentView.SelectedDocs().includes(doc)); const isEmpty = this.childDocsWithoutLinks.length === 0; @@ -599,8 +643,9 @@ export class CollectionCardView extends CollectionSubView() { render() { return (
this.onPointerMove(e)} className="collectionCardView-outer" - ref={this.createDashEventsTarget} + ref={(ele: HTMLDivElement | null) => this.createDashEventsTarget(ele)} style={{ background: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor), color: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color), -- cgit v1.2.3-70-g09d2 From 2f92d924a8dc1675cd12b08bbac7f57b2335a7b2 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Mon, 24 Jun 2024 12:04:43 -0400 Subject: fixing --- src/client/util/CurrentUserUtils.ts | 5 +++-- src/client/views/collections/CollectionCardDeckView.tsx | 10 ---------- src/client/views/global/globalScripts.ts | 10 +++++----- 3 files changed, 8 insertions(+), 17 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 94eee6711..9cf3bfe9b 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -667,9 +667,10 @@ pie title Minerals in my tap water { title: "Time", icon:"hourglass-half", toolTip:"Sort by most recent document creation", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"time", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Type", icon:"eye", toolTip:"Sort by document type", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"docType",funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "AI Sort", icon:"palette", toolTip:"Have Chat GPT sort your cards for you !", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "AI Sort", icon:"robot", toolTip:"Have Chat GPT sort your cards for you !", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + - { title: "AIs", icon:"Visibility", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("robot"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // { title: "AIs", icon:"Visibility", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("robot"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // { title: "Custom", icon:"heart", toolTip:"Add Like labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"like", funcs: {hidden:`showFreeform ("like", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "1st", icon:"Visibility", toolTip:"Filter likes", width: 150, subMenu: this.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("like", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // { title: "Custom", icon:"star", toolTip:"Add Star labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {hidden:`showFreeform ("star", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 2ad7f0ed1..09cddda19 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -660,16 +660,6 @@ export class CollectionCardView extends CollectionSubView() { onMouseLeave={() => this.setHoveredNodeIndex(-1)}> {this.renderCards()}
-
- { - this.layoutDoc._pivotField = fieldKey; - // this.removeEmptyColumns(); - }, 'change pivot field')} - placeholder={StrCast(this.layoutDoc._pivotField)} - /> -
); } diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index cef913837..1344dd071 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -175,15 +175,15 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' }], ['time', { checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "time", - setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "time", + setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort === "time" ? doc.cardSort = '' : doc.cardSort = 'time', }], ['docType', { checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "type", - setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "type", + setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort === "type" ? doc.cardSort = '' : doc.cardSort = 'type', }], ['color', { checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "color", - setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "color", + setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort === "color" ? doc.cardSort = '' : doc.cardSort = 'color', }], ['links', { checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "links", @@ -216,8 +216,8 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' ['chat', { checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "chat", setDoc: (doc: Doc, dv: DocumentView) => { - doc.cardSort = "custom"; - doc.cardSort_customField = "chat"; + doc.cardSort === "custom" ? doc.cardSort = '' : doc.cardSort = 'custom'; + doc.cardSort_customField === "chat" ? doc.cardSort_customField = '' : doc.cardSort_customField = 'chat'; doc.cardSort_visibleSortGroups = new List(); }, }], -- cgit v1.2.3-70-g09d2 From 3a3d4433e0b4bfc134370ba4938f22cbed61428b Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Wed, 26 Jun 2024 14:17:18 -0400 Subject: sigh --- src/client/apis/gpt/GPT.ts | 7 +- src/client/documents/Documents.ts | 8 +- src/client/util/CurrentUserUtils.ts | 46 ++++--- .../views/collections/CollectionCardDeckView.tsx | 147 ++++++++++++--------- src/client/views/global/globalScripts.ts | 94 +++++++------ src/client/views/pdf/GPTPopup/GPTPopup.tsx | 1 + 6 files changed, 182 insertions(+), 121 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 585398204..40af70d99 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -42,8 +42,9 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { sort: { model: 'gpt-4o', maxTokens: 2048, - temp: 0.5, - prompt: "I'm going to give you a list of descriptions. Each one is separated by `======` on either side. Descriptions will vary in length, so make sure to only separate when you see `======`. Sort them into lists by shared content. Make sure each description is in only one list. Each list should be separated by `======` with the elements within it separated by `~~~~~~`. Immediately afterward, surrounded by `------` on BOTH SIDES, provide some insight into your reasoning for the way you sorted. It is VERY important that you format it exactly as described, ensuring the proper number of `=` `~` and `-` (6 of each) and no commas.Try to create around 4 groups, but a little more or less is ok. Also, I may provide some more insight after this colon:" + temp: 0.25, + prompt: "The user is going to give you a list of descriptions. Each one is separated by `======` on either side. Descriptions will vary in length, so make sure to only separate when you see `======`. Sort them by shared content. Make sure each description is only in the list once. Each item should be separated by `======`. Immediately afterward, surrounded by `------` on BOTH SIDES, provide some insight into your reasoning for the way you sorted (and mention nothing about the formatting details given in this description). It is VERY important that you format it exactly as described, ensuring the proper number of `=` and `-` (6 of each) and no commas" + // prompt: "I'm going to give you a list of descriptions. Each one is separated by `======` on either side. Descriptions will vary in length, so make sure to only separate when you see `======`. Sort them into lists by shared content. Make sure each description is in only one list. Each list should be separated by `======` with the elements within it separated by `~~~~~~`. Immediately afterward, surrounded by `------` on BOTH SIDES, provide some insight into your reasoning for the way you sorted. It is VERY important that you format it exactly as described, ensuring the proper number of `=` `~` and `-` (6 of each) and no commas.Try to create around 4 groups, but a little more or less is ok. Also, I may provide some more insight after this colon:" }, describe: { model: 'gpt-4-vision-preview', maxTokens: 2048, temp: 0, prompt: 'Describe these images in 3-5 words' }, chatcard: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'Answer the following question as a short flashcard response. Do not include a label.' }, @@ -75,7 +76,7 @@ const gptAPICall = async (inputTextIn: string, callType: GPTCallType, prompt?: a // dangerouslyAllowBrowser: true, // }; - const usePrompt = prompt ? opts.prompt + prompt : opts.prompt; + const usePrompt = prompt ? prompt + opts.prompt : opts.prompt; const messages: ChatCompletionMessageParam[] = [ { role: 'system', content: usePrompt }, { role: 'user', content: inputText }, diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index a190fe11b..53422b0c8 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -481,8 +481,12 @@ export class DocumentOptions { cardSort?: STRt = new StrInfo('way cards are sorted in deck view'); // cardSortForDropDown?: STRt = new StrInfo('needed for dropdown and i dont know why') cardSort_customField?: STRt = new StrInfo('field key used for sorting cards'); - cardSort_activeIcons?: List; - cardSort_visibleSortGroups?: List; // which sorting values are being filtered (shown) + cardSort_activeIcons?: List; //icons each card is tagges with + cardSort_visibleSortGroups?: List; // which sorting values are being filtered (shown) + + // cardSort_visibleSortGroups?: List; // which sorting values are being filtered (shown) + cardSort_isDesc?: BOOLt = new BoolInfo('whether the cards are sorted ascending or descending'); + test?: STRt = new StrInfo('testing for filtering') } export const DocOptions = new DocumentOptions(); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 9cf3bfe9b..48e4441de 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -668,15 +668,25 @@ pie title Minerals in my tap water { title: "Type", icon:"eye", toolTip:"Sort by document type", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"docType",funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "AI Sort", icon:"robot", toolTip:"Have Chat GPT sort your cards for you !", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + + { title: "Sort", toolTip: "Manage sort order / lock status", icon: "sort" , btnType: ButtonType.MultiToggleButton, toolType:"alignment", ignoreClick: true, + subMenu: [ + { title: "Ascending", toolTip: "Sort the cards in ascending order", btnType: ButtonType.ToggleButton, icon: "sort-up", toolType:"up", ignoreClick: true, scripts: {onClick: '{ return showFreeform(this.toolType, _readOnly_);}' }}, + { title: "Descending", toolTip: "Sort the cards in descending order",btnType: ButtonType.ToggleButton, icon: "sort-down",toolType:"down",ignoreClick: true, scripts: {onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, + ]}, + { title: "Filter", icon:"Filter", toolTip:"Filter cards by tags", width: 150, subMenu: this.cardGroupTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + + + - // { title: "AIs", icon:"Visibility", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("robot"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - // { title: "Custom", icon:"heart", toolTip:"Add Like labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"like", funcs: {hidden:`showFreeform ("like", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "1st", icon:"Visibility", toolTip:"Filter likes", width: 150, subMenu: this.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("like", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - // { title: "Custom", icon:"star", toolTip:"Add Star labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {hidden:`showFreeform ("star", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "2nd", icon:"Visibility", toolTip:"Filter stars", width: 150, subMenu: this.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("star", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - // { title: "Custom", icon:"cloud", toolTip:"Add Idea labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"idea", funcs: {hidden:`showFreeform ("idea", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "3rd", icon:"Visibility", toolTip:"Filter ideas", width: 150, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // // { title: "AIs", icon:"Visibility", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("robot"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // // { title: "Custom", icon:"heart", toolTip:"Add Like labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"like", funcs: {hidden:`showFreeform ("like", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "1st", icon:"Visibility", toolTip:"Filter likes", width: 150, subMenu: this.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("like", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // // { title: "Custom", icon:"star", toolTip:"Add Star labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {hidden:`showFreeform ("star", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "2nd", icon:"Visibility", toolTip:"Filter stars", width: 150, subMenu: this.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("star", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // // { title: "Custom", icon:"cloud", toolTip:"Add Idea labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"idea", funcs: {hidden:`showFreeform ("idea", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "3rd", icon:"Visibility", toolTip:"Filter ideas", width: 150, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, ] } // static labelTools(): Button[] { @@ -691,15 +701,21 @@ pie title Minerals in my tap water // { title: "3rd", icon:"3rd", toolTip:"Filter ideas", width: 80, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // ] // } - static cardGroupTools(icon: string): Button[] { + static cardGroupTools(): Button[] { return [ - { title: "Group 1", icon, toolTip:"Click to toggle group 1's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"1", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Group 2", icon, toolTip:"Click to toggle group 2's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"2", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Group 3", icon, toolTip:"Click to toggle group 3's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"3", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Group 4", icon, toolTip:"Click to toggle group 4's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"4", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "", icon, toolTip:"Click to toggle group 5's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"5", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "", icon, toolTip:"Click to toggle group 6's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"6", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "", icon, toolTip:"Click to toggle group 7's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"7", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Star", icon: "star", toolTip:"Click to toggle the star group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Heart", icon: "heart", toolTip:"Click to toggle the heart group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"heart", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Bolt", icon: "bolt", toolTip:"Click to toggle the bolt group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"bolt", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Cloud", icon: "cloud", toolTip:"Click to toggle the cloud group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"cloud", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + + + // { title: "Group 1", icon, toolTip:"Click to toggle group 1's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"1", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "Group 2", icon, toolTip:"Click to toggle group 2's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"2", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "Group 3", icon, toolTip:"Click to toggle group 3's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"3", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "Group 4", icon, toolTip:"Click to toggle group 4's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"4", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "", icon, toolTip:"Click to toggle group 5's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"5", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "", icon, toolTip:"Click to toggle group 6's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"6", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "", icon, toolTip:"Click to toggle group 7's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"7", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, ] } static viewTools(): Button[] { diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 09cddda19..d8f4362f1 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -34,7 +34,7 @@ enum cardSortings { Type = 'type', Color = 'color', Custom = 'custom', - Drag = 'drag', + Chat = 'chat', None = '', } @observer @@ -45,7 +45,7 @@ export class CollectionCardView extends CollectionSubView() { private _textToDoc = new Map(); @observable _forceChildXf = false; - @observable _isLoading = false; + // @observable _isLoading = false; @observable _hoveredNodeIndex = -1; @observable _docRefs = new ObservableMap(); _draggerRef = React.createRef(); @@ -94,9 +94,10 @@ export class CollectionCardView extends CollectionSubView() { }; componentDidMount(): void { + this.Document.childFilters_boolean = 'OR' this._disposers.sort = reaction( - () => ({ cardSort: this.cardSort, field: this.cardSort_customField }), - ({ cardSort, field }) => (cardSort === cardSortings.Custom && field === 'chat' ? this.openChatPopup() : GPTPopup.Instance.setVisible(false)) + () => ({ cardSort: this.cardSort }), + ({ cardSort}) => (cardSort === cardSortings.Chat ? this.openChatPopup() : GPTPopup.Instance.setVisible(false)) ); } @@ -112,6 +113,7 @@ export class CollectionCardView extends CollectionSubView() { @computed get cardSort() { return StrCast(this.Document.cardSort) as any as cardSortings; } + /** * how much to scale down the contents of the view so that everything will fit */ @@ -126,15 +128,13 @@ export class CollectionCardView extends CollectionSubView() { */ @computed get childDocsWithoutLinks() { const regularDocs = this.childDocs.filter(l => l.type !== DocumentType.LINK); - const activeGroups = NumListCast(this.Document.cardSort_visibleSortGroups); + const activeGroups = StrListCast(this.Document.cardSort_visibleSortGroups); - if (activeGroups.length > 0 && this.cardSort === cardSortings.Custom) { + if (activeGroups.length > 0) { return regularDocs.filter(doc => { - // Get the group number for the current index - const groupNumber = CollectionCardView.getButtonGroup(this.cardSort_customField, doc); - // Check if the group number is in the active groups - return groupNumber !== undefined && activeGroups.includes(groupNumber); - }); + const activeTags = StrListCast(doc.cardSort_activeIcons) + return activeTags !== undefined && activeTags.some(tag => activeGroups.includes(tag)); + }) } // Default return for non-custom cardSort or other cases, filtering out links @@ -217,7 +217,7 @@ export class CollectionCardView extends CollectionSubView() { return Math.abs(stepMag * (apex - index - 1)) - rowOffset; }; - findCardDropIndex = (mouseX: number, mouseY: number) => { + findCardDropIndex = (mouseX: number, mouseY: number, direction: 'left' | 'right') => { const amCardsTotal = this.sortedDocs.length let index = 0; @@ -257,8 +257,9 @@ export class CollectionCardView extends CollectionSubView() { onPointerMove = (e: React.PointerEvent) => { if (DragManager.docsBeingDragged.length != 0 ) { this._isACardBeingDragged = true - - const newIndex = this.findCardDropIndex(e.clientX, e.clientY); + + const direction = e.movementX > 0 ? 'right' : 'left'; + const newIndex = this.findCardDropIndex(e.clientX, e.clientY, direction); if (newIndex !== this._docDraggedIndex && newIndex != -1) { this._docDraggedIndex = newIndex; @@ -278,9 +279,13 @@ export class CollectionCardView extends CollectionSubView() { return false; }; + @computed get sortedDocs() { // console.log("hi hi hi") - return this.sort(this.childDocsWithoutLinks, this.cardSort, BoolCast(this.layoutDoc.sortDesc), this._docDraggedIndex); + // console.log(this.layoutDoc.cardSort_isDesc + "layoutdoc desc") + console.log(this.cardSort + "card sort") + + return this.sort(this.childDocsWithoutLinks, this.cardSort, BoolCast(this.layoutDoc.cardSort_isDesc), this._docDraggedIndex); } /** * Called in the sortedDocsType method. Compares the cards' value in regards to the desired sort type-- earlier cards are move to the @@ -291,48 +296,53 @@ export class CollectionCardView extends CollectionSubView() { * @returns */ sort = (docs: Doc[], sortType: cardSortings, isDesc: boolean, dragIndex: number) => { - // console.log('HIIIIIIIII') - if (sortType === cardSortings.None) return docs; - docs.sort((docA, docB) => { - const [typeA, typeB] = (() => { + // if (sortType === cardSortings.None) return docs; + + if(sortType !== cardSortings.None){ + docs.sort((docA, docB) => { + + const [typeA, typeB] = (() => { switch (sortType) { case cardSortings.Time: - return [DateCast(docA.author_date)?.date ?? Date.now(), - DateCast(docB.author_date)?.date ?? Date.now()]; + return [DateCast(docA.author_date)?.date ?? Date.now(), + DateCast(docB.author_date)?.date ?? Date.now()]; case cardSortings.Color: - return [ClientUtils.hexToHsv(StrCast(docA.backgroundColor)), // If docA.type is undefined, use an empty string - ClientUtils.hexToHsv(StrCast(docB.backgroundColor))]; // If docB.type is undefined, use an empty string + return [ClientUtils.hexToHsv(StrCast(docA.backgroundColor)), + ClientUtils.hexToHsv(StrCast(docB.backgroundColor))]; case cardSortings.Custom: - return [CollectionCardView.getButtonGroup(this.cardSort_customField, docA)??9999, - CollectionCardView.getButtonGroup(this.cardSort_customField, docB)??9999]; - default: return [StrCast(docA.type), // If docA.type is undefined, use an empty string - StrCast(docB.type)]; // If docB.type is undefined, use an empty string - } // prettier-ignore + return [CollectionCardView.getButtonGroup(this.cardSort_customField, docA) ?? 9999, + CollectionCardView.getButtonGroup(this.cardSort_customField, docB) ?? 9999]; + case cardSortings.Chat: + return [NumCast(docA.chat) ?? 9999, + NumCast(docB.chat) ?? 9999] + default: + return [StrCast(docA.type), StrCast(docB.type)] + } })(); - - // console.log(ClientUtils.hexToHsv(StrCast(docA.backgroundColor)) ?? 9999 + "docA col") - // console.log(ClientUtils.hexToHsv(StrCast(docB.backgroundColor)) ?? 9999 + "docB col") - + + // console.log(`Sorting ${sortType}: ${typeA} vs ${typeB}`); const out = typeA < typeB ? -1 : typeA > typeB ? 1 : 0; - return isDesc ? -out : out; // Reverse the sort order if descending is true - }); + // console.log(`Comparison result: ${out} (isDesc: ${isDesc})`); - if (dragIndex != -1){ - // console.log("what what") + if (isDesc){ + return out + } - const draggedDoc = DragManager.docsBeingDragged[0] + return -out + + });} + + if (dragIndex != -1) { + const draggedDoc = DragManager.docsBeingDragged[0]; const originalIndex = docs.findIndex(doc => doc === draggedDoc); - - - // Remove the dragged document from its original position + docs.splice(originalIndex, 1); - // Insert the dragged document at the new position docs.splice(dragIndex, 0, draggedDoc); - // } } - + return docs; }; + @@ -464,22 +474,35 @@ export class CollectionCardView extends CollectionSubView() { * Converts the gpt output into a hashmap that can be used for sorting. lists are seperated by ==== while elements within the list are seperated by ~~~~~~ * @param gptOutput */ - processGptOutput = (gptOutput: string) => { + @action processGptOutput = (gptOutput: string) => { // Split the string into individual list items const listItems = gptOutput.split('======').filter(item => item.trim() !== ''); + // console.log(listItems + " LISTT"); + + // Debug: print the map contents + // console.log("Map contents:", Array.from(this._textToDoc.entries())); + listItems.forEach((item, index) => { - // Split the item by '~~~~~~' to get all descriptors - const parts = item.split('~~~~~~').map(part => part.trim()); - - parts.forEach(part => { - // Find the corresponding Doc in the textToDoc map - const doc = this._textToDoc.get(part); - if (doc) { - doc.chat = index; - } - }); + // Normalize the item (trim whitespace) + const normalizedItem = item.trim(); + // console.log("Normalized item:", normalizedItem); + + // Find the corresponding Doc in the textToDoc map + const doc = this._textToDoc.get(normalizedItem); + // console.log("DOC:", doc); + // console.log("ITEM:", normalizedItem); + + if (doc) { + doc.chat = index; + } else { + console.warn(`No matching document found for item: ${normalizedItem}`); + } }); - }; + + } + + // ); + // }; /** * Opens up the chat popup and starts the process for smart sorting. */ @@ -513,7 +536,7 @@ export class CollectionCardView extends CollectionSubView() { // }, new Set()).size ?? 0 // ); - const activeButtonIndex = CollectionCardView.getButtonGroup(this.cardSort_customField, doc); + // const activeButtonIndex = CollectionCardView.getButtonGroup(this.cardSort_customField, doc); const totalWidth = amButtons * 72 + amButtons * 2 * 5 + 6; @@ -552,8 +575,10 @@ export class CollectionCardView extends CollectionSubView() { // doc.cardSort_activeIcons = new List() - const list = StrListCast(doc.cardSort_activeIcons); - doc.cardSort_activeIcons = new List(list.includes(icon) ? list.filter(d => d !== icon) : [...list, icon]); + // const list = StrListCast(doc.cardSort_activeIcons); + // doc.cardSort_activeIcons = new List(list.includes(icon) ? list.filter(d => d !== icon) : [...list, icon]); + + BoolCast(doc[icon]) ? doc[icon] = false : doc[icon] = true @@ -563,9 +588,10 @@ export class CollectionCardView extends CollectionSubView() { getButtonIcon = (doc: Doc, icon: any): JSX.Element => { - const isActive = StrListCast(doc.cardSort_activeIcons).includes(icon) + // const isActive = StrListCast(doc.cardSort_activeIcons).includes(icon) + const isActive = doc[icon] - console.log(StrListCast(doc.cardSort_activeIcons)) + // console.log(StrListCast(doc.cardSort_activeIcons)) const color = isActive ? '#4476f7' : '#323232'; return ; @@ -577,6 +603,7 @@ export class CollectionCardView extends CollectionSubView() { renderCards = () => { const anySelected = this.childDocs.some(doc => DocumentView.SelectedDocs().includes(doc)); const isEmpty = this.childDocsWithoutLinks.length === 0; + const isDesc = BoolCast(this.Document.cardSort_isDesc) if (isEmpty) { return ( diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 1344dd071..4239329dd 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -36,7 +36,7 @@ import { ImageBox } from '../nodes/ImageBox'; import { VideoBox } from '../nodes/VideoBox'; import { WebBox } from '../nodes/WebBox'; import { RichTextMenu } from '../nodes/formattedText/RichTextMenu'; -import { NumListCast } from '../../../fields/Doc'; +import { NumListCast, StrListCast } from '../../../fields/Doc'; import { List } from '../../../fields/List'; // import { InkTranscription } from '../InkTranscription'; @@ -137,20 +137,25 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' | 'clusters' | 'viewAll' | 'fitOnce', checkResult?: boolean, persist?: boolean) { const selected = DocumentView.SelectedDocs().lastElement(); + + function isAttrFiltered(attr: string) { + return StrListCast(selected._childFilters).some(filter => filter.includes(attr)) + } + // prettier-ignore - const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'like' | 'star' | 'idea' | 'chat' | '1' | '2' | '3' | '4', + const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'heart' | 'star' | 'cloud' | 'bolt' | 'chat' | '1' | '2' | '3' | '4' | 'up' | 'down', { waitForRender?: boolean; checkResult: (doc: Doc) => any; setDoc: (doc: Doc, dv: DocumentView) => void; }> = new Map([ ['grid', { - checkResult: (doc:Doc) => BoolCast(doc?._freeform_backgroundGrid, false), - setDoc: (doc:Doc) => { doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid; }, + checkResult: (doc: Doc) => BoolCast(doc?._freeform_backgroundGrid, false), + setDoc: (doc: Doc) => { doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid; }, }], ['snaplines', { - checkResult: (doc:Doc) => BoolCast(doc?._freeform_snapLines, false), - setDoc: (doc:Doc) => { doc._freeform_snapLines = !doc._freeform_snapLines; }, + checkResult: (doc: Doc) => BoolCast(doc?._freeform_snapLines, false), + setDoc: (doc: Doc) => { doc._freeform_snapLines = !doc._freeform_snapLines; }, }], ['viewAll', { checkResult: (doc: Doc) => BoolCast(doc?._freeform_fitContentsToBox, false), @@ -161,13 +166,13 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' }, }], ['center', { - checkResult: (doc:Doc) => BoolCast(doc?._stacking_alignCenter, false), - setDoc: (doc:Doc) => { doc._stacking_alignCenter = !doc._stacking_alignCenter; }, + checkResult: (doc: Doc) => BoolCast(doc?._stacking_alignCenter, false), + setDoc: (doc: Doc) => { doc._stacking_alignCenter = !doc._stacking_alignCenter; }, }], ['clusters', { waitForRender: true, // flags that undo batch should terminate after a re-render giving the script the chance to fire - checkResult: (doc:Doc) => BoolCast(doc?._freeform_useClusters, false), - setDoc: (doc:Doc) => { doc._freeform_useClusters = !doc._freeform_useClusters; }, + checkResult: (doc: Doc) => BoolCast(doc?._freeform_useClusters, false), + setDoc: (doc: Doc) => { doc._freeform_useClusters = !doc._freeform_useClusters; }, }], ['flashcards', { checkResult: (doc: Doc) => BoolCast(Doc.UserDoc().defaultToFlashcards, false), @@ -185,63 +190,70 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "color", setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort === "color" ? doc.cardSort = '' : doc.cardSort = 'color', }], - ['links', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "links", - setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "links", - }], - ['like', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "like", + ['heart', { + checkResult: (doc: Doc) => isAttrFiltered('heart'), setDoc: (doc: Doc, dv: DocumentView) => { - doc.cardSort = "custom"; - doc.cardSort_customField = "like"; - doc.cardSort_visibleSortGroups = new List(); + isAttrFiltered('heart') ? Doc.setDocFilter(doc, 'heart', true, 'remove') : Doc.setDocFilter(doc, 'heart', true, 'match'); + } }], ['star', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "star", + checkResult: (doc: Doc) => isAttrFiltered('star'), + setDoc: (doc: Doc, dv: DocumentView) => { - doc.cardSort = "custom"; - doc.cardSort_customField = "star"; - doc.cardSort_visibleSortGroups = new List(); + isAttrFiltered('star') ? Doc.setDocFilter(doc, 'star', true, 'remove') : Doc.setDocFilter(doc, 'star', true, 'match'); } }], - ['idea', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "idea", + ['bolt', { + checkResult: (doc: Doc) => isAttrFiltered('bolt'), setDoc: (doc: Doc, dv: DocumentView) => { - doc.cardSort = "custom"; - doc.cardSort_customField = "idea"; - doc.cardSort_visibleSortGroups = new List(); + isAttrFiltered('bolt') ? Doc.setDocFilter(doc, 'bolt', true, 'remove') : Doc.setDocFilter(doc, 'bolt', true, 'match'); + + } + }], + ['cloud', { + checkResult: (doc: Doc) => isAttrFiltered('cloud'), + setDoc: (doc: Doc, dv: DocumentView) => { + isAttrFiltered('cloud') ? Doc.setDocFilter(doc, 'cloud', true, 'remove') : Doc.setDocFilter(doc, 'cloud', true, 'match'); + } }], ['chat', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "chat", + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "chat", setDoc: (doc: Doc, dv: DocumentView) => { - doc.cardSort === "custom" ? doc.cardSort = '' : doc.cardSort = 'custom'; - doc.cardSort_customField === "chat" ? doc.cardSort_customField = '' : doc.cardSort_customField = 'chat'; - doc.cardSort_visibleSortGroups = new List(); + doc.cardSort === "chat" ? doc.cardSort = '' : doc.cardSort = 'chat'; }, }], - ]); - for (let i = 0; i < 8; i++) { - map.set((i + 1 + '') as any, { - checkResult: (doc: Doc) => NumListCast(doc?.cardSort_visibleSortGroups).includes(i), + ['up', { + checkResult: (doc: Doc) => BoolCast(!doc?.cardSort_isDesc), setDoc: (doc: Doc, dv: DocumentView) => { - const list = NumListCast(doc.cardSort_visibleSortGroups); - doc.cardSort_visibleSortGroups = new List(list.includes(i) ? list.filter(d => d !== i) : [...list, i]); + doc.cardSort_isDesc = false; }, - }); - } + }], + ['down', { + checkResult: (doc: Doc) => BoolCast(doc?.cardSort_isDesc), + setDoc: (doc: Doc, dv: DocumentView) => { + doc.cardSort_isDesc = true; + }, + }], + ]); if (checkResult) { - // console.log("HIIIIII") return map.get(attr)?.checkResult(selected); } + const filters = StrListCast(selected._childFilters).concat(StrListCast(selected?._childFiltersByRanges).filter((filter, i) => !(i % 3))); + + + + // console.log(filters.some(filter => filter.includes('star'))+ "SUOOOOPPP") + const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; DocumentView.Selected().map(dv => map.get(attr)?.setDoc(dv.layoutDoc, dv)); setTimeout(() => batch.end(), 100); return undefined; }); + ScriptingGlobals.add(function cardHasLabel(label: string) { const selected = DocumentView.SelectedDocs().lastElement(); const labelNum = Number(label) - 1; diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index 468922532..6184a7b73 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -180,6 +180,7 @@ export class GPTPopup extends ObservableReactComponent { * Sorts cards in the CollectionCardDeckView */ generateSort = async () => { + console.log(this.chatSortPrompt + "USER PROMPT") this.setLoading(true); this.setSortDone(false); -- cgit v1.2.3-70-g09d2 From 9b0fa4d5581942c54375c10e3887c8010d3eb5e4 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Thu, 27 Jun 2024 14:06:22 -0400 Subject: time --- src/client/documents/Documents.ts | 6 +- src/client/util/CurrentUserUtils.ts | 2 + .../views/collections/CollectionCardDeckView.tsx | 8 ++- .../views/collections/CollectionCarouselView.tsx | 2 +- src/client/views/global/globalScripts.ts | 80 +++++++++++++++++----- src/client/views/pdf/AnchorMenu.tsx | 2 +- 6 files changed, 75 insertions(+), 25 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 53422b0c8..324d80581 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -480,13 +480,13 @@ export class DocumentOptions { cardSort?: STRt = new StrInfo('way cards are sorted in deck view'); // cardSortForDropDown?: STRt = new StrInfo('needed for dropdown and i dont know why') - cardSort_customField?: STRt = new StrInfo('field key used for sorting cards'); + // cardSort_customField?: STRt = new StrInfo('field key used for sorting cards'); cardSort_activeIcons?: List; //icons each card is tagges with - cardSort_visibleSortGroups?: List; // which sorting values are being filtered (shown) + // cardSort_visibleSortGroups?: List; // which sorting values are being filtered (shown) // cardSort_visibleSortGroups?: List; // which sorting values are being filtered (shown) cardSort_isDesc?: BOOLt = new BoolInfo('whether the cards are sorted ascending or descending'); - test?: STRt = new StrInfo('testing for filtering') + // test?: STRt = new StrInfo('testing for filtering') } export const DocOptions = new DocumentOptions(); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 48e4441de..f3b5e5b1d 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -668,12 +668,14 @@ pie title Minerals in my tap water { title: "Type", icon:"eye", toolTip:"Sort by document type", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"docType",funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "AI Sort", icon:"robot", toolTip:"Have Chat GPT sort your cards for you !", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Pile", icon:"layer-group", toolTip:"View the cards as a pile in the free form view !", btnType: ButtonType.ClickButton, expertMode: false, toolType:"pile", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Sort", toolTip: "Manage sort order / lock status", icon: "sort" , btnType: ButtonType.MultiToggleButton, toolType:"alignment", ignoreClick: true, subMenu: [ { title: "Ascending", toolTip: "Sort the cards in ascending order", btnType: ButtonType.ToggleButton, icon: "sort-up", toolType:"up", ignoreClick: true, scripts: {onClick: '{ return showFreeform(this.toolType, _readOnly_);}' }}, { title: "Descending", toolTip: "Sort the cards in descending order",btnType: ButtonType.ToggleButton, icon: "sort-down",toolType:"down",ignoreClick: true, scripts: {onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, ]}, + { title: "Filter", icon:"Filter", toolTip:"Filter cards by tags", width: 150, subMenu: this.cardGroupTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index d8f4362f1..d3e23c962 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -53,6 +53,7 @@ export class CollectionCardView extends CollectionSubView() { @observable _docDraggedIndex: number = -1; @observable _isACardBeingDragged: boolean = false; @observable overIndex: number = -1; + static getButtonGroup(groupFieldKey: 'chat' | 'star' | 'idea' | 'like', doc: Doc): number | undefined { return Cast(doc[groupFieldKey], 'number', null); @@ -97,8 +98,10 @@ export class CollectionCardView extends CollectionSubView() { this.Document.childFilters_boolean = 'OR' this._disposers.sort = reaction( () => ({ cardSort: this.cardSort }), - ({ cardSort}) => (cardSort === cardSortings.Chat ? this.openChatPopup() : GPTPopup.Instance.setVisible(false)) + ({ cardSort}) => (cardSort === cardSortings.Chat ? this.openChatPopup() : GPTPopup.Instance.setVisible(false)) ); + + } componentWillUnmount() { @@ -475,6 +478,9 @@ export class CollectionCardView extends CollectionSubView() { * @param gptOutput */ @action processGptOutput = (gptOutput: string) => { + + console.log("HIIII") + console.log(StrCast(this.Document.cardSort) + "cardSort") // Split the string into individual list items const listItems = gptOutput.split('======').filter(item => item.trim() !== ''); // console.log(listItems + " LISTT"); diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index 2adad68e0..4884db709 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -33,7 +33,7 @@ enum practiceVal { export class CollectionCarouselView extends CollectionSubView() { private _dropDisposer?: DragManager.DragDropDisposer; get practiceField() { return this.fieldKey + "_practice"; } // prettier-ignore - get starField() { return this.fieldKey + "_star"; } // prettier-ignore + get starField() { return "star"; } // prettier-ignore constructor(props: any) { super(props); diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 4239329dd..2ecde0eee 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -38,8 +38,10 @@ import { WebBox } from '../nodes/WebBox'; import { RichTextMenu } from '../nodes/formattedText/RichTextMenu'; import { NumListCast, StrListCast } from '../../../fields/Doc'; import { List } from '../../../fields/List'; - +import { CollectionViewType } from '../../documents/DocumentTypes'; // import { InkTranscription } from '../InkTranscription'; +import { Docs } from '../../documents/Documents'; +import { CollectionSubView } from '../collections/CollectionSubView'; // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function IsNoneSelected() { @@ -139,11 +141,11 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' const selected = DocumentView.SelectedDocs().lastElement(); function isAttrFiltered(attr: string) { - return StrListCast(selected._childFilters).some(filter => filter.includes(attr)) + return StrListCast(selected._childFilters).some(filter => filter.includes(attr)); } // prettier-ignore - const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'heart' | 'star' | 'cloud' | 'bolt' | 'chat' | '1' | '2' | '3' | '4' | 'up' | 'down', + const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'heart' | 'star' | 'cloud' | 'bolt' | 'chat' | '1' | '2' | '3' | '4' | 'up' | 'down' | 'pile', { waitForRender?: boolean; checkResult: (doc: Doc) => any; @@ -219,7 +221,11 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' } }], ['chat', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "chat", + checkResult: (doc: Doc) => { + + if (StrCast(doc?.cardSort) === "chat"){ + return true + }} , setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort === "chat" ? doc.cardSort = '' : doc.cardSort = 'chat'; }, @@ -236,6 +242,46 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' doc.cardSort_isDesc = true; }, }], + ['pile', { + checkResult: (doc: Doc) => doc._type_collection == CollectionViewType.Freeform, + setDoc: (doc: Doc, dv: DocumentView) => { + doc._type_collection = CollectionViewType.Freeform; + const newCol = Docs.Create.CarouselDocument(DocListCast(doc[Doc.LayoutFieldKey(doc)]), { + _width: 250, + _height: 200, + _layout_fitWidth: false, + _layout_autoHeight: true, + }); + + + const iconMap: { [key: number]: any } = { + 0: 'star', + 1: 'heart', + 2: 'cloud', + 3: 'bolt' + }; + + for (let i=0; i<4; i++){ + if (isAttrFiltered(iconMap[i])){ + newCol[iconMap[i]] = true + } + } + + // if (doc.type == DocumentType.COL ) { + newCol && dv.ComponentView?.addDocument?.(newCol); + dv.ComponentView?._props.focus(newCol, {willPan: true , willZoomCentered: true, zoomScale: 200} ) + + // } + // doc as CollectionFreeFormView + // doc as typeof CollectionSubView + + // doc._props + + // CollectionFreeFormView.addDocumemnt + + // doc?.addDocument; //this._props.addDocument(newCol) + }, + }], ]); if (checkResult) { @@ -243,8 +289,6 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' } const filters = StrListCast(selected._childFilters).concat(StrListCast(selected?._childFiltersByRanges).filter((filter, i) => !(i % 3))); - - // console.log(filters.some(filter => filter.includes('star'))+ "SUOOOOPPP") const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; @@ -253,7 +297,6 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' return undefined; }); - ScriptingGlobals.add(function cardHasLabel(label: string) { const selected = DocumentView.SelectedDocs().lastElement(); const labelNum = Number(label) - 1; @@ -355,37 +398,36 @@ ScriptingGlobals.add(function setCardSort(value?: any, checkResult?: boolean) { if (checkResult) { // console.log(attr + "attricute") // console.log(map.get(attr)?.checkResult(selected) + "check result") - console.log(StrCast(selected?.cardSort) + "check") - const hi = StrCast(selected?.cardSort) - return StrCast(selected?.cardSortForDropDown) ?? "Time"; + console.log(StrCast(selected?.cardSort) + 'check'); + const hi = StrCast(selected?.cardSort); + return StrCast(selected?.cardSortForDropDown) ?? 'Time'; } - + function docFields(doc: Doc): void { - switch(value){ + switch (value) { case 'Custom 1': - doc.cardSort_customField = "like"; + doc.cardSort_customField = 'like'; break; case 'Custom 2': - doc.cardSort_customField = "star"; + doc.cardSort_customField = 'star'; break; case 'Custom 3': - doc.cardSort_customField = "idea"; + doc.cardSort_customField = 'idea'; break; case 'Chat GPT': - doc.cardSort = "custom"; - doc.cardSort_customField = "chat"; + doc.cardSort = 'custom'; + doc.cardSort_customField = 'chat'; break; default: break; } doc.cardSort_visibleSortGroups = new List(); - } // const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; DocumentView.Selected().map(dv => { - dv.Document.cardSortForDropDown = value + dv.Document.cardSortForDropDown = value; if (value != 'Chat GPT') { dv.Document.cardSort = value.trim().split(/\s+/)[0].toLowerCase(); diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index 2f6824466..96f025ca0 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -133,7 +133,7 @@ export class AnchorMenu extends AntimodeMenu { _layout_autoHeight: true, }); - this.addToCollection?.(newCol); + this.addToCollection?.(newCol); //this._props.addDocument(newCol) }; pointerDown = (e: React.PointerEvent) => { -- cgit v1.2.3-70-g09d2 From 3e46e59b3919458d945745f457d8c76f13094796 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Sun, 14 Jul 2024 14:06:10 -0400 Subject: in it to win it --- package-lock.json | 2150 ++++++++++++++------ src/client/util/CurrentUserUtils.ts | 3 +- src/client/views/MainView.tsx | 3 +- .../views/collections/CollectionCardDeckView.tsx | 15 +- src/client/views/global/globalScripts.ts | 14 +- src/client/views/pdf/GPTPopup/GPTPopup.scss | 19 +- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 98 +- 7 files changed, 1677 insertions(+), 625 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/package-lock.json b/package-lock.json index 61eccb86e..0542a29cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3,382 +3,70 @@ "version": "1.0.0", "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "dash", - "version": "1.0.0", - "dependencies": { - "@adobe/react-spectrum": "^3.32.2", - "@azure/storage-blob": "^12.17.0", - "@babel/preset-env": "^7.23.5", - "@babel/preset-react": "^7.23.3", - "@bundled-es-modules/pdfjs-dist": "^3.6.172-alpha.1", - "@emotion/react": "^11.11.1", - "@emotion/styled": "^11.11.0", - "@ffmpeg/core": "^0.12.5", - "@ffmpeg/ffmpeg": "^0.12.8", - "@fortawesome/fontawesome-svg-core": "^6.5.1", - "@fortawesome/free-brands-svg-icons": "^6.5.1", - "@fortawesome/free-regular-svg-icons": "^6.5.1", - "@fortawesome/free-solid-svg-icons": "^6.5.1", - "@fortawesome/react-fontawesome": "^0.2.0", - "@fullcalendar/core": "^6.1.10", - "@fullcalendar/daygrid": "^6.1.10", - "@fullcalendar/multimonth": "^6.1.10", - "@internationalized/date": "^3.5.0", - "@mui/icons-material": "^5.14.19", - "@mui/material": "^5.14.19", - "@octokit/core": "^6.0.1", - "@react-google-maps/api": "^2.19.2", - "@react-spring/web": "^9.7.3", - "@turf/turf": "^6.5.0", - "@types/bezier-js": "^4.1.3", - "@types/brotli": "^1.3.4", - "@types/cors": "^2.8.17", - "@types/d3-axis": "^3.0.6", - "@types/d3-color": "^3.1.3", - "@types/d3-scale": "^4.0.8", - "@types/d3-selection": "^3.0.10", - "@types/dom-speech-recognition": "0.0.4", - "@types/find-in-files": "^0.5.3", - "@types/fluent-ffmpeg": "^2.1.24", - "@types/formidable": "3.4.5", - "@types/geojson": "^7946.0.14", - "@types/google-maps": "^3.2.6", - "@types/mapbox-gl": "^3.1.0", - "@types/pdf-parse": "^1.1.4", - "@types/reveal": "^4.2.0", - "@types/supercluster": "^7.1.3", - "@types/web": "^0.0.147", - "@types/webpack-hot-middleware": "^2.25.9", - "@typescript-eslint/parser": "^7.8.0", - "@webscopeio/react-textarea-autocomplete": "^4.9.2", - "adm-zip": "^0.5.10", - "archiver": "^7.0.1", - "async": "^3.2.5", - "axios": "^1.6.2", - "babel": "^6.23.0", - "babel-loader": "^9.1.3", - "bcrypt-nodejs": "0.0.3", - "better-react-mathjax": "^2.0.3", - "bezier-curve": "^1.0.0", - "bezier-js": "^6.1.4", - "bingmaps-react": "^1.2.10", - "bluebird": "^3.7.2", - "body-parser": "^1.20.2", - "bootstrap": "^5.3.2", - "brotli": "^1.3.3", - "browndash-components": "^0.1.44", - "browser-assert": "^1.2.1", - "bson": "^6.2.0", - "canvas": "^2.11.2", - "chart.js": "^4.4.0", - "child_process": "^1.0.2", - "class-transformer": "^0.5.1", - "color": "^4.2.3", - "colors": "^1.4.0", - "compute-cosine-similarity": "^1.1.0", - "connect-flash": "^0.1.1", - "connect-mongo": "^5.1.0", - "cookie-parser": "^1.4.6", - "cookie-session": "^2.0.0", - "core-js": "^3.33.3", - "cors": "^2.8.5", - "css-loader": "^7.0.0", - "csstype": "^3.1.3", - "csv-parser": "^3.0.0", - "csv-stringify": "^6.4.4", - "csvtojson": "^2.0.10", - "D": "^1.0.0", - "d3": "^7.8.5", - "depcheck": "^1.4.7", - "dotenv": "^16.3.1", - "eslint-webpack-plugin": "^4.1.0", - "exif": "^0.6.0", - "exifr": "^7.1.3", - "express": "^4.18.2", - "express-flash": "0.0.2", - "express-session": "^1.17.3", - "express-validator": "^7.0.1", - "extract-colors": "^4.0.2", - "ffmpeg": "0.0.4", - "file-loader": "^6.2.0", - "file-saver": "^2.0.5", - "find-in-files": "^0.5.0", - "fit-curve": "^0.2.0", - "flexlayout-react": "^0.7.15", - "fluent-ffmpeg": "^2.1.2", - "forever-agent": "^0.6.1", - "fork-ts-checker-webpack-plugin": "^9.0.2", - "form-data": "^4.0.0", - "formidable": "3.5.1", - "function-plot": "^1.23.3", - "golden-layout": "^2.6.0", - "google-auth-library": "^9.4.1", - "googleapis": "^133.0.0", - "googlephotos": "^0.3.5", - "got": "^14.0.0", - "howler": "^2.2.4", - "html-to-image": "^1.11.11", - "html-to-text": "^9.0.5", - "html-webpack-plugin": "^5.5.3", - "http-browserify": "^1.7.0", - "https": "^1.0.0", - "https-browserify": "^1.0.0", - "i": "^0.3.7", - "image-data-uri": "^2.0.1", - "image-size": "^1.0.2", - "image-size-stream": "^1.1.0", - "is-plain-obj": "^4.1.0", - "jimp": "^0.22.10", - "jpeg-autorotate": "^9.0.0", - "jquery": "^3.7.1", - "js-datepicker": "^5.18.2", - "jsonschema": "^1.4.1", - "jszip": "^3.10.1", - "lodash": "^4.17.21", - "mapbox-gl": "^3.0.1", - "markdown-it": "^14.1.0", - "mathquill": "^0.10.1-a", - "md5-file": "^5.0.0", - "memorystream": "^0.3.1", - "mermaid": "^10.9.0", - "mobile-detect": "^1.4.5", - "mobx": "^6.12.0", - "mobx-react": "^9.1.0", - "mobx-utils": "^6.0.8", - "mongodb": "^6.3.0", - "mongoose": "^8.0.2", - "node-stream-zip": "^1.15.0", - "nodemailer": "^6.9.7", - "nodemon": "^3.0.2", - "npm": "^10.2.5", - "openai": "^4.26.0", - "p-limit": "^5.0.0", - "passport": "^0.7.0", - "passport-google-oauth20": "^2.0.0", - "passport-local": "^1.0.0", - "path-browserify": "^1.0.1", - "pdf-parse": "^1.1.1", - "pdfjs": "^2.4.7", - "pdfjs-dist": "^4.0.269", - "probe-image-size": "^7.2.3", - "process": "^0.11.10", - "prosemirror-commands": "^1.5.2", - "prosemirror-find-replace": "^0.9.0", - "prosemirror-history": "^1.3.2", - "prosemirror-inputrules": "^1.4.0", - "prosemirror-keymap": "^1.2.2", - "prosemirror-model": "^1.19.3", - "prosemirror-schema-list": "^1.3.0", - "prosemirror-state": "^1.4.3", - "prosemirror-transform": "^1.8.0", - "prosemirror-view": "^1.32.5", - "pug": "^3.0.2", - "query-string": "^7.1.3", - "querystring-es3": "^0.2.1", - "raw-loader": "^4.0.2", - "rc-switch": "^4.1.0", - "react": "^18.2.0", - "react-autosuggest": "^10.1.0", - "react-awesome-reveal": "^4.2.7", - "react-color": "^2.19.3", - "react-compound-slider": "^3.4.0", - "react-datepicker": "^6.1.0", - "react-dom": "^18.2.0", - "react-grid-layout": "^1.4.4", - "react-icons": "^5.0.1", - "react-jsx-parser": "^1.29.0", - "react-latex-next": "^3.0.0", - "react-loading": "^2.0.3", - "react-map-gl": "^7.1.6", - "react-markdown": "^9.0.1", - "react-measure": "^2.5.2", - "react-resizable": "^3.0.5", - "react-select": "^5.8.0", - "react-textarea-autosize": "^8.5.3", - "react-type-animation": "^3.2.0", - "react-xarrows": "^2.0.2", - "readline": "^1.3.0", - "recharts": "^2.10.3", - "rehype-katex": "^7.0.0", - "rehype-raw": "^7.0.0", - "remark-gfm": "^4.0.0", - "remark-math": "^6.0.0", - "request": "^2.88.2", - "request-promise": "^4.2.6", - "reveal.js": "^5.0.2", - "rimraf": "^5.0.5", - "sass": "^1.69.5", - "sass-loader": "^14.2.0", - "serializr": "^3.0.2", - "shelljs": "^0.8.5", - "socket.io": "^4.7.2", - "socket.io-client": "^4.7.2", - "standard-http-error": "^2.0.1", - "stream-browserify": "^3.0.0", - "styled-components": "^6.1.1", - "supercluster": "^8.0.1", - "textarea-caret": "^3.1.0", - "tough-cookie": "^4.1.3", - "tslint": "^6.1.3", - "tslint-loader": "^3.5.4", - "typescript": "^5.3.3", - "typescript-collections": "^1.3.3", - "typescript-language-server": "^4.1.3", - "uninstall": "^0.0.0", - "url": "^0.11.3", - "url-loader": "^4.1.1", - "util": "^0.12.5", - "uuid": "^9.0.1", - "valid-url": "^1.0.9", - "web-request": "^1.0.7", - "webpack": "^5.89.0", - "webpack-cli": "^5.1.4", - "webpack-dev-middleware": "^7.0.0", - "webpack-hot-middleware": "^2.25.4", - "wikijs": "^6.4.1", - "words-to-numbers": "^1.5.1", - "xoauth2": "^1.2.0", - "xregexp": "^5.1.1" - }, - "devDependencies": { - "@eslint/js": "^9.1.1", - "@types/adm-zip": "^0.5.5", - "@types/animejs": "^3.1.12", - "@types/archiver": "^6.0.2", - "@types/async": "^3.2.24", - "@types/bcrypt-nodejs": "0.0.31", - "@types/bluebird": "^3.5.42", - "@types/body-parser": "^1.19.5", - "@types/chai": "^4.3.11", - "@types/color": "^3.0.6", - "@types/cookie-parser": "^1.4.6", - "@types/cookie-session": "^2.0.48", - "@types/d3": "^7.4.3", - "@types/exif": "^0.6.5", - "@types/express": "^4.17.21", - "@types/express-session": "^1.17.10", - "@types/file-saver": "^2.0.7", - "@types/howler": "^2.2.11", - "@types/html-to-text": "^9.0.4", - "@types/jquery": "^3.5.29", - "@types/libxmljs": "^0.18.12", - "@types/lodash": "^4.14.202", - "@types/mocha": "^10.0.6", - "@types/node": "^20.10.3", - "@types/nodemailer": "^6.4.14", - "@types/passport": "^1.0.16", - "@types/passport-google-oauth20": "^2.0.14", - "@types/passport-local": "^1.0.38", - "@types/rc-switch": "^1.9.5", - "@types/react": "^18.2.41", - "@types/react-autosuggest": "^10.1.10", - "@types/react-color": "^3.0.10", - "@types/react-datepicker": "^6.2.0", - "@types/react-dom": "^18.2.17", - "@types/react-grid-layout": "^1.3.5", - "@types/react-measure": "^2.0.12", - "@types/react-reconciler": "^0.28.8", - "@types/request": "^2.48.12", - "@types/request-promise": "^4.1.51", - "@types/shelljs": "^0.8.15", - "@types/uuid": "^9.0.7", - "@types/valid-url": "^1.0.7", - "@types/webpack": "^5.28.5", - "@types/youtube": "0.0.50", - "chai": "^5.0.0", - "cross-env": "^7.0.3", - "eslint": "^8.57.0", - "eslint-config-airbnb": "^19.0.4", - "eslint-config-node": "^4.1.0", - "eslint-config-prettier": "^9.1.0", - "eslint-import-resolver-typescript": "^3.6.1", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsx-a11y": "^6.8.0", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^5.0.1", - "eslint-plugin-react": "^7.34.1", - "eslint-plugin-react-hooks": "^4.6.0", - "globals": "^15.1.0", - "jsdom": "^24.0.0", - "mocha": "^10.2.0", - "prettier": "^3.1.0", - "scss-loader": "0.0.1", - "style-loader": "^4.0.0", - "ts-loader": "^9.5.1", - "ts-node": "^10.9.1", - "ts-node-dev": "^2.0.0", - "typescript-eslint": "^7.8.0", - "webpack-dev-server": "^5.0.4" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@adobe/react-spectrum": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/@adobe/react-spectrum/-/react-spectrum-3.35.1.tgz", - "integrity": "sha512-QNhsaEHv5S5Vqsk7b8aCV9F7qAnWw8VJ/Nep/SOjeiJ7vK993jEOetEhSsUIQ8VHsMKs6qkTtZr0/DKoV+Z/9w==", - "dependencies": { - "@internationalized/string": "^3.2.3", - "@react-aria/i18n": "^3.11.1", - "@react-aria/ssr": "^3.9.4", - "@react-aria/utils": "^3.24.1", - "@react-aria/visually-hidden": "^3.8.12", - "@react-spectrum/actionbar": "^3.4.5", - "@react-spectrum/actiongroup": "^3.10.5", - "@react-spectrum/avatar": "^3.0.12", - "@react-spectrum/badge": "^3.1.13", - "@react-spectrum/breadcrumbs": "^3.9.7", - "@react-spectrum/button": "^3.16.4", - "@react-spectrum/buttongroup": "^3.6.13", - "@react-spectrum/calendar": "^3.4.9", - "@react-spectrum/checkbox": "^3.9.6", - "@react-spectrum/combobox": "^3.12.5", - "@react-spectrum/contextualhelp": "^3.6.11", - "@react-spectrum/datepicker": "^3.9.6", - "@react-spectrum/dialog": "^3.8.11", - "@react-spectrum/divider": "^3.5.13", - "@react-spectrum/dnd": "^3.3.10", - "@react-spectrum/dropzone": "^3.0.1", - "@react-spectrum/filetrigger": "^3.0.1", - "@react-spectrum/form": "^3.7.6", - "@react-spectrum/icon": "^3.7.13", - "@react-spectrum/illustratedmessage": "^3.5.1", - "@react-spectrum/image": "^3.5.1", - "@react-spectrum/inlinealert": "^3.2.5", - "@react-spectrum/labeledvalue": "^3.1.14", - "@react-spectrum/layout": "^3.6.5", - "@react-spectrum/link": "^3.6.7", - "@react-spectrum/list": "^3.7.10", - "@react-spectrum/listbox": "^3.12.9", - "@react-spectrum/menu": "^3.19.1", - "@react-spectrum/meter": "^3.5.1", - "@react-spectrum/numberfield": "^3.9.3", - "@react-spectrum/overlays": "^5.6.1", - "@react-spectrum/picker": "^3.14.5", - "@react-spectrum/progress": "^3.7.7", - "@react-spectrum/provider": "^3.9.7", - "@react-spectrum/radio": "^3.7.6", - "@react-spectrum/searchfield": "^3.8.6", - "@react-spectrum/slider": "^3.6.9", - "@react-spectrum/statuslight": "^3.5.13", - "@react-spectrum/switch": "^3.5.5", - "@react-spectrum/table": "^3.12.10", - "@react-spectrum/tabs": "^3.8.10", - "@react-spectrum/tag": "^3.2.6", - "@react-spectrum/text": "^3.5.5", - "@react-spectrum/textfield": "^3.12.1", - "@react-spectrum/theme-dark": "^3.5.10", - "@react-spectrum/theme-default": "^3.5.10", - "@react-spectrum/theme-light": "^3.4.10", - "@react-spectrum/tooltip": "^3.6.7", - "@react-spectrum/view": "^3.6.10", - "@react-spectrum/well": "^3.4.13", - "@react-stately/collections": "^3.10.7", - "@react-stately/data": "^3.11.4", - "@react-types/shared": "^3.23.1", + "dependencies": { + "@adobe/react-spectrum": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/@adobe/react-spectrum/-/react-spectrum-3.35.0.tgz", + "integrity": "sha512-dhCKWKDS/xF02EpWluicH7Va6KAANbrUx4rb1UeeFT3czhwz44oCQ74ZYviVedNv6Bq7O22/kbMa20rDdyt/4A==", + "requires": { + "@internationalized/string": "^3.2.2", + "@react-aria/i18n": "^3.11.0", + "@react-aria/ssr": "^3.9.3", + "@react-aria/utils": "^3.24.0", + "@react-aria/visually-hidden": "^3.8.11", + "@react-spectrum/actionbar": "^3.4.4", + "@react-spectrum/actiongroup": "^3.10.4", + "@react-spectrum/avatar": "^3.0.11", + "@react-spectrum/badge": "^3.1.12", + "@react-spectrum/breadcrumbs": "^3.9.6", + "@react-spectrum/button": "^3.16.3", + "@react-spectrum/buttongroup": "^3.6.12", + "@react-spectrum/calendar": "^3.4.8", + "@react-spectrum/checkbox": "^3.9.5", + "@react-spectrum/combobox": "^3.12.4", + "@react-spectrum/contextualhelp": "^3.6.10", + "@react-spectrum/datepicker": "^3.9.5", + "@react-spectrum/dialog": "^3.8.10", + "@react-spectrum/divider": "^3.5.12", + "@react-spectrum/dnd": "^3.3.9", + "@react-spectrum/dropzone": "^3.0.0", + "@react-spectrum/filetrigger": "^3.0.0", + "@react-spectrum/form": "^3.7.5", + "@react-spectrum/icon": "^3.7.12", + "@react-spectrum/illustratedmessage": "^3.5.0", + "@react-spectrum/image": "^3.5.0", + "@react-spectrum/inlinealert": "^3.2.4", + "@react-spectrum/labeledvalue": "^3.1.13", + "@react-spectrum/layout": "^3.6.4", + "@react-spectrum/link": "^3.6.6", + "@react-spectrum/list": "^3.7.9", + "@react-spectrum/listbox": "^3.12.8", + "@react-spectrum/menu": "^3.19.0", + "@react-spectrum/meter": "^3.5.0", + "@react-spectrum/numberfield": "^3.9.2", + "@react-spectrum/overlays": "^5.6.0", + "@react-spectrum/picker": "^3.14.4", + "@react-spectrum/progress": "^3.7.6", + "@react-spectrum/provider": "^3.9.6", + "@react-spectrum/radio": "^3.7.5", + "@react-spectrum/searchfield": "^3.8.5", + "@react-spectrum/slider": "^3.6.8", + "@react-spectrum/statuslight": "^3.5.12", + "@react-spectrum/switch": "^3.5.4", + "@react-spectrum/table": "^3.12.9", + "@react-spectrum/tabs": "^3.8.9", + "@react-spectrum/tag": "^3.2.5", + "@react-spectrum/text": "^3.5.4", + "@react-spectrum/textfield": "^3.12.0", + "@react-spectrum/theme-dark": "^3.5.9", + "@react-spectrum/theme-default": "^3.5.9", + "@react-spectrum/theme-light": "^3.4.9", + "@react-spectrum/tooltip": "^3.6.6", + "@react-spectrum/view": "^3.6.9", + "@react-spectrum/well": "^3.4.12", + "@react-stately/collections": "^3.10.6", + "@react-stately/data": "^3.11.3", + "@react-types/shared": "^3.23.0", "client-only": "^0.0.1" } }, @@ -1045,6 +733,13 @@ "@babel/helper-replace-supers": "^7.24.1", "@babel/helper-split-export-declaration": "^7.24.5", "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + } } }, "@babel/plugin-transform-computed-properties": { @@ -1598,6 +1293,13 @@ "@babel/types": "^7.24.5", "debug": "^4.3.1", "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + } } }, "@babel/types": { @@ -1610,6 +1312,11 @@ "to-fast-properties": "^2.0.0" } }, + "@braintree/sanitize-url": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz", + "integrity": "sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==" + }, "@bundled-es-modules/pdfjs-dist": { "version": "3.6.172-alpha.1", "resolved": "https://registry.npmjs.org/@bundled-es-modules/pdfjs-dist/-/pdfjs-dist-3.6.172-alpha.1.tgz", @@ -1857,9 +1564,9 @@ } }, "@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.4.0.tgz", + "integrity": "sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg==", "dev": true }, "@ffmpeg/core": { @@ -2233,6 +1940,72 @@ } } }, + "@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "requires": { + "@sinclair/typebox": "^0.27.8" + } + }, + "@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "requires": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "@jimp/bmp": { "version": "0.22.12", "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.22.12.tgz", @@ -2889,7 +2662,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "requires": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -2898,14 +2670,12 @@ "@nodelib/fs.stat": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" }, "@nodelib/fs.walk": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "requires": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -4592,6 +4362,49 @@ "@swc/helpers": "^0.5.0" } }, + "@react-spring/animated": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.3.tgz", + "integrity": "sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==", + "requires": { + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + } + }, + "@react-spring/core": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.3.tgz", + "integrity": "sha512-IqFdPVf3ZOC1Cx7+M0cXf4odNLxDC+n7IN3MDcVCTIOSBfqEcBebSv+vlY5AhM0zw05PDbjKrNmBpzv/AqpjnQ==", + "requires": { + "@react-spring/animated": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + } + }, + "@react-spring/shared": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.3.tgz", + "integrity": "sha512-NEopD+9S5xYyQ0pGtioacLhL2luflh6HACSSDUZOwLHoxA5eku1UPuqcJqjwSD6luKjjLfiLOspxo43FUHKKSA==", + "requires": { + "@react-spring/types": "~9.7.3" + } + }, + "@react-spring/types": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.3.tgz", + "integrity": "sha512-Kpx/fQ/ZFX31OtlqVEFfgaD1ACzul4NksrvIgYfIFq9JpDHFwQkMVZ10tbo0FU/grje4rcL4EIrjekl3kYwgWw==" + }, + "@react-spring/web": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.3.tgz", + "integrity": "sha512-BXt6BpS9aJL/QdVqEIX9YoUy8CE6TJrU0mNCqSoxdXlIeNcEBWOfIyE6B14ENNsyQKS3wOWkiJfco0tCr/9tUg==", + "requires": { + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + } + }, "@react-stately/calendar": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/@react-stately/calendar/-/calendar-3.5.0.tgz", @@ -5305,6 +5118,11 @@ "selderee": "^0.11.0" } }, + "@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + }, "@sindresorhus/is": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-6.3.0.tgz", @@ -7004,8 +6822,7 @@ "@types/d3-scale-chromatic": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz", - "integrity": "sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==", - "dev": true + "integrity": "sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==" }, "@types/d3-selection": { "version": "3.0.10", @@ -7169,9 +6986,9 @@ } }, "@types/geojson": { - "version": "7946.0.8", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz", - "integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==" + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==" }, "@types/glob": { "version": "7.2.0", @@ -7241,6 +7058,27 @@ "@types/node": "*" } }, + "@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" + }, + "@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, "@types/jquery": { "version": "3.5.30", "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.30.tgz", @@ -7271,6 +7109,11 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "@types/katex": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", + "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==" + }, "@types/keygrip": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.6.tgz", @@ -7730,6 +7573,11 @@ "integrity": "sha512-tgsWVG80dM5PVEBSbXUttPJTBCOo0IKbBh4R4z/SHsC5C81A3aaUH4fsbj+JYk7fopApU/Mao1c0EWTE592TSg==", "dev": true }, + "@types/web": { + "version": "0.0.148", + "resolved": "https://registry.npmjs.org/@types/web/-/web-0.0.148.tgz", + "integrity": "sha512-HX2eARbn26tZuCOxZ25Ew6UUNhw8fgdGrOGcxX0/J6yTtlJm+nHlL9/h+2zgSzse13vlVe+c+W3LWqhnlAd5rg==" + }, "@types/webidl-conversions": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", @@ -7773,12 +7621,123 @@ "@types/node": "*" } }, + "@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" + }, "@types/youtube": { "version": "0.0.50", "resolved": "https://registry.npmjs.org/@types/youtube/-/youtube-0.0.50.tgz", "integrity": "sha512-d4GpH4uPYp9W07kc487tiq6V/EUHl18vZWFMbQoe4Sk9LXEWzFi/BMf9x7TI4m7/j7gU3KeX8H6M8aPBgykeLw==", "dev": true }, + "@typescript-eslint/eslint-plugin": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.0.tgz", + "integrity": "sha512-FX1X6AF0w8MdVFLSdqwqN/me2hyhuQg4ykN6ZpVhh1ij/80pTvDKclX1sZB9iqex8SjQfVhwMKs3JtnnMLzG9w==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/type-utils": "7.13.0", + "@typescript-eslint/utils": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + } + }, + "@typescript-eslint/parser": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.0.tgz", + "integrity": "sha512-EjMfl69KOS9awXXe83iRN7oIEXy9yYdqWfqdrFAYAAr6syP8eLEFI7ZE4939antx2mNgPRW/o1ybm2SFYkbTVA==", + "requires": { + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/typescript-estree": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.0.tgz", + "integrity": "sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng==", + "requires": { + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.0.tgz", + "integrity": "sha512-xMEtMzxq9eRkZy48XuxlBFzpVMDurUAfDu5Rz16GouAtXm0TaAoTFzqWUFPPuQYXI/CDaH/Bgx/fk/84t/Bc9A==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "7.13.0", + "@typescript-eslint/utils": "7.13.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + } + }, + "@typescript-eslint/types": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.0.tgz", + "integrity": "sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==" + }, + "@typescript-eslint/typescript-estree": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.0.tgz", + "integrity": "sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw==", + "requires": { + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "dependencies": { + "semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==" + } + } + }, + "@typescript-eslint/utils": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.0.tgz", + "integrity": "sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/typescript-estree": "7.13.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.0.tgz", + "integrity": "sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw==", + "requires": { + "@typescript-eslint/types": "7.13.0", + "eslint-visitor-keys": "^3.4.3" + } + }, "@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -8681,6 +8640,14 @@ "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==" }, + "better-react-mathjax": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/better-react-mathjax/-/better-react-mathjax-2.0.3.tgz", + "integrity": "sha512-wfifT8GFOKb1TWm2+E50I6DJpLZ5kLbch283Lu043EJtwSv0XvZDjr4YfR4d2MjAhqP6SH4VjjrKgbX8R00oCQ==", + "requires": { + "mathjax-full": "^3.2.2" + } + }, "bezier-curve": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/bezier-curve/-/bezier-curve-1.0.0.tgz", @@ -8957,6 +8924,11 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" + }, "emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -8979,6 +8951,16 @@ "requires": { "ansi-regex": "^6.0.1" } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } } } }, @@ -10829,7 +10811,7 @@ } }, "string-width": { - "version": "npm:string-width@4.2.3", + "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { @@ -10847,7 +10829,7 @@ } }, "strip-ansi": { - "version": "npm:strip-ansi@6.0.1", + "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { @@ -11367,6 +11349,11 @@ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" }, + "ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==" + }, "class-transformer": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", @@ -11706,6 +11693,35 @@ } } }, + "compute-cosine-similarity": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/compute-cosine-similarity/-/compute-cosine-similarity-1.1.0.tgz", + "integrity": "sha512-FXhNx0ILLjGi9Z9+lglLzM12+0uoTnYkHm7GiadXDAr0HGVLm25OivUS1B/LPkbzzvlcXz/1EvWg9ZYyJSdhTw==", + "requires": { + "compute-dot": "^1.1.0", + "compute-l2norm": "^1.1.0", + "validate.io-array": "^1.0.5", + "validate.io-function": "^1.0.2" + } + }, + "compute-dot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/compute-dot/-/compute-dot-1.1.0.tgz", + "integrity": "sha512-L5Ocet4DdMrXboss13K59OK23GXjiSia7+7Ukc7q4Bl+RVpIXK2W9IHMbWDZkh+JUEvJAwOKRaJDiFUa1LTnJg==", + "requires": { + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2" + } + }, + "compute-l2norm": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/compute-l2norm/-/compute-l2norm-1.1.0.tgz", + "integrity": "sha512-6EHh1Elj90eU28SXi+h2PLnTQvZmkkHWySpoFz+WOlVNLz3DQoC4ISUHSV9n5jMxPHtKGJ01F4uu2PsXBB8sSg==", + "requires": { + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -11874,6 +11890,14 @@ "vary": "^1" } }, + "cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "requires": { + "layout-base": "^1.0.0" + } + }, "cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", @@ -12059,11 +12083,44 @@ "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-6.4.6.tgz", "integrity": "sha512-h2V2XZ3uOTLilF5dPIptgUfN/o2ia/80Ie0Lly18LAnw5s8Eb7kt8rfxSUy24AztJZas9f6DPZpVlzDUtFt/ag==" }, + "csvtojson": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/csvtojson/-/csvtojson-2.0.10.tgz", + "integrity": "sha512-lUWFxGKyhraKCW8Qghz6Z0f2l/PqB1W3AO0HKJzGIQ5JRSlR651ekJDiGJbBT4sRNNv5ddnSGVEnsxP9XRCVpQ==", + "requires": { + "bluebird": "^3.5.1", + "lodash": "^4.17.3", + "strip-bom": "^2.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, "custom-event": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==" }, + "cytoscape": { + "version": "3.29.2", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.29.2.tgz", + "integrity": "sha512-2G1ycU28Nh7OHT9rkXRLpCDP30MKH1dXJORZuBhtEhEW7pKwgPi77ImqlCWinouyE1PNepIOGZBOrE84DG7LyQ==" + }, + "cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "requires": { + "cose-base": "^1.0.0" + } + }, "d3": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", @@ -12288,6 +12345,30 @@ "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==" }, + "d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "requires": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + }, + "dependencies": { + "d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" + }, + "d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "requires": { + "d3-path": "1" + } + } + } + }, "d3-scale": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", @@ -12392,6 +12473,15 @@ "d3-transition": "2 - 3" } }, + "dagre-d3-es": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.10.tgz", + "integrity": "sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==", + "requires": { + "d3": "^7.8.2", + "lodash-es": "^4.17.21" + } + }, "damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -12486,6 +12576,11 @@ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==" }, + "dayjs": { + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==" + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -12764,6 +12859,14 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "requires": { + "path-type": "^4.0.0" + } + }, "dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", @@ -12832,6 +12935,11 @@ "domelementtype": "^2.3.0" } }, + "dompurify": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.5.tgz", + "integrity": "sha512-lwG+n5h8QNpxtyrJW/gJWckL+1/DQiYMX8f7t8Z2AZTPw1esVrqjI63i7Zc2Gz0aKzLVMYC1V1PL/ky+aY/NgA==" + }, "domutils": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", @@ -12907,6 +13015,11 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.761.tgz", "integrity": "sha512-PIbxpiJGx6Bb8dQaonNc6CGTRlVntdLg/2nMa1YhnrwYOORY9a3ZgGN0UQYE6lAcj/lkyduJN7BPt/JiY+jAQQ==" }, + "elkjs": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.3.tgz", + "integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==" + }, "emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -13183,6 +13296,12 @@ "text-table": "^0.2.0" }, "dependencies": { + "@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -14045,6 +14164,21 @@ } } }, + "eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "dev": true, + "requires": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + } + }, "eslint-module-utils": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", @@ -14390,8 +14524,50 @@ "eslint-visitor-keys": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==" + }, + "eslint-webpack-plugin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-4.2.0.tgz", + "integrity": "sha512-rsfpFQ01AWQbqtjgPRr2usVRxhWDuG0YDYcG8DJOteD3EFnpeuYuOwk0PQiN7PRBTqS6ElNdtPZPggj8If9WnA==", + "requires": { + "@types/eslint": "^8.56.10", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "schema-utils": "^4.2.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "requires": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==" }, "espree": { "version": "9.6.1", @@ -14702,6 +14878,11 @@ "tmp": "^0.0.33" } }, + "extract-colors": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/extract-colors/-/extract-colors-4.0.6.tgz", + "integrity": "sha512-U+pYyQKXCSHOmtZPIEJBGLJjLDiqS+oOub2ILA3a7UGt9+IvZvwAN3hOPFjUgT+gX/apSBwP5vBgnKMlV0fy8Q==" + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -14728,6 +14909,18 @@ "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" }, + "fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -14748,7 +14941,6 @@ "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, "requires": { "reusify": "^1.0.4" } @@ -15491,6 +15683,13 @@ "@turf/meta": "6.x", "@types/geojson": "7946.0.8", "rbush": "^3.0.1" + }, + "dependencies": { + "@types/geojson": { + "version": "7946.0.8", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz", + "integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==" + } } }, "geojson-vt": { @@ -15552,6 +15751,15 @@ "get-intrinsic": "^1.2.4" } }, + "get-tsconfig": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", + "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", + "dev": true, + "requires": { + "resolve-pkg-maps": "^1.0.0" + } + }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -15646,9 +15854,10 @@ } }, "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.4.0.tgz", + "integrity": "sha512-unnwvMZpv0eDUyjNyh9DH/yxUaRYrEjW/qK4QcdrHg3oO11igUQrCSgODHEqxlKg8v2CD2Sd7UkqqEBoz5U7TQ==", + "dev": true }, "globalthis": { "version": "1.0.4", @@ -15660,6 +15869,19 @@ "gopd": "^1.0.1" } }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, "golden-layout": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/golden-layout/-/golden-layout-2.6.0.tgz", @@ -15865,6 +16087,40 @@ "function-bind": "^1.1.2" } }, + "hast-util-from-dom": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.0.tgz", + "integrity": "sha512-d6235voAp/XR3Hh5uy7aGLbM3S4KamdW0WEgOaU1YoewnuYw4HXb5eRtv9g65m/RFGEfUY1Mw4UqCc5Y8L4Stg==", + "requires": { + "@types/hast": "^3.0.0", + "hastscript": "^8.0.0", + "web-namespaces": "^2.0.0" + } + }, + "hast-util-from-html": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.1.tgz", + "integrity": "sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==", + "requires": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + } + }, + "hast-util-from-html-isomorphic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz", + "integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==", + "requires": { + "@types/hast": "^3.0.0", + "hast-util-from-dom": "^5.0.0", + "hast-util-from-html": "^2.0.0", + "unist-util-remove-position": "^5.0.0" + } + }, "hast-util-from-parse5": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz", @@ -15880,6 +16136,14 @@ "web-namespaces": "^2.0.0" } }, + "hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "requires": { + "@types/hast": "^3.0.0" + } + }, "hast-util-parse-selector": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", @@ -15944,6 +16208,17 @@ "zwitch": "^2.0.0" } }, + "hast-util-to-text": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "requires": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" + } + }, "hast-util-whitespace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", @@ -17167,6 +17442,11 @@ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==" + }, "is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", @@ -17266,6 +17546,64 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -17623,6 +17961,21 @@ "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==" }, + "katex": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.10.tgz", + "integrity": "sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==", + "requires": { + "commander": "^8.3.0" + }, + "dependencies": { + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" + } + } + }, "kdbush": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz", @@ -17644,6 +17997,11 @@ "json-buffer": "3.0.1" } }, + "khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -17657,6 +18015,11 @@ "graceful-fs": "^4.1.9" } }, + "kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==" + }, "kruptein": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/kruptein/-/kruptein-3.0.6.tgz", @@ -17715,6 +18078,11 @@ "shell-quote": "^1.8.1" } }, + "layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==" + }, "lazystream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", @@ -17739,7 +18107,12 @@ } } }, - "node_modules/leac": { + "ldrs": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ldrs/-/ldrs-1.0.2.tgz", + "integrity": "sha512-sYJmivdkIiHrUEqTrEWccBoLdaENpzbzkABI5rk8rRxTXrg9i2xVuDvUUuhOhJY3RmQyaoxs046pM1DCRdcIpg==" + }, + "leac": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz", "integrity": "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==" @@ -17767,6 +18140,14 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, + "linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "requires": { + "uc.micro": "^2.0.0" + } + }, "load-bmfont": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", @@ -18058,6 +18439,26 @@ "vt-pbf": "^3.1.3" } }, + "markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "requires": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + } + } + }, "markdown-table": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", @@ -18077,6 +18478,17 @@ "mr-parser": "^0.2.1" } }, + "mathjax-full": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/mathjax-full/-/mathjax-full-3.2.2.tgz", + "integrity": "sha512-+LfG9Fik+OuI8SLwsiR02IVdjcnRCy5MufYLi0C3TdMT56L/pjB0alMVGgoWJF8pN9Rc7FESycZB9BMNWIid5w==", + "requires": { + "esm": "^3.2.25", + "mhchemparser": "^4.1.0", + "mj-context-menu": "^0.6.1", + "speech-rule-engine": "^4.0.6" + } + }, "mathquill": { "version": "0.10.1-a", "resolved": "https://registry.npmjs.org/mathquill/-/mathquill-0.10.1-a.tgz", @@ -18205,6 +18617,20 @@ "mdast-util-to-markdown": "^2.0.0" } }, + "mdast-util-math": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz", + "integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==", + "requires": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "longest-streak": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.1.0", + "unist-util-remove-position": "^5.0.0" + } + }, "mdast-util-mdx-expression": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz", @@ -18299,6 +18725,11 @@ "@types/mdast": "^4.0.0" } }, + "mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==" + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -18337,11 +18768,309 @@ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + }, + "mermaid": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.9.1.tgz", + "integrity": "sha512-Mx45Obds5W1UkW1nv/7dHRsbfMM1aOKA2+Pxs/IGHNonygDHwmng8xTHyS9z4KWVi0rbko8gjiBmuwwXQ7tiNA==", + "requires": { + "@braintree/sanitize-url": "^6.0.1", + "@types/d3-scale": "^4.0.3", + "@types/d3-scale-chromatic": "^3.0.0", + "cytoscape": "^3.28.1", + "cytoscape-cose-bilkent": "^4.1.0", + "d3": "^7.4.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.10", + "dayjs": "^1.11.7", + "dompurify": "^3.0.5", + "elkjs": "^0.9.0", + "katex": "^0.16.9", + "khroma": "^2.0.0", + "lodash-es": "^4.17.21", + "mdast-util-from-markdown": "^1.3.0", + "non-layered-tidy-tree-layout": "^2.0.2", + "stylis": "^4.1.3", + "ts-dedent": "^2.2.0", + "uuid": "^9.0.0", + "web-worker": "^1.2.0" + }, + "dependencies": { + "@types/mdast": { + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", + "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", + "requires": { + "@types/unist": "^2" + } + }, + "@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + }, + "mdast-util-from-markdown": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz", + "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==", + "requires": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "mdast-util-to-string": "^3.1.0", + "micromark": "^3.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-decode-string": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "unist-util-stringify-position": "^3.0.0", + "uvu": "^0.5.0" + } + }, + "mdast-util-to-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", + "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", + "requires": { + "@types/mdast": "^3.0.0" + } + }, + "micromark": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", + "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==", + "requires": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "micromark-core-commonmark": "^1.0.1", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-chunked": "^1.0.0", + "micromark-util-combine-extensions": "^1.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-subtokenize": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.1", + "uvu": "^0.5.0" + } + }, + "micromark-core-commonmark": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz", + "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", + "requires": { + "decode-named-character-reference": "^1.0.0", + "micromark-factory-destination": "^1.0.0", + "micromark-factory-label": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-factory-title": "^1.0.0", + "micromark-factory-whitespace": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-chunked": "^1.0.0", + "micromark-util-classify-character": "^1.0.0", + "micromark-util-html-tag-name": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-subtokenize": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.1", + "uvu": "^0.5.0" + } + }, + "micromark-factory-destination": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz", + "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==", + "requires": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "micromark-factory-label": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz", + "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==", + "requires": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "micromark-factory-space": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", + "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "requires": { + "micromark-util-character": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "micromark-factory-title": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz", + "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==", + "requires": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "micromark-factory-whitespace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz", + "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==", + "requires": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "requires": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "micromark-util-chunked": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz", + "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", + "requires": { + "micromark-util-symbol": "^1.0.0" + } + }, + "micromark-util-classify-character": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz", + "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", + "requires": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "micromark-util-combine-extensions": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz", + "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==", + "requires": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "micromark-util-decode-numeric-character-reference": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz", + "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==", + "requires": { + "micromark-util-symbol": "^1.0.0" + } + }, + "micromark-util-decode-string": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz", + "integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==", + "requires": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-symbol": "^1.0.0" + } + }, + "micromark-util-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", + "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==" + }, + "micromark-util-html-tag-name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz", + "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==" + }, + "micromark-util-normalize-identifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz", + "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", + "requires": { + "micromark-util-symbol": "^1.0.0" + } + }, + "micromark-util-resolve-all": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz", + "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", + "requires": { + "micromark-util-types": "^1.0.0" + } + }, + "micromark-util-sanitize-uri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", + "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", + "requires": { + "micromark-util-character": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-symbol": "^1.0.0" + } + }, + "micromark-util-subtokenize": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz", + "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==", + "requires": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==" + }, + "micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==" + }, + "unist-util-stringify-position": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", + "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", + "requires": { + "@types/unist": "^2.0.0" + } + } + } + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, + "mhchemparser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/mhchemparser/-/mhchemparser-4.2.1.tgz", + "integrity": "sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ==" + }, "micromark": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", @@ -18475,6 +19204,20 @@ "micromark-util-types": "^2.0.0" } }, + "micromark-extension-math": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.0.0.tgz", + "integrity": "sha512-iJ2Q28vBoEovLN5o3GO12CpqorQRYDPT+p4zW50tGwTfJB+iv/VnB6Ini+gqa24K97DwptMBBIvVX6Bjk49oyQ==", + "requires": { + "@types/katex": "^0.16.0", + "devlop": "^1.0.0", + "katex": "^0.16.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, "micromark-factory-destination": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", @@ -18736,6 +19479,11 @@ } } }, + "mj-context-menu": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.6.1.tgz", + "integrity": "sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA==" + }, "mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -19044,6 +19792,11 @@ "resolved": "https://registry.npmjs.org/mr-parser/-/mr-parser-0.2.1.tgz", "integrity": "sha512-hug+mpbSSKnH13rFqy3zm+XiG+QTStiDAgMTHK355TIstQE0qBkBtSJsa5YHP94AuarVX9b/4dcebdTRZ9YiEw==" }, + "mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==" + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -19102,9 +19855,9 @@ "dev": true }, "nan": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz", - "integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz", + "integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==", "optional": true }, "nanoid": { @@ -19256,6 +20009,11 @@ } } }, + "non-layered-tidy-tree-layout": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", + "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==" + }, "nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -19352,7 +20110,7 @@ "dependencies": { "@isaacs/cliui": { "version": "8.0.2", - "bundled": true, + "resolved": false, "requires": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -19364,7 +20122,7 @@ "dependencies": { "ansi-regex": { "version": "6.0.1", - "bundled": true + "resolved": false }, "ansi-styles": { "version": "4.3.0", @@ -19376,11 +20134,11 @@ }, "emoji-regex": { "version": "9.2.2", - "bundled": true + "resolved": false }, "string-width": { "version": "5.1.2", - "bundled": true, + "resolved": false, "requires": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -19419,7 +20177,7 @@ }, "strip-ansi": { "version": "7.1.0", - "bundled": true, + "resolved": false, "requires": { "ansi-regex": "^6.0.1" } @@ -19483,11 +20241,11 @@ }, "@isaacs/string-locale-compare": { "version": "1.1.0", - "bundled": true + "resolved": false }, "@npmcli/agent": { "version": "2.2.2", - "bundled": true, + "resolved": false, "requires": { "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", @@ -19498,7 +20256,7 @@ }, "@npmcli/arborist": { "version": "7.5.3", - "bundled": true, + "resolved": false, "requires": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/fs": "^3.1.1", @@ -19539,7 +20297,7 @@ }, "@npmcli/config": { "version": "8.3.3", - "bundled": true, + "resolved": false, "requires": { "@npmcli/map-workspaces": "^3.0.2", "ci-info": "^4.0.0", @@ -19553,14 +20311,14 @@ }, "@npmcli/fs": { "version": "3.1.1", - "bundled": true, + "resolved": false, "requires": { "semver": "^7.3.5" } }, "@npmcli/git": { "version": "5.0.7", - "bundled": true, + "resolved": false, "requires": { "@npmcli/promise-spawn": "^7.0.0", "lru-cache": "^10.0.1", @@ -19574,7 +20332,7 @@ }, "@npmcli/installed-package-contents": { "version": "2.1.0", - "bundled": true, + "resolved": false, "requires": { "npm-bundled": "^3.0.0", "npm-normalize-package-bin": "^3.0.0" @@ -19582,7 +20340,7 @@ }, "@npmcli/map-workspaces": { "version": "3.0.6", - "bundled": true, + "resolved": false, "requires": { "@npmcli/name-from-folder": "^2.0.0", "glob": "^10.2.2", @@ -19592,7 +20350,7 @@ }, "@npmcli/metavuln-calculator": { "version": "7.1.1", - "bundled": true, + "resolved": false, "requires": { "cacache": "^18.0.0", "json-parse-even-better-errors": "^3.0.0", @@ -19603,15 +20361,15 @@ }, "@npmcli/name-from-folder": { "version": "2.0.0", - "bundled": true + "resolved": false }, "@npmcli/node-gyp": { "version": "3.0.0", - "bundled": true + "resolved": false }, "@npmcli/package-json": { "version": "5.1.1", - "bundled": true, + "resolved": false, "requires": { "@npmcli/git": "^5.0.0", "glob": "^10.2.2", @@ -19624,25 +20382,25 @@ }, "@npmcli/promise-spawn": { "version": "7.0.2", - "bundled": true, + "resolved": false, "requires": { "which": "^4.0.0" } }, "@npmcli/query": { "version": "3.1.0", - "bundled": true, + "resolved": false, "requires": { "postcss-selector-parser": "^6.0.10" } }, "@npmcli/redact": { "version": "2.0.0", - "bundled": true + "resolved": false }, "@npmcli/run-script": { "version": "8.1.0", - "bundled": true, + "resolved": false, "requires": { "@npmcli/node-gyp": "^3.0.0", "@npmcli/package-json": "^5.0.0", @@ -19654,27 +20412,27 @@ }, "@pkgjs/parseargs": { "version": "0.11.0", - "bundled": true, + "resolved": false, "optional": true }, "@sigstore/bundle": { "version": "2.3.2", - "bundled": true, + "resolved": false, "requires": { "@sigstore/protobuf-specs": "^0.3.2" } }, "@sigstore/core": { "version": "1.1.0", - "bundled": true + "resolved": false }, "@sigstore/protobuf-specs": { "version": "0.3.2", - "bundled": true + "resolved": false }, "@sigstore/sign": { "version": "2.3.2", - "bundled": true, + "resolved": false, "requires": { "@sigstore/bundle": "^2.3.2", "@sigstore/core": "^1.0.0", @@ -19686,7 +20444,7 @@ }, "@sigstore/tuf": { "version": "2.3.4", - "bundled": true, + "resolved": false, "requires": { "@sigstore/protobuf-specs": "^0.3.2", "tuf-js": "^2.2.1" @@ -19694,7 +20452,7 @@ }, "@sigstore/verify": { "version": "1.2.1", - "bundled": true, + "resolved": false, "requires": { "@sigstore/bundle": "^2.3.2", "@sigstore/core": "^1.1.0", @@ -19703,11 +20461,11 @@ }, "@tufjs/canonical-json": { "version": "2.0.0", - "bundled": true + "resolved": false }, "@tufjs/models": { "version": "2.0.1", - "bundled": true, + "resolved": false, "requires": { "@tufjs/canonical-json": "2.0.0", "minimatch": "^9.0.4" @@ -19715,18 +20473,18 @@ }, "abbrev": { "version": "2.0.0", - "bundled": true + "resolved": false }, "agent-base": { "version": "7.1.1", - "bundled": true, + "resolved": false, "requires": { "debug": "^4.3.4" } }, "aggregate-error": { "version": "3.1.0", - "bundled": true, + "resolved": false, "requires": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -19734,27 +20492,27 @@ }, "ansi-regex": { "version": "5.0.1", - "bundled": true + "resolved": false }, "ansi-styles": { "version": "6.2.1", - "bundled": true + "resolved": false }, "aproba": { "version": "2.0.0", - "bundled": true + "resolved": false }, "archy": { "version": "1.0.0", - "bundled": true + "resolved": false }, "balanced-match": { "version": "1.0.2", - "bundled": true + "resolved": false }, "bin-links": { "version": "4.0.4", - "bundled": true, + "resolved": false, "requires": { "cmd-shim": "^6.0.0", "npm-normalize-package-bin": "^3.0.0", @@ -19764,18 +20522,18 @@ }, "binary-extensions": { "version": "2.3.0", - "bundled": true + "resolved": false }, "brace-expansion": { "version": "2.0.1", - "bundled": true, + "resolved": false, "requires": { "balanced-match": "^1.0.0" } }, "cacache": { "version": "18.0.3", - "bundled": true, + "resolved": false, "requires": { "@npmcli/fs": "^3.1.0", "fs-minipass": "^3.0.0", @@ -19793,30 +20551,30 @@ }, "chalk": { "version": "5.3.0", - "bundled": true + "resolved": false }, "chownr": { "version": "2.0.0", - "bundled": true + "resolved": false }, "ci-info": { "version": "4.0.0", - "bundled": true + "resolved": false }, "cidr-regex": { "version": "4.1.1", - "bundled": true, + "resolved": false, "requires": { "ip-regex": "^5.0.0" } }, "clean-stack": { "version": "2.2.0", - "bundled": true + "resolved": false }, "cli-columns": { "version": "4.0.0", - "bundled": true, + "resolved": false, "requires": { "string-width": "^4.2.3", "strip-ansi": "^6.0.1" @@ -19824,26 +20582,26 @@ }, "cmd-shim": { "version": "6.0.3", - "bundled": true + "resolved": false }, "color-convert": { "version": "2.0.1", - "bundled": true, + "resolved": false, "requires": { "color-name": "~1.1.4" } }, "color-name": { "version": "1.1.4", - "bundled": true + "resolved": false }, "common-ancestor-path": { "version": "1.0.1", - "bundled": true + "resolved": false }, "cross-spawn": { "version": "7.0.3", - "bundled": true, + "resolved": false, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -19852,7 +20610,7 @@ "dependencies": { "which": { "version": "2.0.2", - "bundled": true, + "resolved": false, "requires": { "isexe": "^2.0.0" } @@ -19861,36 +20619,36 @@ }, "cssesc": { "version": "3.0.0", - "bundled": true + "resolved": false }, "debug": { "version": "4.3.4", - "bundled": true, + "resolved": false, "requires": { "ms": "2.1.2" }, "dependencies": { "ms": { "version": "2.1.2", - "bundled": true + "resolved": false } } }, "diff": { "version": "5.2.0", - "bundled": true + "resolved": false }, "eastasianwidth": { "version": "0.2.0", - "bundled": true + "resolved": false }, "emoji-regex": { "version": "8.0.0", - "bundled": true + "resolved": false }, "encoding": { "version": "0.1.13", - "bundled": true, + "resolved": false, "optional": true, "requires": { "iconv-lite": "^0.6.2" @@ -19898,23 +20656,23 @@ }, "env-paths": { "version": "2.2.1", - "bundled": true + "resolved": false }, "err-code": { "version": "2.0.3", - "bundled": true + "resolved": false }, "exponential-backoff": { "version": "3.1.1", - "bundled": true + "resolved": false }, "fastest-levenshtein": { "version": "1.0.16", - "bundled": true + "resolved": false }, "foreground-child": { "version": "3.1.1", - "bundled": true, + "resolved": false, "requires": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -19922,18 +20680,18 @@ }, "fs-minipass": { "version": "3.0.3", - "bundled": true, + "resolved": false, "requires": { "minipass": "^7.0.3" } }, "function-bind": { "version": "1.1.2", - "bundled": true + "resolved": false }, "glob": { "version": "10.4.1", - "bundled": true, + "resolved": false, "requires": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -19944,29 +20702,29 @@ }, "graceful-fs": { "version": "4.2.11", - "bundled": true + "resolved": false }, "hasown": { "version": "2.0.2", - "bundled": true, + "resolved": false, "requires": { "function-bind": "^1.1.2" } }, "hosted-git-info": { "version": "7.0.2", - "bundled": true, + "resolved": false, "requires": { "lru-cache": "^10.0.1" } }, "http-cache-semantics": { "version": "4.1.1", - "bundled": true + "resolved": false }, "http-proxy-agent": { "version": "7.0.2", - "bundled": true, + "resolved": false, "requires": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -19974,7 +20732,7 @@ }, "https-proxy-agent": { "version": "7.0.4", - "bundled": true, + "resolved": false, "requires": { "agent-base": "^7.0.2", "debug": "4" @@ -19982,7 +20740,7 @@ }, "iconv-lite": { "version": "0.6.3", - "bundled": true, + "resolved": false, "optional": true, "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -19990,26 +20748,26 @@ }, "ignore-walk": { "version": "6.0.5", - "bundled": true, + "resolved": false, "requires": { "minimatch": "^9.0.0" } }, "imurmurhash": { "version": "0.1.4", - "bundled": true + "resolved": false }, "indent-string": { "version": "4.0.0", - "bundled": true + "resolved": false }, "ini": { "version": "4.1.3", - "bundled": true + "resolved": false }, "init-package-json": { "version": "6.0.3", - "bundled": true, + "resolved": false, "requires": { "@npmcli/package-json": "^5.0.0", "npm-package-arg": "^11.0.0", @@ -20022,7 +20780,7 @@ }, "ip-address": { "version": "9.0.5", - "bundled": true, + "resolved": false, "requires": { "jsbn": "1.1.0", "sprintf-js": "^1.1.3" @@ -20030,37 +20788,37 @@ }, "ip-regex": { "version": "5.0.0", - "bundled": true + "resolved": false }, "is-cidr": { "version": "5.1.0", - "bundled": true, + "resolved": false, "requires": { "cidr-regex": "^4.1.1" } }, "is-core-module": { "version": "2.13.1", - "bundled": true, + "resolved": false, "requires": { "hasown": "^2.0.0" } }, "is-fullwidth-code-point": { "version": "3.0.0", - "bundled": true + "resolved": false }, "is-lambda": { "version": "1.0.1", - "bundled": true + "resolved": false }, "isexe": { "version": "2.0.0", - "bundled": true + "resolved": false }, "jackspeak": { "version": "3.1.2", - "bundled": true, + "resolved": false, "requires": { "@isaacs/cliui": "^8.0.2", "@pkgjs/parseargs": "^0.11.0" @@ -20068,31 +20826,31 @@ }, "jsbn": { "version": "1.1.0", - "bundled": true + "resolved": false }, "json-parse-even-better-errors": { "version": "3.0.2", - "bundled": true + "resolved": false }, "json-stringify-nice": { "version": "1.1.4", - "bundled": true + "resolved": false }, "jsonparse": { "version": "1.3.1", - "bundled": true + "resolved": false }, "just-diff": { "version": "6.0.2", - "bundled": true + "resolved": false }, "just-diff-apply": { "version": "5.5.0", - "bundled": true + "resolved": false }, "libnpmaccess": { "version": "8.0.6", - "bundled": true, + "resolved": false, "requires": { "npm-package-arg": "^11.0.2", "npm-registry-fetch": "^17.0.1" @@ -20100,7 +20858,7 @@ }, "libnpmdiff": { "version": "6.1.3", - "bundled": true, + "resolved": false, "requires": { "@npmcli/arborist": "^7.5.3", "@npmcli/installed-package-contents": "^2.1.0", @@ -20114,7 +20872,7 @@ }, "libnpmexec": { "version": "8.1.2", - "bundled": true, + "resolved": false, "requires": { "@npmcli/arborist": "^7.5.3", "@npmcli/run-script": "^8.1.0", @@ -20130,14 +20888,14 @@ }, "libnpmfund": { "version": "5.0.11", - "bundled": true, + "resolved": false, "requires": { "@npmcli/arborist": "^7.5.3" } }, "libnpmhook": { "version": "10.0.5", - "bundled": true, + "resolved": false, "requires": { "aproba": "^2.0.0", "npm-registry-fetch": "^17.0.1" @@ -20145,7 +20903,7 @@ }, "libnpmorg": { "version": "6.0.6", - "bundled": true, + "resolved": false, "requires": { "aproba": "^2.0.0", "npm-registry-fetch": "^17.0.1" @@ -20153,7 +20911,7 @@ }, "libnpmpack": { "version": "7.0.3", - "bundled": true, + "resolved": false, "requires": { "@npmcli/arborist": "^7.5.3", "@npmcli/run-script": "^8.1.0", @@ -20163,7 +20921,7 @@ }, "libnpmpublish": { "version": "9.0.9", - "bundled": true, + "resolved": false, "requires": { "ci-info": "^4.0.0", "normalize-package-data": "^6.0.1", @@ -20177,14 +20935,14 @@ }, "libnpmsearch": { "version": "7.0.6", - "bundled": true, + "resolved": false, "requires": { "npm-registry-fetch": "^17.0.1" } }, "libnpmteam": { "version": "6.0.5", - "bundled": true, + "resolved": false, "requires": { "aproba": "^2.0.0", "npm-registry-fetch": "^17.0.1" @@ -20192,7 +20950,7 @@ }, "libnpmversion": { "version": "6.0.3", - "bundled": true, + "resolved": false, "requires": { "@npmcli/git": "^5.0.7", "@npmcli/run-script": "^8.1.0", @@ -20203,11 +20961,11 @@ }, "lru-cache": { "version": "10.2.2", - "bundled": true + "resolved": false }, "make-fetch-happen": { "version": "13.0.1", - "bundled": true, + "resolved": false, "requires": { "@npmcli/agent": "^2.0.0", "cacache": "^18.0.0", @@ -20225,25 +20983,25 @@ }, "minimatch": { "version": "9.0.4", - "bundled": true, + "resolved": false, "requires": { "brace-expansion": "^2.0.1" } }, "minipass": { "version": "7.1.2", - "bundled": true + "resolved": false }, "minipass-collect": { "version": "2.0.1", - "bundled": true, + "resolved": false, "requires": { "minipass": "^7.0.3" } }, "minipass-fetch": { "version": "3.0.5", - "bundled": true, + "resolved": false, "requires": { "encoding": "^0.1.13", "minipass": "^7.0.3", @@ -20253,14 +21011,14 @@ }, "minipass-flush": { "version": "1.0.5", - "bundled": true, + "resolved": false, "requires": { "minipass": "^3.0.0" }, "dependencies": { "minipass": { "version": "3.3.6", - "bundled": true, + "resolved": false, "requires": { "yallist": "^4.0.0" } @@ -20269,7 +21027,7 @@ }, "minipass-json-stream": { "version": "1.0.1", - "bundled": true, + "resolved": false, "requires": { "jsonparse": "^1.3.1", "minipass": "^3.0.0" @@ -20277,7 +21035,7 @@ "dependencies": { "minipass": { "version": "3.3.6", - "bundled": true, + "resolved": false, "requires": { "yallist": "^4.0.0" } @@ -20286,14 +21044,14 @@ }, "minipass-pipeline": { "version": "1.2.4", - "bundled": true, + "resolved": false, "requires": { "minipass": "^3.0.0" }, "dependencies": { "minipass": { "version": "3.3.6", - "bundled": true, + "resolved": false, "requires": { "yallist": "^4.0.0" } @@ -20302,14 +21060,14 @@ }, "minipass-sized": { "version": "1.0.3", - "bundled": true, + "resolved": false, "requires": { "minipass": "^3.0.0" }, "dependencies": { "minipass": { "version": "3.3.6", - "bundled": true, + "resolved": false, "requires": { "yallist": "^4.0.0" } @@ -20318,7 +21076,7 @@ }, "minizlib": { "version": "2.1.2", - "bundled": true, + "resolved": false, "requires": { "minipass": "^3.0.0", "yallist": "^4.0.0" @@ -20326,7 +21084,7 @@ "dependencies": { "minipass": { "version": "3.3.6", - "bundled": true, + "resolved": false, "requires": { "yallist": "^4.0.0" } @@ -20335,23 +21093,23 @@ }, "mkdirp": { "version": "1.0.4", - "bundled": true + "resolved": false }, "ms": { "version": "2.1.3", - "bundled": true + "resolved": false }, "mute-stream": { "version": "1.0.0", - "bundled": true + "resolved": false }, "negotiator": { "version": "0.6.3", - "bundled": true + "resolved": false }, "node-gyp": { "version": "10.1.0", - "bundled": true, + "resolved": false, "requires": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", @@ -20367,20 +21125,20 @@ "dependencies": { "proc-log": { "version": "3.0.0", - "bundled": true + "resolved": false } } }, "nopt": { "version": "7.2.1", - "bundled": true, + "resolved": false, "requires": { "abbrev": "^2.0.0" } }, "normalize-package-data": { "version": "6.0.1", - "bundled": true, + "resolved": false, "requires": { "hosted-git-info": "^7.0.0", "is-core-module": "^2.8.1", @@ -20390,29 +21148,29 @@ }, "npm-audit-report": { "version": "5.0.0", - "bundled": true + "resolved": false }, "npm-bundled": { "version": "3.0.1", - "bundled": true, + "resolved": false, "requires": { "npm-normalize-package-bin": "^3.0.0" } }, "npm-install-checks": { "version": "6.3.0", - "bundled": true, + "resolved": false, "requires": { "semver": "^7.1.1" } }, "npm-normalize-package-bin": { "version": "3.0.1", - "bundled": true + "resolved": false }, "npm-package-arg": { "version": "11.0.2", - "bundled": true, + "resolved": false, "requires": { "hosted-git-info": "^7.0.0", "proc-log": "^4.0.0", @@ -20422,14 +21180,14 @@ }, "npm-packlist": { "version": "8.0.2", - "bundled": true, + "resolved": false, "requires": { "ignore-walk": "^6.0.4" } }, "npm-pick-manifest": { "version": "9.0.1", - "bundled": true, + "resolved": false, "requires": { "npm-install-checks": "^6.0.0", "npm-normalize-package-bin": "^3.0.0", @@ -20439,7 +21197,7 @@ }, "npm-profile": { "version": "10.0.0", - "bundled": true, + "resolved": false, "requires": { "npm-registry-fetch": "^17.0.1", "proc-log": "^4.0.0" @@ -20447,7 +21205,7 @@ }, "npm-registry-fetch": { "version": "17.0.1", - "bundled": true, + "resolved": false, "requires": { "@npmcli/redact": "^2.0.0", "make-fetch-happen": "^13.0.0", @@ -20461,18 +21219,18 @@ }, "npm-user-validate": { "version": "2.0.1", - "bundled": true + "resolved": false }, "p-map": { "version": "4.0.0", - "bundled": true, + "resolved": false, "requires": { "aggregate-error": "^3.0.0" } }, "pacote": { "version": "18.0.6", - "bundled": true, + "resolved": false, "requires": { "@npmcli/git": "^5.0.0", "@npmcli/installed-package-contents": "^2.0.1", @@ -20495,7 +21253,7 @@ }, "parse-conflict-json": { "version": "3.0.1", - "bundled": true, + "resolved": false, "requires": { "json-parse-even-better-errors": "^3.0.0", "just-diff": "^6.0.0", @@ -20504,11 +21262,11 @@ }, "path-key": { "version": "3.1.1", - "bundled": true + "resolved": false }, "path-scurry": { "version": "1.11.1", - "bundled": true, + "resolved": false, "requires": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -20516,7 +21274,7 @@ }, "postcss-selector-parser": { "version": "6.1.0", - "bundled": true, + "resolved": false, "requires": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -20524,27 +21282,27 @@ }, "proc-log": { "version": "4.2.0", - "bundled": true + "resolved": false }, "proggy": { "version": "2.0.0", - "bundled": true + "resolved": false }, "promise-all-reject-late": { "version": "1.0.1", - "bundled": true + "resolved": false }, "promise-call-limit": { "version": "3.0.1", - "bundled": true + "resolved": false }, "promise-inflight": { "version": "1.0.1", - "bundled": true + "resolved": false }, "promise-retry": { "version": "2.0.1", - "bundled": true, + "resolved": false, "requires": { "err-code": "^2.0.2", "retry": "^0.12.0" @@ -20552,29 +21310,29 @@ }, "promzard": { "version": "1.0.2", - "bundled": true, + "resolved": false, "requires": { "read": "^3.0.1" } }, "qrcode-terminal": { "version": "0.12.0", - "bundled": true + "resolved": false }, "read": { "version": "3.0.1", - "bundled": true, + "resolved": false, "requires": { "mute-stream": "^1.0.0" } }, "read-cmd-shim": { "version": "4.0.0", - "bundled": true + "resolved": false }, "read-package-json-fast": { "version": "3.0.2", - "bundled": true, + "resolved": false, "requires": { "json-parse-even-better-errors": "^3.0.0", "npm-normalize-package-bin": "^3.0.0" @@ -20582,35 +21340,35 @@ }, "retry": { "version": "0.12.0", - "bundled": true + "resolved": false }, "safer-buffer": { "version": "2.1.2", - "bundled": true, + "resolved": false, "optional": true }, "semver": { "version": "7.6.2", - "bundled": true + "resolved": false }, "shebang-command": { "version": "2.0.0", - "bundled": true, + "resolved": false, "requires": { "shebang-regex": "^3.0.0" } }, "shebang-regex": { "version": "3.0.0", - "bundled": true + "resolved": false }, "signal-exit": { "version": "4.1.0", - "bundled": true + "resolved": false }, "sigstore": { "version": "2.3.1", - "bundled": true, + "resolved": false, "requires": { "@sigstore/bundle": "^2.3.2", "@sigstore/core": "^1.0.0", @@ -20622,11 +21380,11 @@ }, "smart-buffer": { "version": "4.2.0", - "bundled": true + "resolved": false }, "socks": { "version": "2.8.3", - "bundled": true, + "resolved": false, "requires": { "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" @@ -20634,7 +21392,7 @@ }, "socks-proxy-agent": { "version": "8.0.3", - "bundled": true, + "resolved": false, "requires": { "agent-base": "^7.1.1", "debug": "^4.3.4", @@ -20643,7 +21401,7 @@ }, "spdx-correct": { "version": "3.2.0", - "bundled": true, + "resolved": false, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -20651,7 +21409,7 @@ "dependencies": { "spdx-expression-parse": { "version": "3.0.1", - "bundled": true, + "resolved": false, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -20661,11 +21419,11 @@ }, "spdx-exceptions": { "version": "2.5.0", - "bundled": true + "resolved": false }, "spdx-expression-parse": { "version": "4.0.0", - "bundled": true, + "resolved": false, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -20673,22 +21431,22 @@ }, "spdx-license-ids": { "version": "3.0.18", - "bundled": true + "resolved": false }, "sprintf-js": { "version": "1.1.3", - "bundled": true + "resolved": false }, "ssri": { "version": "10.0.6", - "bundled": true, + "resolved": false, "requires": { "minipass": "^7.0.3" } }, "string-width": { "version": "4.2.3", - "bundled": true, + "resolved": false, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -20697,7 +21455,7 @@ }, "string-width-cjs": { "version": "npm:string-width-cjs@4.2.3", - "bundled": true, + "resolved": false, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -20706,25 +21464,25 @@ }, "strip-ansi": { "version": "6.0.1", - "bundled": true, + "resolved": false, "requires": { "ansi-regex": "^5.0.1" } }, "strip-ansi-cjs": { "version": "npm:strip-ansi-cjs@6.0.1", - "bundled": true, + "resolved": false, "requires": { "ansi-regex": "^5.0.1" } }, "supports-color": { "version": "9.4.0", - "bundled": true + "resolved": false }, "tar": { "version": "6.2.1", - "bundled": true, + "resolved": false, "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -20736,14 +21494,14 @@ "dependencies": { "fs-minipass": { "version": "2.1.0", - "bundled": true, + "resolved": false, "requires": { "minipass": "^3.0.0" }, "dependencies": { "minipass": { "version": "3.3.6", - "bundled": true, + "resolved": false, "requires": { "yallist": "^4.0.0" } @@ -20752,25 +21510,25 @@ }, "minipass": { "version": "5.0.0", - "bundled": true + "resolved": false } } }, "text-table": { "version": "0.2.0", - "bundled": true + "resolved": false }, "tiny-relative-date": { "version": "1.3.0", - "bundled": true + "resolved": false }, "treeverse": { "version": "3.0.0", - "bundled": true + "resolved": false }, "tuf-js": { "version": "2.2.1", - "bundled": true, + "resolved": false, "requires": { "@tufjs/models": "2.0.1", "debug": "^4.3.4", @@ -20779,25 +21537,25 @@ }, "unique-filename": { "version": "3.0.0", - "bundled": true, + "resolved": false, "requires": { "unique-slug": "^4.0.0" } }, "unique-slug": { "version": "4.0.0", - "bundled": true, + "resolved": false, "requires": { "imurmurhash": "^0.1.4" } }, "util-deprecate": { "version": "1.0.2", - "bundled": true + "resolved": false }, "validate-npm-package-license": { "version": "3.0.4", - "bundled": true, + "resolved": false, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -20805,7 +21563,7 @@ "dependencies": { "spdx-expression-parse": { "version": "3.0.1", - "bundled": true, + "resolved": false, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -20815,28 +21573,28 @@ }, "validate-npm-package-name": { "version": "5.0.1", - "bundled": true + "resolved": false }, "walk-up-path": { "version": "3.0.1", - "bundled": true + "resolved": false }, "which": { "version": "4.0.0", - "bundled": true, + "resolved": false, "requires": { "isexe": "^3.1.1" }, "dependencies": { "isexe": { "version": "3.1.1", - "bundled": true + "resolved": false } } }, "wrap-ansi": { "version": "8.1.0", - "bundled": true, + "resolved": false, "requires": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -20845,15 +21603,15 @@ "dependencies": { "ansi-regex": { "version": "6.0.1", - "bundled": true + "resolved": false }, "emoji-regex": { "version": "9.2.2", - "bundled": true + "resolved": false }, "string-width": { "version": "5.1.2", - "bundled": true, + "resolved": false, "requires": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -20862,7 +21620,7 @@ }, "strip-ansi": { "version": "7.1.0", - "bundled": true, + "resolved": false, "requires": { "ansi-regex": "^6.0.1" } @@ -20871,7 +21629,7 @@ }, "wrap-ansi-cjs": { "version": "npm:wrap-ansi-cjs@7.0.0", - "bundled": true, + "resolved": false, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -20880,7 +21638,7 @@ "dependencies": { "ansi-styles": { "version": "4.3.0", - "bundled": true, + "resolved": false, "requires": { "color-convert": "^2.0.1" } @@ -20889,7 +21647,7 @@ }, "write-file-atomic": { "version": "5.0.1", - "bundled": true, + "resolved": false, "requires": { "imurmurhash": "^0.1.4", "signal-exit": "^4.0.1" @@ -20897,7 +21655,7 @@ }, "yallist": { "version": "4.0.0", - "bundled": true + "resolved": false } } }, @@ -22024,6 +22782,11 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" }, + "punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==" + }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -22069,8 +22832,7 @@ "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" }, "queue-tick": { "version": "1.0.1", @@ -22442,6 +23204,14 @@ } } }, + "react-latex-next": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-latex-next/-/react-latex-next-3.0.0.tgz", + "integrity": "sha512-x70f1b1G7TronVigsRgKHKYYVUNfZk/3bciFyYX1lYLQH2y3/TXku3+5Vap8MDbJhtopePSYBsYWS6jhzIdz+g==", + "requires": { + "katex": "^0.16.0" + } + }, "react-loading": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/react-loading/-/react-loading-2.0.3.tgz", @@ -22561,6 +23331,16 @@ "@react-types/shared": "^3.23.0" } }, + "react-textarea-autosize": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.3.tgz", + "integrity": "sha512-XT1024o2pqCuZSuBt9FwHlaDeNtVrtCXu0Rnz88t1jUGheCLa3PhjE1GH8Ctm2axEtvdCl5SUHYschyQ0L5QHQ==", + "requires": { + "@babel/runtime": "^7.20.13", + "use-composed-ref": "^1.3.0", + "use-latest": "^1.2.1" + } + }, "react-themeable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/react-themeable/-/react-themeable-1.1.0.tgz", @@ -22803,6 +23583,20 @@ "jsesc": "~0.5.0" } }, + "rehype-katex": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.0.tgz", + "integrity": "sha512-h8FPkGE00r2XKU+/acgqwWUlyzve1IiOKwsEkg4pDL3k48PiE0Pt+/uLtVHDVkN1yA4iurZN6UES8ivHVEQV6Q==", + "requires": { + "@types/hast": "^3.0.0", + "@types/katex": "^0.16.0", + "hast-util-from-html-isomorphic": "^2.0.0", + "hast-util-to-text": "^4.0.0", + "katex": "^0.16.0", + "unist-util-visit-parents": "^6.0.0", + "vfile": "^6.0.0" + } + }, "rehype-raw": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", @@ -22831,6 +23625,17 @@ "unified": "^11.0.0" } }, + "remark-math": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz", + "integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==", + "requires": { + "@types/mdast": "^4.0.0", + "mdast-util-math": "^3.0.0", + "micromark-extension-math": "^3.0.0", + "unified": "^11.0.0" + } + }, "remark-parse": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", @@ -23092,6 +23897,12 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, + "resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true + }, "resolve-protobuf-schema": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", @@ -23135,8 +23946,7 @@ "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" }, "reveal.js": { "version": "5.1.0", @@ -23183,7 +23993,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "requires": { "queue-microtask": "^1.2.2" } @@ -23210,6 +24019,14 @@ } } }, + "sade": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "requires": { + "mri": "^1.1.0" + } + }, "safe-array-concat": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", @@ -23689,6 +24506,11 @@ "resolved": "https://registry.npmjs.org/skmeans/-/skmeans-0.9.7.tgz", "integrity": "sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg==" }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, "slice-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", @@ -23880,6 +24702,23 @@ } } }, + "speech-rule-engine": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/speech-rule-engine/-/speech-rule-engine-4.0.7.tgz", + "integrity": "sha512-sJrL3/wHzNwJRLBdf6CjJWIlxC04iYKkyXvYSVsWVOiC2DSkHmxsqOhEeMsBA9XK+CHuNcsdkbFDnoUfAsmp9g==", + "requires": { + "commander": "9.2.0", + "wicked-good-xpath": "1.3.0", + "xmldom-sre": "0.1.31" + }, + "dependencies": { + "commander": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.2.0.tgz", + "integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==" + } + } + }, "splaytree": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/splaytree/-/splaytree-3.1.2.tgz", @@ -24620,6 +25459,16 @@ "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", "integrity": "sha512-6C5h3CE+0qjGp+YKYTs74xR0k/Nw/ePtl/Lp6CCf44hqBQ66qnH1sDFR5mV/Gc48EsrHLB53lCFSffQCkka3kg==" }, + "ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==" + }, + "ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==" + }, "ts-loader": { "version": "9.5.1", "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", @@ -25114,6 +25963,17 @@ "resolved": "https://registry.npmjs.org/typescript-collections/-/typescript-collections-1.3.3.tgz", "integrity": "sha512-7sI4e/bZijOzyURng88oOFZCISQPTHozfE2sUu5AviFYk5QV7fYGb6YiDl+vKjF/pICA354JImBImL9XJWUvdQ==" }, + "typescript-eslint": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.13.0.tgz", + "integrity": "sha512-upO0AXxyBwJ4BbiC6CRgAJKtGYha2zw4m1g7TIVPSonwYEuf7vCicw3syjS1OxdDMTz96sZIXl3Jx3vWJLLKFw==", + "dev": true, + "requires": { + "@typescript-eslint/eslint-plugin": "7.13.0", + "@typescript-eslint/parser": "7.13.0", + "@typescript-eslint/utils": "7.13.0" + } + }, "typescript-language-server": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/typescript-language-server/-/typescript-language-server-4.3.3.tgz", @@ -25137,6 +25997,11 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", "integrity": "sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg==" }, + "uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==" + }, "uid-safe": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", @@ -25242,6 +26107,15 @@ "set-value": "^2.0.1" } }, + "unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "requires": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + } + }, "unist-util-is": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", @@ -25417,11 +26291,24 @@ "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==" }, + "use-composed-ref": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.3.0.tgz", + "integrity": "sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ==" + }, "use-isomorphic-layout-effect": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==" }, + "use-latest": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.2.1.tgz", + "integrity": "sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==", + "requires": { + "use-isomorphic-layout-effect": "^1.1.1" + } + }, "use-sync-external-store": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", @@ -25467,6 +26354,24 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" }, + "uvu": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", + "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", + "requires": { + "dequal": "^2.0.0", + "diff": "^5.0.0", + "kleur": "^4.0.3", + "sade": "^1.7.3" + }, + "dependencies": { + "diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==" + } + } + }, "v8-compile-cache": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", @@ -25484,6 +26389,16 @@ "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==" }, + "validate.io-array": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz", + "integrity": "sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==" + }, + "validate.io-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz", + "integrity": "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==" + }, "validator": { "version": "13.12.0", "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", @@ -25643,6 +26558,11 @@ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==" }, + "web-worker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.3.0.tgz", + "integrity": "sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA==" + }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -26005,6 +26925,11 @@ "has-tostringtag": "^1.0.2" } }, + "wicked-good-xpath": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz", + "integrity": "sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw==" + }, "wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -26194,6 +27119,11 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, + "xmldom-sre": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/xmldom-sre/-/xmldom-sre-0.1.31.tgz", + "integrity": "sha512-f9s+fUkX04BxQf+7mMWAp5zk61pciie+fFLC9hX9UVvCeJQfNHRHXpeo5MPcR0EUf57PYLdt+ZO4f3Ipk2oZUw==" + }, "xmlhttprequest-ssl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index f42c15c14..80e13875c 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -676,6 +676,7 @@ pie title Minerals in my tap water { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "AI Sort", icon:"robot", toolTip:"Have Chat GPT sort your cards for you !", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Pile", icon:"layer-group", toolTip:"View the cards as a pile in the free form view !", btnType: ButtonType.ClickButton, expertMode: false, toolType:"pile", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Chat Popup", icon:"lightbulb", toolTip:"Toggle the chat popup's visibility!", width: 50,btnType: ButtonType.ToggleButton, expertMode: false, toolType:"toggle-chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, { title: "Sort", toolTip: "Manage sort order / lock status", icon: "sort" , btnType: ButtonType.MultiToggleButton, toolType:"alignment", ignoreClick: true, subMenu: [ @@ -684,7 +685,7 @@ pie title Minerals in my tap water ]}, { title: "Filter", icon:"Filter", toolTip:"Filter cards by tags", width: 150, subMenu: this.cardGroupTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - + diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 7ad5cd88c..6c95bf4db 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -550,7 +550,8 @@ export class MainView extends ObservableReactComponent<{}> { fa.faSatellite, fa.faStar, fa.faCloud, - fa.faBolt + fa.faBolt, + fa.faLightbulb ] ); } diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 60befebec..907a5a343 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -613,9 +613,11 @@ export class CollectionCardView extends CollectionSubView() { const isEmpty = this.childDocsWithoutLinks.length === 0; const isDesc = BoolCast(this.Document.cardSort_isDesc) + console.log(this.childDocsWithoutLinks.length + "length") + if (isEmpty) { return ( - + Sorry ! There are no cards in this group ); @@ -676,6 +678,10 @@ export class CollectionCardView extends CollectionSubView() { }; render() { + const isEmpty = this.childDocsWithoutLinks.length === 0; + const transformValue = `scale(${1 / this.fitContentScale})`; + const heightValue = `${100 * this.fitContentScale}%`; + return (
this.onPointerMove(e)} @@ -688,9 +694,9 @@ export class CollectionCardView extends CollectionSubView() {
this.setHoveredNodeIndex(-1)}> {this.renderCards()} @@ -698,4 +704,5 @@ export class CollectionCardView extends CollectionSubView() {
); } + } diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 2ecde0eee..6ea1751a9 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -42,6 +42,7 @@ import { CollectionViewType } from '../../documents/DocumentTypes'; // import { InkTranscription } from '../InkTranscription'; import { Docs } from '../../documents/Documents'; import { CollectionSubView } from '../collections/CollectionSubView'; +import { GPTPopup, GPTPopupMode } from '../pdf/GPTPopup/GPTPopup'; // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function IsNoneSelected() { @@ -145,7 +146,7 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' } // prettier-ignore - const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'heart' | 'star' | 'cloud' | 'bolt' | 'chat' | '1' | '2' | '3' | '4' | 'up' | 'down' | 'pile', + const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'heart' | 'star' | 'cloud' | 'bolt' | 'chat' | '1' | '2' | '3' | '4' | 'up' | 'down' | 'pile' | 'toggle-chat', { waitForRender?: boolean; checkResult: (doc: Doc) => any; @@ -242,6 +243,14 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' doc.cardSort_isDesc = true; }, }], + ['toggle-chat', { + checkResult: (doc: Doc) => GPTPopup.Instance.visible, + setDoc: (doc: Doc, dv: DocumentView) => { + GPTPopup.Instance.setVisible(!GPTPopup.Instance.visible); + GPTPopup.Instance.setMode(GPTPopupMode.SORT); + + }, + }], ['pile', { checkResult: (doc: Doc) => doc._type_collection == CollectionViewType.Freeform, setDoc: (doc: Doc, dv: DocumentView) => { @@ -269,7 +278,8 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' // if (doc.type == DocumentType.COL ) { newCol && dv.ComponentView?.addDocument?.(newCol); - dv.ComponentView?._props.focus(newCol, {willPan: true , willZoomCentered: true, zoomScale: 200} ) + // dv.ComponentView?._props.focus(newCol, {willPan: true , willZoomCentered: true, zoomScale: 200} ) + DocumentView.showDocument(newCol, { willZoomCentered: true }) // } // doc as CollectionFreeFormView diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.scss b/src/client/views/pdf/GPTPopup/GPTPopup.scss index 042b1dea5..291f272ce 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.scss +++ b/src/client/views/pdf/GPTPopup/GPTPopup.scss @@ -7,10 +7,13 @@ $highlightedText: #82e0ff; .summary-box { position: fixed; - bottom: 10px; - right: 10px; + top: 115px; + left: 75px; width: 250px; + height: 200px; min-height: 200px; + min-width: 180px; + border-radius: 16px; padding: 16px; padding-bottom: 0; @@ -21,6 +24,18 @@ $highlightedText: #82e0ff; background-color: #ffffff; box-shadow: 0 2px 5px #7474748d; color: $textgrey; + resize: both; /* Allows resizing */ + overflow: auto; + + .resize-handle { + width: 10px; + height: 10px; + background: #ccc; + position: absolute; + right: 0; + bottom: 0; + cursor: se-resize; + } .summary-heading { display: flex; diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index 5a5e80dc4..71d437c3d 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -354,6 +354,84 @@ export class GPTPopup extends ObservableReactComponent { } }; + cardMenu = () => ( +
+
+ + ) + + cardActual = (opt: string) => { + const isSort = opt === 'sort' + + if (opt === 'sort'){ + return ( + <> +
+ { + if (e.key === 'Enter') { + this.generateSort(); + } + e.stopPropagation(); + }} + type="text" + placeholder= {`How do you want to sort your cards ?` } + id="search-input" + style={{ width: '100%' }} + /> +
+
+
+ + ) + + } + +} + sortBox = () => ( <>
@@ -575,12 +653,22 @@ export class GPTPopup extends ObservableReactComponent { render() { return ( - -
- {this.mode === GPTPopupMode.SUMMARY ? this.summaryBox() : this.mode === GPTPopupMode.DATA ? this.dataAnalysisBox() : this.mode === GPTPopupMode.IMAGE ? this.imageBox() : this.mode === GPTPopupMode.SORT ? this.sortBox() : null} +
+ {this.mode === GPTPopupMode.SUMMARY + ? this.summaryBox() + : this.mode === GPTPopupMode.DATA + ? this.dataAnalysisBox() + : this.mode === GPTPopupMode.IMAGE + ? this.imageBox() + : this.mode === GPTPopupMode.SORT + ? this.sortBox() + : null} +
- - ); } + } -- cgit v1.2.3-70-g09d2 From abacdb311ee658b74f009106f4e7751fc216af4b Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Thu, 18 Jul 2024 11:24:12 -0400 Subject: boutta get silly --- src/client/util/CurrentUserUtils.ts | 27 +- src/client/views/DocumentButtonBar.scss | 4 + src/client/views/DocumentButtonBar.tsx | 42 ++++ src/client/views/FilterPanel.tsx | 2 +- src/client/views/MainView.tsx | 2 +- src/client/views/PropertiesView.tsx | 2 +- .../views/collections/CollectionCardDeckView.tsx | 2 +- src/client/views/global/globalScripts.ts | 201 ++++++++------- src/client/views/pdf/GPTPopup/GPTPopup.scss | 23 +- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 277 ++++++++++++--------- 10 files changed, 356 insertions(+), 226 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 80e13875c..380d16686 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -676,7 +676,7 @@ pie title Minerals in my tap water { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "AI Sort", icon:"robot", toolTip:"Have Chat GPT sort your cards for you !", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Pile", icon:"layer-group", toolTip:"View the cards as a pile in the free form view !", btnType: ButtonType.ClickButton, expertMode: false, toolType:"pile", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Chat Popup", icon:"lightbulb", toolTip:"Toggle the chat popup's visibility!", width: 50,btnType: ButtonType.ToggleButton, expertMode: false, toolType:"toggle-chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, + { title: "Chat Popup", icon:"lightbulb", toolTip:"Toggle the chat popup's visibility!", width: 45 ,btnType: ButtonType.ToggleButton, expertMode: false, toolType:"toggle-chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, { title: "Sort", toolTip: "Manage sort order / lock status", icon: "sort" , btnType: ButtonType.MultiToggleButton, toolType:"alignment", ignoreClick: true, subMenu: [ @@ -684,7 +684,8 @@ pie title Minerals in my tap water { title: "Descending", toolTip: "Sort the cards in descending order",btnType: ButtonType.ToggleButton, icon: "sort-down",toolType:"down",ignoreClick: true, scripts: {onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, ]}, - { title: "Filter", icon:"Filter", toolTip:"Filter cards by tags", width: 150, subMenu: this.cardGroupTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + // { title: "Filter", icon:"Filter", toolTip:"Filter cards by tags", width: 150, subMenu: this.cardGroupTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + @@ -711,12 +712,13 @@ pie title Minerals in my tap water // { title: "3rd", icon:"3rd", toolTip:"Filter ideas", width: 80, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // ] // } - static cardGroupTools(): Button[] { + static tagGroupTools(): Button[] { return [ - { title: "Star", icon: "star", toolTip:"Click to toggle the star group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Heart", icon: "heart", toolTip:"Click to toggle the heart group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"heart", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Bolt", icon: "bolt", toolTip:"Click to toggle the bolt group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"bolt", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Cloud", icon: "cloud", toolTip:"Click to toggle the cloud group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"cloud", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Star", icon: "star", toolTip:"Click to toggle the star group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, + { title: "Heart", icon: "heart", toolTip:"Click to toggle the heart group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"heart", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, + { title: "Bolt", icon: "bolt", toolTip:"Click to toggle the bolt group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"bolt", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, + { title: "Cloud", icon: "cloud", toolTip:"Click to toggle the cloud group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"cloud", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, + { title: "Options", icon: "gear", toolTip:"Click to customize your filter panel", btnType: ButtonType.ClickButton, expertMode: false, toolType:"opts", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, // { title: "Group 1", icon, toolTip:"Click to toggle group 1's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"1", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, @@ -847,7 +849,16 @@ pie title Minerals in my tap water // { title: "Visibility", icon:"Visibility", toolTip:"Filter stars", width: 80, subMenu: this.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("star", true)`, width: 100, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // // { title: "Custom", icon:"cloud", toolTip:"Add Idea labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"idea", funcs: {hidden:`showFreeform ("idea", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // { title: "Visibility", icon:"Visibility", toolTip:"Filter ideas", width: 80, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`,width: 100, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - + { title: "Filter", icon:"=", toolTip:"Filter cards by tags", btnType: ButtonType.MultiToggleButton, width: 150, ignoreClick: true,toolType:DocumentType.COL, + subMenu: this.tagGroupTools(), funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, + // [ + // { title: "Star", icon: "star", toolTip:"Click to toggle the star group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "Heart", icon: "heart", toolTip:"Click to toggle the heart group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"heart", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "Bolt", icon: "bolt", toolTip:"Click to toggle the bolt group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"bolt", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "Cloud", icon: "cloud", toolTip:"Click to toggle the cloud group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"cloud", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + + // ] + }, { title: "Card", icon: "Card", toolTip: "Card View Tools", subMenu: CurrentUserUtils.cardTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available // { title: "Create", icon: "Create", toolTip: "Assign card labels", subMenu: CurrentUserUtils.labelTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available { title: "Web", icon: "Web", toolTip: "Web functions", subMenu: CurrentUserUtils.webTools(), expertMode: false, toolType:DocumentType.WEB, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when Web is selected diff --git a/src/client/views/DocumentButtonBar.scss b/src/client/views/DocumentButtonBar.scss index 11614d627..374d6ecd3 100644 --- a/src/client/views/DocumentButtonBar.scss +++ b/src/client/views/DocumentButtonBar.scss @@ -153,6 +153,10 @@ $linkGap: 3px; &:hover { background-color: $black; + + .documentButtonBar-pinTypes { + display: flex; + } } } diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index a75c7098c..3d6436cb5 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -286,6 +286,42 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => ( @computed get keywordButton() { const targetDoc = this.view0?.Document; + + const metaBtn = (name: string, icon: IconProp) => { + const tooltip = `Show ${name}`; + return ( + {tooltip}
}> +
+ { + // this.subPin = + // (pinLayoutView ? 'Layout' : '') + + // (pinLayoutView && pinContentView ? ' &' : '') + + // (pinContentView ? ' Content View' : '') + + // (pinLayoutView && pinContentView ? '(shift+alt)' : pinLayoutView ? '(shift)' : pinContentView ? '(alt)' : ''); + // })} + // onPointerLeave={action(() => { + // this.subPin = ''; + // })} + onClick={e => { + name === 'keywords' ? targetDoc && (targetDoc[DocData].showLabels = !targetDoc[DocData].showLabels) : 'hi' + + + }} + /> +
+ + ); + }; + + + + return !targetDoc ? null : ( Open keyword menu
}>
( onClick={() => { targetDoc[DocData].showLabels = !targetDoc[DocData].showLabels; }}> + +
+ {/* {pinBtn(true, false, 'window-maximize')} + {pinBtn(false, true, 'address-card')} + {pinBtn(true, true, 'id-card')} */} +
diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index c97edd7f0..5db627d23 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -222,7 +222,7 @@ export class FilterPanel extends ObservableReactComponent {
- +
{/* THE FOLLOWING CODE SHOULD BE DEVELOPER FOR BOOLEAN EXPRESSION (AND / OR) */} {/*
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 0d42f4099..f552540b8 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -90,7 +90,7 @@ export class MainView extends ObservableReactComponent<{}> { @observable private _windowWidth: number = 0; @observable private _windowHeight: number = 0; - @observable private _dashUIWidth: number = 0; // width of entire main dashboard region including left menu buttons and properties panel (but not including the dashboard selector button row) + @observable _dashUIWidth: number = 0; // width of entire main dashboard region including left menu buttons and properties panel (but not including the dashboard selector button row) @observable private _dashUIHeight: number = 0; // height of entire main dashboard region including top menu buttons @observable private _panelContent: string = 'none'; @observable private _sidebarContent: any = Doc.MyLeftSidebarPanel; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 024db82a4..58bb67120 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -58,7 +58,7 @@ export class PropertiesView extends ObservableReactComponent { GPTPopup.Instance.setVisible(true); - GPTPopup.Instance.setMode(GPTPopupMode.SORT); + GPTPopup.Instance.setMode(GPTPopupMode.CARD); const sortDesc = await this.childPairStringList(); // Await the promise to get the string result GPTPopup.Instance.setCardsDoneLoading(true); // Set dataDoneLoading to true after data is loaded GPTPopup.Instance.setSortDesc(sortDesc.join()); diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 616633bc1..a48e3f9d9 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -1,10 +1,9 @@ import { Colors } from 'browndash-components'; import { action, runInAction } from 'mobx'; import { aggregateBounds } from '../../../Utils'; -import { Doc, DocListCast, NumListCast, Opt } from '../../../fields/Doc'; +import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { InkTool } from '../../../fields/InkField'; -import { List } from '../../../fields/List'; import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types'; import { WebField } from '../../../fields/URLField'; import { Gestures } from '../../../pen-gestures/GestureTypes'; @@ -42,7 +41,9 @@ import { CollectionViewType } from '../../documents/DocumentTypes'; import { Docs } from '../../documents/Documents'; import { CollectionSubView } from '../collections/CollectionSubView'; import { GPTPopup, GPTPopupMode } from '../pdf/GPTPopup/GPTPopup'; - +import { PropertiesView } from '../PropertiesView'; +import { MainView } from '../MainView'; +import { SnappingManager } from '../../util/SnappingManager'; // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function IsNoneSelected() { return DocumentView.Selected().length <= 0; @@ -145,7 +146,7 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' } // prettier-ignore - const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'heart' | 'star' | 'cloud' | 'bolt' | 'chat' | '1' | '2' | '3' | '4' | 'up' | 'down' | 'pile' | 'toggle-chat', + const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'chat' | 'up' | 'down' | 'pile' | 'toggle-chat', { waitForRender?: boolean; checkResult: (doc: Doc) => any; @@ -192,34 +193,34 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "color", setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort === "color" ? doc.cardSort = '' : doc.cardSort = 'color', }], - ['heart', { - checkResult: (doc: Doc) => isAttrFiltered('heart'), - setDoc: (doc: Doc, dv: DocumentView) => { - isAttrFiltered('heart') ? Doc.setDocFilter(doc, 'heart', true, 'remove') : Doc.setDocFilter(doc, 'heart', true, 'match'); - - } - }], - ['star', { - checkResult: (doc: Doc) => isAttrFiltered('star'), - - setDoc: (doc: Doc, dv: DocumentView) => { - isAttrFiltered('star') ? Doc.setDocFilter(doc, 'star', true, 'remove') : Doc.setDocFilter(doc, 'star', true, 'match'); - } - }], - ['bolt', { - checkResult: (doc: Doc) => isAttrFiltered('bolt'), - setDoc: (doc: Doc, dv: DocumentView) => { - isAttrFiltered('bolt') ? Doc.setDocFilter(doc, 'bolt', true, 'remove') : Doc.setDocFilter(doc, 'bolt', true, 'match'); - - } - }], - ['cloud', { - checkResult: (doc: Doc) => isAttrFiltered('cloud'), - setDoc: (doc: Doc, dv: DocumentView) => { - isAttrFiltered('cloud') ? Doc.setDocFilter(doc, 'cloud', true, 'remove') : Doc.setDocFilter(doc, 'cloud', true, 'match'); - - } - }], + // ['heart', { + // checkResult: (doc: Doc) => isAttrFiltered('heart'), + // setDoc: (doc: Doc, dv: DocumentView) => { + // isAttrFiltered('heart') ? Doc.setDocFilter(doc, 'heart', true, 'remove') : Doc.setDocFilter(doc, 'heart', true, 'match'); + + // } + // }], + // ['star', { + // checkResult: (doc: Doc) => isAttrFiltered('star'), + + // setDoc: (doc: Doc, dv: DocumentView) => { + // isAttrFiltered('star') ? Doc.setDocFilter(doc, 'star', true, 'remove') : Doc.setDocFilter(doc, 'star', true, 'match'); + // } + // }], + // ['bolt', { + // checkResult: (doc: Doc) => isAttrFiltered('bolt'), + // setDoc: (doc: Doc, dv: DocumentView) => { + // isAttrFiltered('bolt') ? Doc.setDocFilter(doc, 'bolt', true, 'remove') : Doc.setDocFilter(doc, 'bolt', true, 'match'); + + // } + // }], + // ['cloud', { + // checkResult: (doc: Doc) => isAttrFiltered('cloud'), + // setDoc: (doc: Doc, dv: DocumentView) => { + // isAttrFiltered('cloud') ? Doc.setDocFilter(doc, 'cloud', true, 'remove') : Doc.setDocFilter(doc, 'cloud', true, 'match'); + + // } + // }], ['chat', { checkResult: (doc: Doc) => { @@ -275,20 +276,9 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' } } - // if (doc.type == DocumentType.COL ) { newCol && dv.ComponentView?.addDocument?.(newCol); - // dv.ComponentView?._props.focus(newCol, {willPan: true , willZoomCentered: true, zoomScale: 200} ) DocumentView.showDocument(newCol, { willZoomCentered: true }) - // } - // doc as CollectionFreeFormView - // doc as typeof CollectionSubView - - // doc._props - - // CollectionFreeFormView.addDocumemnt - - // doc?.addDocument; //this._props.addDocument(newCol) }, }], ]); @@ -306,11 +296,40 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' return undefined; }); -ScriptingGlobals.add(function cardHasLabel(label: string) { + +ScriptingGlobals.add(function handleTags(value?: any, checkResult?: boolean) { const selected = DocumentView.SelectedDocs().lastElement(); - const labelNum = Number(label) - 1; - return labelNum < 4 || (selected && DocListCast(selected[Doc.LayoutFieldKey(selected)]).some(doc => doc[StrCast(selected.cardSort_customField)] == labelNum)); -}, ''); + + function isAttrFiltered(attr: string) { + return StrListCast(selected._childFilters).some(filter => filter.includes(attr)); + } + + if (checkResult) { + return value=== 'opts' ? PropertiesView.Instance.openFilters : isAttrFiltered(value) + } + + if (value != 'opts'){ + isAttrFiltered(value) ? Doc.setDocFilter(selected, value, true, 'remove') : Doc.setDocFilter(selected, value, true, 'match'); + } + else { + SnappingManager.PropertiesWidth < 5 && SnappingManager.SetPropertiesWidth(0); + SnappingManager.SetPropertiesWidth(MainView.Instance.propertiesWidth() < 15 ? Math.min(MainView.Instance._dashUIWidth - 50, 250) : 0); + + PropertiesView.Instance.CloseAll() + PropertiesView.Instance.openFilters = true + } + + + return undefined; + }, ''); + + + +// ScriptingGlobals.add(function cardHasLabel(label: string) { +// const selected = DocumentView.SelectedDocs().lastElement(); +// const labelNum = Number(label) - 1; +// return labelNum < 4 || (selected && DocListCast(selected[Doc.LayoutFieldKey(selected)]).some(doc => doc[StrCast(selected.cardSort_customField)] == labelNum)); +// }, ''); // ScriptingGlobals.add(function setCardSort(attr: "Time" | "Type"| "Color"| "ChatGPT"| "Custom 1"| "Custom 2"| "Custom 3", value?: any, checkResult?: boolean) { // // const editorView = RichTextMenu.Instance?.TextView?.EditorView; @@ -400,55 +419,53 @@ ScriptingGlobals.add(function cardHasLabel(label: string) { // // return undefined; // }); -ScriptingGlobals.add(function setCardSort(value?: any, checkResult?: boolean) { - // const editorView = RichTextMenu.Instance?.TextView?.EditorView; - const selected = DocumentView.SelectedDocs().lastElement(); - - if (checkResult) { - // console.log(attr + "attricute") - // console.log(map.get(attr)?.checkResult(selected) + "check result") - console.log(StrCast(selected?.cardSort) + 'check'); - const hi = StrCast(selected?.cardSort); - return StrCast(selected?.cardSortForDropDown) ?? 'Time'; - } - - function docFields(doc: Doc): void { - switch (value) { - case 'Custom 1': - doc.cardSort_customField = 'like'; - break; - case 'Custom 2': - doc.cardSort_customField = 'star'; - break; - case 'Custom 3': - doc.cardSort_customField = 'idea'; - break; - case 'Chat GPT': - doc.cardSort = 'custom'; - doc.cardSort_customField = 'chat'; - break; - default: - break; - } - - doc.cardSort_visibleSortGroups = new List(); - } +// ScriptingGlobals.add(function setCardSort(value?: any, checkResult?: boolean) { +// // const editorView = RichTextMenu.Instance?.TextView?.EditorView; +// const selected = DocumentView.SelectedDocs().lastElement(); +// if (checkResult) { +// // console.log(attr + "attricute") +// // console.log(map.get(attr)?.checkResult(selected) + "check result") +// console.log(StrCast(selected?.cardSort) + 'check'); +// const hi = StrCast(selected?.cardSort); +// return StrCast(selected?.cardSortForDropDown) ?? 'Time'; +// } +// function docFields(doc: Doc): void { +// switch (value) { +// case 'Custom 1': +// doc.cardSort_customField = 'like'; +// break; +// case 'Custom 2': +// doc.cardSort_customField = 'star'; +// break; +// case 'Custom 3': +// doc.cardSort_customField = 'idea'; +// break; +// case 'Chat GPT': +// doc.cardSort = 'custom'; +// doc.cardSort_customField = 'chat'; +// break; +// default: +// break; +// } + +// doc.cardSort_visibleSortGroups = new List(); +// } - // const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; - DocumentView.Selected().map(dv => { - dv.Document.cardSortForDropDown = value; +// // const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; +// DocumentView.Selected().map(dv => { +// dv.Document.cardSortForDropDown = value; - if (value != 'Chat GPT') { - dv.Document.cardSort = value.trim().split(/\s+/)[0].toLowerCase(); - } - docFields(dv.Document); - }); +// if (value != 'Chat GPT') { +// dv.Document.cardSort = value.trim().split(/\s+/)[0].toLowerCase(); +// } +// docFields(dv.Document); +// }); - return undefined; +// return undefined; - // map.get(attr)?.setDoc?.(); - // return undefined; -}); +// // map.get(attr)?.setDoc?.(); +// // return undefined; +// }); // ScriptingGlobals.add(function setCardSortAttr(attr: 'time' | 'docType' | 'color', value: any, checkResult?: boolean) { // // const editorView = RichTextMenu.Instance?.TextView?.EditorView; diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.scss b/src/client/views/pdf/GPTPopup/GPTPopup.scss index 291f272ce..57973ef34 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.scss +++ b/src/client/views/pdf/GPTPopup/GPTPopup.scss @@ -71,10 +71,12 @@ $highlightedText: #82e0ff; } .btns-wrapper-gpt { - height: 50px; + height: 100%; display: flex; justify-content: center; align-items: center; + flex-direction: column; + transform: translateY(30px); @@ -93,17 +95,20 @@ $highlightedText: #82e0ff; } - } - button { - font-size: 9px; - padding: 10px; - color: #ffffff; - width: 100%; - background-color: $button; - border-radius: 5px; + } + // button { + // font-size: 9px; + // padding: 10px; + // color: #ffffff; + // width: 100%; + // background-color: $button; + // border-radius: 5px; + + // } + .text-btn { &:hover { background-color: $button; diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index 71d437c3d..bbd5ea630 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -4,7 +4,7 @@ import { Button, IconButton, Type } from 'browndash-components'; import { action, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { CgClose } from 'react-icons/cg'; +import { CgClose, CgPathBack, CgArrowLeftO, CgCornerUpLeft } from 'react-icons/cg'; import ReactLoading from 'react-loading'; import { TypeAnimation } from 'react-type-animation'; import { ClientUtils } from '../../../../ClientUtils'; @@ -33,6 +33,10 @@ export enum GPTPopupMode { } + + + + interface GPTPopupProps {} @observer @@ -166,6 +170,15 @@ export class GPTPopup extends ObservableReactComponent { this.chatSortPrompt = e.target.value; }); + + @observable quizAnswer: string = "" + + quizAnswerChanged = action((e: React.ChangeEvent) => { + this.quizAnswer = e.target.value; + }); + + + @observable private regenerateCallback: (() => Promise) | null = null; @action public setRegenerateCallback(callback: () => Promise) { @@ -359,81 +372,133 @@ export class GPTPopup extends ObservableReactComponent {
- ) + + cardActual = (opt: GPTPopupMode) => { + if (opt === GPTPopupMode.SORT) { + return ( + !this.sortDone ? ( + <> +
+ { + if (e.key === 'Enter') { + this.generateSort(); + } + e.stopPropagation(); + }} + type="text" + placeholder="How do you want to sort your cards?" + id="search-input" + style={{ width: '100%' }} + /> + {/*
+
*/} +
+ + ) : ( +
+
+

{this.text === 'Something went wrong :(' ? 'Something went wrong :(' : `${this.sortRespText}`}

+ this.setSortDone(false)} + icon={} + color={StrCast(Doc.UserDoc().userVariantColor)} + /> +
+
+ ) + ); + } else if (opt === GPTPopupMode.QUIZ) { return ( <> -
- { - if (e.key === 'Enter') { - this.generateSort(); - } - e.stopPropagation(); - }} - type="text" - placeholder= {`How do you want to sort your cards ?` } - id="search-input" - style={{ width: '100%' }} - /> -
-
-
- - ) - +
+ { + if (e.key === 'Enter') { + this.generateSort(); + } + e.stopPropagation(); + }} + type="text" + placeholder="What is the selected card?" + id="search-input" + style={{ width: '100%' }} + /> +
+
+
+ + ); } - -} - + }; + sortBox = () => ( - <>
{this.heading('SORTING')} <> @@ -445,62 +510,13 @@ export class GPTPopup extends ObservableReactComponent {
) : ( - !this.sortDone && ( - <> -
- { - if (e.key === 'Enter') { - this.generateSort(); - } - e.stopPropagation(); - }} - type="text" - placeholder="How do you want to sort your cards ?" - id="search-input" - style={{ width: '100%' }} - /> -
-
-
- - ) - )} - - {this.sortDone && ( -
-
-

{this.text === 'Something went wrong :(' ? 'Something went wrong :(' : `${this.sortRespText}`}

- this.setSortDone(false)} - icon={} - color={StrCast(Doc.UserDoc().userVariantColor)} - /> -
-
+ (this.mode === GPTPopupMode.CARD ? this.cardMenu() : this.cardActual(this.mode)) // Call the functions to render JSX )}
- -); + ); + + imageBox = () => (
@@ -647,25 +663,60 @@ export class GPTPopup extends ObservableReactComponent { heading = (headingText: string) => (
- {this.loading ? : } onClick={() => this.setVisible(false)} />} + {this.loading ? ( + + ) : ( + <> + {(this.mode === GPTPopupMode.SORT || this.mode === GPTPopupMode.QUIZ) && ( + } + onClick={() => this.mode = GPTPopupMode.CARD} + style = {{right: '-55px'}} + /> + )} + } + onClick={() => this.setVisible(false)} + /> + + + )}
); + render() { + let content; + + switch (this.mode) { + case GPTPopupMode.SUMMARY: + content = this.summaryBox(); + break; + case GPTPopupMode.DATA: + content = this.dataAnalysisBox(); + break; + case GPTPopupMode.IMAGE: + content = this.imageBox(); + break; + case GPTPopupMode.SORT: + case GPTPopupMode.CARD: + case GPTPopupMode.QUIZ: + content = this.sortBox(); + break; + default: + content = null; + } + return (
- {this.mode === GPTPopupMode.SUMMARY - ? this.summaryBox() - : this.mode === GPTPopupMode.DATA - ? this.dataAnalysisBox() - : this.mode === GPTPopupMode.IMAGE - ? this.imageBox() - : this.mode === GPTPopupMode.SORT - ? this.sortBox() - : null} + {content}
); -- cgit v1.2.3-70-g09d2 From de253f5acca34f20017895a2d8469b5ebd6032bf Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Tue, 30 Jul 2024 14:31:00 -0400 Subject: fight w css --- src/client/apis/gpt/GPT.ts | 9 ++ src/client/documents/Documents.ts | 2 + src/client/util/CurrentUserUtils.ts | 4 +- src/client/views/DocumentButtonBar.tsx | 6 +- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/FilterPanel.tsx | 95 ++++++++++++ src/client/views/StyleProvider.tsx | 7 + .../views/collections/CollectionCardDeckView.scss | 50 +++--- .../views/collections/CollectionCardDeckView.tsx | 1 + src/client/views/nodes/IconTagBox.scss | 30 ++++ src/client/views/nodes/IconTagBox.tsx | 168 +++++++++++++++++++++ src/client/views/pdf/GPTPopup/GPTPopup.scss | 3 +- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 164 ++++++++++++++------ 13 files changed, 460 insertions(+), 81 deletions(-) create mode 100644 src/client/views/nodes/IconTagBox.scss create mode 100644 src/client/views/nodes/IconTagBox.tsx (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 40af70d99..d95e564c7 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -12,6 +12,7 @@ enum GPTCallType { DESCRIBE = 'describe', MERMAID = 'mermaid', DATA = 'data', + RUBRIC = 'rubric' } type GPTCallOpts = { @@ -26,6 +27,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { summary: { model: 'gpt-4-turbo', maxTokens: 256, temp: 0.5, prompt: 'Summarize the text given in simpler terms.' }, edit: { model: 'gpt-4-turbo', maxTokens: 256, temp: 0.5, prompt: 'Reword the text.' }, flashcard: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'Make flashcards out of this text with each question and answer labeled. Do not label each flashcard and do not include asterisks: ' }, + completion: { model: 'gpt-4-turbo', maxTokens: 256, temp: 0.5, prompt: "You are a helpful assistant. Answer the user's prompt." }, mermaid: { model: 'gpt-4-turbo', @@ -54,6 +56,13 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { temp: 0, prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If there are no differences, say correct', }, + + rubric: { + model: 'gpt-4-turbo', + maxTokens: 1024, + temp: 0, + prompt: "Provide a definition for the vollowing term. It will be used as a rubric to evaluate the user's understanding of the topic", + }, }; let lastCall = ''; diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e8e9b4fb6..612629f89 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -493,6 +493,8 @@ export class DocumentOptions { // cardSort_visibleSortGroups?: List; // which sorting values are being filtered (shown) cardSort_isDesc?: BOOLt = new BoolInfo('whether the cards are sorted ascending or descending'); // test?: STRt = new StrInfo('testing for filtering') + keywords?: MAPt = new MapInfo('keywords', true); + } export const DocOptions = new DocumentOptions(); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 380d16686..67f8dafc4 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -39,7 +39,7 @@ import { ColorScheme } from "./SettingsManager"; import { SnappingManager } from "./SnappingManager"; import { UndoManager } from "./UndoManager"; -interface Button { +export interface Button { // DocumentOptions fields a button can set title?: string; toolTip?: string; @@ -714,7 +714,7 @@ pie title Minerals in my tap water // } static tagGroupTools(): Button[] { return [ - { title: "Star", icon: "star", toolTip:"Click to toggle the star group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, + { title: "Star", icon: StrCast(Doc.UserDoc().myFilterHotKeyIcons) ?? "Star", toolTip:"Click to toggle the star group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, { title: "Heart", icon: "heart", toolTip:"Click to toggle the heart group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"heart", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, { title: "Bolt", icon: "bolt", toolTip:"Click to toggle the bolt group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"bolt", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, { title: "Cloud", icon: "cloud", toolTip:"Click to toggle the cloud group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"cloud", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 3d6436cb5..c8df66535 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -309,7 +309,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => ( // this.subPin = ''; // })} onClick={e => { - name === 'keywords' ? targetDoc && (targetDoc[DocData].showLabels = !targetDoc[DocData].showLabels) : 'hi' + name === 'tags' ? targetDoc && (targetDoc[DocData].showIconTags = !targetDoc[DocData].showIconTags) : 'hi' }} @@ -332,7 +332,9 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => ( }}>
- {/* {pinBtn(true, false, 'window-maximize')} + { + metaBtn('tags', "tag") + /* {pinBtn(true, false, 'window-maximize')} {pinBtn(false, true, 'address-card')} {pinBtn(true, true, 'id-card')} */}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index dc40562e8..b5d819b97 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -832,7 +832,7 @@ export class DocumentDecorations extends ObservableReactComponent DocumentView.Selected()} /> diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 5db627d23..332a89a96 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -19,6 +19,16 @@ import './FilterPanel.scss'; import { DocumentView } from './nodes/DocumentView'; import { Handle, Tick, TooltipRail, Track } from './nodes/SliderBox-components'; import { ObservableReactComponent } from './ObservableReactComponent'; +import { Button } from '../util/CurrentUserUtils'; +import { ButtonType } from './nodes/FontIconBox/FontIconBox'; +import { DocCast } from '../../fields/Types'; +// import { Docs } from '../../documents/Documents'; +import { Docs } from '../documents/Documents'; +import { CurrentUserUtils } from '../util/CurrentUserUtils'; +import { DocumentOptions } from '../documents/Documents'; +import { DocUtils } from '../documents/DocUtils'; +import { dropActionType } from '../util/DropActionTypes'; + interface filterProps { Document: Doc; @@ -217,6 +227,83 @@ export class FilterPanel extends ObservableReactComponent { return nonNumbers / facetValues.length > 0.1 ? facetValues.sort() : facetValues.sort((n1: string, n2: string) => Number(n1) - Number(n2)); }; + addHotkey() { + + const buttons = DocCast(Doc.UserDoc().myContextMenuBtns); + const filter = buttons['Filter'] + const filter2 = DocCast(filter) + const but2 = Doc.UserDoc().myContextMenuBtns + + // const newCol = Docs.Create.CarouselDocument(DocListCast(doc[Doc.LayoutFieldKey(doc)]), { + // _width: 250, + // _height: 200, + // _layout_fitWidth: false, + // _layout_autoHeight: true, + // }); + + // CurrentUserUtils.setupContextMenuButtons() + + // const hm = Docs.Create.FontIconDocument() + + // DocumentView.getDocumentView(filter2)?.ComponentView?.addDocument?.(hm) + + // console.log(DocumentView.getDocumentView(filter2) + "hiiiii") + + // DocumentView.getDocumentView(DocCast(buttons['Card']))?.ComponentView?.addDocument?.(hm) + + const hi = CurrentUserUtils.contextMenuTools() + + const newKey: Button = { title: "Cloud", icon: "cloud", toolTip:"Click to toggle the cloud group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"cloud", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}} + + + const heyy = [...hi, newKey] + + Doc.UserDoc().myFilterHotKeyIcons = "palette" + Doc.UserDoc().myFilterHotKeyTitles = "hi" + + CurrentUserUtils.setupContextMenuButtons(Doc.UserDoc()); + + + + Doc.UserDoc().hi = Docs.Create.FontIconDocument( + { title: '', + icon: 'map-pin', + + backgroundColor: '#ACCEF7', + layout_hideAllLinks: true, + _width: 15, + _height: 15, + _xPadding: 0, + } + ) + + + // buttons['Filter'] + + + + + const reqdCtxtOpts:DocumentOptions = { title: "hi", undoIgnoreFields:new List(['width', "linearView_IsOpen"]), flexGap: 0, childDragAction: dropActionType.embed, childDontRegisterViews: true, linearView_IsOpen: true, ignoreClick: true, linearView_Expandable: false, _height: 35 }; + const ctxtMenuBtns = CurrentUserUtils.setupContextMenuBtn(newKey, buttons); + // DocUtils.AssignOpts(buttons, reqdCtxtOpts, ctxtMenuBtns); + + + DocUtils.AssignOpts(DocCast(buttons['Filter']), reqdCtxtOpts, [ctxtMenuBtns]); + + + // newCol && dv.ComponentView?.addDocument?.(newCol); + + // console.log(but2 + "omgg") + + + + // doc.cardSort_activeIcons = new List(list.includes(icon) ? list.filter(d => d !== icon) : [...list, icon]); + + + + // Doc.UserDoc().myContextMenuBtns = new List([...buttons, newKey as Doc]) + } + render() { return (
@@ -283,6 +370,14 @@ export class FilterPanel extends ObservableReactComponent { ) )}
+
+
+
+ +
+
+ +
); } diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 40d0358d2..55e6217ff 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -30,6 +30,7 @@ import { DocumentView, DocumentViewProps } from './nodes/DocumentView'; import { FieldViewProps } from './nodes/FieldView'; import { StyleProp } from './StyleProp'; import './StyleProvider.scss'; +import { IconTagBox } from './nodes/IconTagBox'; function toggleLockedPosition(doc: Doc) { UndoManager.RunInBatch(() => Doc.toggleLockedPosition(doc), 'toggleBackground'); @@ -377,6 +378,11 @@ export function DefaultStyleProvider(doc: Opt, props: Opt) } } + + const iconTags = () => { + if (doc && doc![DocData].showIconTags) + {return ()} + } return ( <> {paint()} @@ -384,6 +390,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt ); } diff --git a/src/client/views/collections/CollectionCardDeckView.scss b/src/client/views/collections/CollectionCardDeckView.scss index eb1b456f5..5869f89e1 100644 --- a/src/client/views/collections/CollectionCardDeckView.scss +++ b/src/client/views/collections/CollectionCardDeckView.scss @@ -22,32 +22,32 @@ transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955); } -.card-button-container { - display: flex; - padding: 3px; - // width: 300px; - // height:100px; - pointer-events: none; /* This ensures the container does not capture hover events */ - - background-color: rgb(218, 218, 218); /* Background color of the container */ - border-radius: 50px; /* Rounds the corners of the container */ - transform: translateY(25px); - // box-shadow: 0 4px 8px rgba(0,0,0,0.1); /* Optional: Adds shadow for depth */ - align-items: center; /* Centers buttons vertically */ - justify-content: start; /* Centers buttons horizontally */ - - button { - pointer-events: auto; /* Re-enable pointer events for the buttons */ +// .card-button-container { +// display: flex; +// padding: 3px; +// // width: 300px; +// // height:100px; +// pointer-events: none; /* This ensures the container does not capture hover events */ + +// background-color: rgb(218, 218, 218); /* Background color of the container */ +// border-radius: 50px; /* Rounds the corners of the container */ +// transform: translateY(25px); +// // box-shadow: 0 4px 8px rgba(0,0,0,0.1); /* Optional: Adds shadow for depth */ +// align-items: center; /* Centers buttons vertically */ +// justify-content: start; /* Centers buttons horizontally */ + +// button { +// pointer-events: auto; /* Re-enable pointer events for the buttons */ - width: 70px; - height: 70px; - border-radius: 50%; - background-color: $dark-gray; - // border-color: $medium-blue; - margin: 5px; // transform: translateY(-50px); - background-color: transparent; - } -} +// width: 70px; +// height: 70px; +// border-radius: 50%; +// background-color: $dark-gray; +// // border-color: $medium-blue; +// margin: 5px; // transform: translateY(-50px); +// background-color: transparent; +// } +// } .no-card-span{ position: relative; diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 410ddc355..736cc2354 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -446,6 +446,7 @@ export class CollectionCardView extends CollectionSubView() { }; const docTextPromises = this.childDocsWithoutLinks.map(async doc => { const docText = (await docToText(doc)) ?? ''; + doc['gptInputText'] = docText this._textToDoc.set(docText.replace(/\n/g, ' ').trim(), doc); return `======${docText.replace(/\n/g, ' ').trim()}======`; }); diff --git a/src/client/views/nodes/IconTagBox.scss b/src/client/views/nodes/IconTagBox.scss new file mode 100644 index 000000000..8c0f92c90 --- /dev/null +++ b/src/client/views/nodes/IconTagBox.scss @@ -0,0 +1,30 @@ +@import '../global/globalCssVariables.module.scss'; + +.card-button-container { + display: flex; + padding: 3px; + position: absolute; + // width: 300px; + // height:100px; + pointer-events: none; /* This ensures the container does not capture hover events */ + + background-color: rgb(218, 218, 218); /* Background color of the container */ + border-radius: 50px; /* Rounds the corners of the container */ + transform: translateY(25px); + // box-shadow: 0 4px 8px rgba(0,0,0,0.1); /* Optional: Adds shadow for depth */ + align-items: center; /* Centers buttons vertically */ + justify-content: start; /* Centers buttons horizontally */ + + button { + pointer-events: auto; /* Re-enable pointer events for the buttons */ + transform: translateY(-7.5px); + + width: 30px; + height: 30px; + border-radius: 50%; + background-color: $dark-gray; + // border-color: $medium-blue; + margin: 5px; // transform: translateY(-50px); + background-color: transparent; + } +} \ No newline at end of file diff --git a/src/client/views/nodes/IconTagBox.tsx b/src/client/views/nodes/IconTagBox.tsx new file mode 100644 index 000000000..9a2273c3a --- /dev/null +++ b/src/client/views/nodes/IconTagBox.tsx @@ -0,0 +1,168 @@ +import React from "react"; +import { observer } from "mobx-react"; +import { computed } from "mobx"; + +import { ObservableReactComponent } from "../ObservableReactComponent"; +import { NumCast } from "../../../fields/Types"; +import { makeObservable } from "mobx"; +import { Doc } from "../../../fields/Doc"; +import { Reaction } from "mobx"; +import { reaction } from "mobx"; +import { numberRange } from "../../../Utils"; +import { Tooltip } from "@mui/material"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { undoable } from "../../util/UndoManager"; +import { BoolCast } from "../../../fields/Types"; +import { DocCast } from "../../../fields/Types"; +import './IconTagBox.scss'; +import { AclAdmin, AclAugment, AclEdit, DocData } from '../../../fields/DocSymbols'; + + +export interface IconTagProps { + doc: Doc; + + +} + +@observer +export class IconTagBox extends ObservableReactComponent { + private ref: React.RefObject; + private height: number = 0; + + + @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 { + 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): void { + this.height = this.ref.current?.getBoundingClientRect().height ? this.ref.current?.getBoundingClientRect().height : 0; + this._props.doc._keywordHeight = this.height; + } + + /** + * Renders the buttons to customize sorting depending on which group the card belongs to and the amount of total groups + * @param doc + * @param cardSort + * @returns + */ + renderButtons = (doc: Doc): JSX.Element | null => { + // if (cardSort !== cardSortings.Custom) return null; + + const amButtons = 4 + + // const amButtons = Math.max( + // 4, + // this.childDocs?.reduce((set, d) => { + // if (this.cardSort_customField) { + // set.add(NumCast(d[this.cardSort_customField])); + // } + // return set; + // }, new Set()).size ?? 0 + // ); + + // const activeButtonIndex = CollectionCardView.getButtonGroup(this.cardSort_customField, doc); + + const totalWidth = amButtons * 35 + amButtons * 2 * 5 + 6; + + const iconMap: { [key: number]: any } = { + 0: 'star', + 1: 'heart', + 2: 'cloud', + 3: 'bolt' + }; + + return ( +
+ {numberRange(amButtons).map(i => ( + Click to add/remove this card from the {iconMap[i]} group
}> + + + ))} +
+ ); + }; + + /** + * Toggles the buttons between on and off when creating custom sort groupings/changing those created by gpt + * @param childPairIndex + * @param buttonID + * @param doc + */ + toggleButton = undoable((doc: Doc, icon: string) => { + + + + // this.cardSort_customField && (doc[this.cardSort_customField] = buttonID); + + // doc.cardSort_activeIcons = new List() + + + // const list = StrListCast(doc.cardSort_activeIcons); + // doc.cardSort_activeIcons = new List(list.includes(icon) ? list.filter(d => d !== icon) : [...list, icon]); + + BoolCast(doc[icon]) ? doc[icon] = false : doc[icon] = true + + + + // StrListCast(doc.cardSort_activeIcons).push(iconMap[buttonID]) + }, 'toggle card tag'); + + + getButtonIcon = (doc: Doc, icon: any): JSX.Element => { + + // const isActive = StrListCast(doc.cardSort_activeIcons).includes(icon) + const isActive = doc[icon] + + // console.log(StrListCast(doc.cardSort_activeIcons)) + const color = isActive ? '#4476f7' : '#323232'; + + return ; + }; + + render (){ + return ( + <> + {this.renderButtons(this._props.doc)} + + + ) + + } + + + +} + + diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.scss b/src/client/views/pdf/GPTPopup/GPTPopup.scss index 57973ef34..eaa3eaebf 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.scss +++ b/src/client/views/pdf/GPTPopup/GPTPopup.scss @@ -66,8 +66,9 @@ $highlightedText: #82e0ff; .content-wrapper { padding-top: 10px; min-height: 50px; - max-height: 150px; + // max-height: 150px; overflow-y: auto; + height: 100% } .btns-wrapper-gpt { diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index bbd5ea630..a41c33a4d 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -19,7 +19,9 @@ import { AnchorMenu } from '../AnchorMenu'; import './GPTPopup.scss'; import { SettingsManager } from '../../../util/SettingsManager'; import { SnappingManager } from '../../../util/SnappingManager'; - +import { DocumentView } from '../../nodes/DocumentView'; +import { DocCast } from '../../../../fields/Types'; +import { RTFCast } from '../../../../fields/Types'; export enum GPTPopupMode { SUMMARY, @@ -177,6 +179,59 @@ export class GPTPopup extends ObservableReactComponent { this.quizAnswer = e.target.value; }); + generateQuiz = async () => { + this.setLoading(true); + this.setSortDone(false); + + + const selected = DocumentView.SelectedDocs().lastElement(); + + const questionText = 'Question: ' + StrCast(selected['gptInputText']); + + if (StrCast(selected['gptRubric']) === '') { + const rubricText = 'Rubric: ' + await this.generateRubric(StrCast(selected['gptInputText']), selected) + } + + const rubricText = 'Rubric: ' + (StrCast(selected['gptRubric'])) + // const rubricText = 'Rubric: ' + StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_0']).text)?.Text); + const queryText = questionText + ' UserAnswer: ' + this.quizAnswer + '. ' + 'Rubric' + rubricText; + + try { + const res = await gptAPICall(queryText, GPTCallType.QUIZ); + if (!res) { + console.error('GPT call failed'); + return; + } + console.log(res) + this.setQuizResp(res) + + this.setLoading(false); + this.setSortDone(true); + + // this._outputValue = res; + } catch (err) { + console.error('GPT call failed'); + } + + + } + + generateRubric = async (inputText: string, doc:Doc) => { + try { + const res = await gptAPICall(inputText, GPTCallType.RUBRIC); + console.log(res + "rubbbb") + // if (!res) { + // console.error('GPT call failed'); + // return; + // } + doc['gptRubric']= res; + return res + } catch (err) { + console.error('GPT call failed'); + } + + } + @observable private regenerateCallback: (() => Promise) | null = null; @@ -192,6 +247,14 @@ export class GPTPopup extends ObservableReactComponent { public createFilteredDoc: (axes?: any) => boolean = () => false; public addToCollection: ((doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) | undefined; + @observable quizRespText: string = '' + + @action setQuizResp (resp: string) { + this.quizRespText = resp + + } + + /** * Sorts cards in the CollectionCardDeckView */ @@ -403,7 +466,8 @@ export class GPTPopup extends ObservableReactComponent { ) cardActual = (opt: GPTPopupMode) => { - if (opt === GPTPopupMode.SORT) { + const isSort = opt === GPTPopupMode.SORT + // if (opt === GPTPopupMode.SORT) { return ( !this.sortDone ? ( <> @@ -412,24 +476,24 @@ export class GPTPopup extends ObservableReactComponent { className="searchBox-input" defaultValue="" autoComplete="off" - onChange={this.sortPromptChanged} + onChange={isSort ? this.sortPromptChanged : this.quizAnswerChanged} onKeyDown={e => { if (e.key === 'Enter') { - this.generateSort(); + isSort ? this.generateSort() : this.generateQuiz(); } e.stopPropagation(); }} type="text" - placeholder="How do you want to sort your cards?" + placeholder={`${isSort ? 'How do you want to sort your cards?' : 'What is the selected card?'}`} id="search-input" style={{ width: '100%' }} /> {/*
*/}
- - ); - } + // } else if (opt === GPTPopupMode.QUIZ) { + // return ( + // <> + //
+ // { + // if (e.key === 'Enter') { + // this.generateQuiz(); + // } + // e.stopPropagation(); + // }} + // type="text" + // placeholder="What is the selected card?" + // id="search-input" + // style={{ width: '100%' }} + // /> + // {/*
+ //
*/} + //
+ // + // ); + // } }; sortBox = () => (
- {this.heading('SORTING')} + {this.heading(this.mode === GPTPopupMode.SORT ? 'SORTING' : 'QUIZ')} <> {!this.cardsDoneLoading || this.loading ? (
@@ -673,7 +737,7 @@ export class GPTPopup extends ObservableReactComponent { tooltip="back" icon={} onClick={() => this.mode = GPTPopupMode.CARD} - style = {{right: '-55px'}} + style = {{right: '-20%'}} /> )} Date: Tue, 6 Aug 2024 14:48:49 -0400 Subject: locking into hotkey buttons --- src/client/util/CurrentUserUtils.ts | 24 +-- src/client/views/DocumentButtonBar.scss | 5 + src/client/views/DocumentButtonBar.tsx | 43 ++--- src/client/views/DocumentDecorations.tsx | 9 +- src/client/views/FilterPanel.scss | 64 +++++++ src/client/views/FilterPanel.tsx | 285 ++++++++++++++++++++++++++----- src/client/views/MainView.tsx | 3 +- src/client/views/nodes/IconTagBox.tsx | 38 +++-- 8 files changed, 380 insertions(+), 91 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 67f8dafc4..0d8955ced 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -44,6 +44,7 @@ export interface Button { title?: string; toolTip?: string; icon?: string; + isSystem?: boolean; btnType?: ButtonType; numBtnMin?: number; numBtnMax?: number; @@ -713,14 +714,14 @@ pie title Minerals in my tap water // ] // } static tagGroupTools(): Button[] { - return [ - { title: "Star", icon: StrCast(Doc.UserDoc().myFilterHotKeyIcons) ?? "Star", toolTip:"Click to toggle the star group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, - { title: "Heart", icon: "heart", toolTip:"Click to toggle the heart group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"heart", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, - { title: "Bolt", icon: "bolt", toolTip:"Click to toggle the bolt group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"bolt", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, - { title: "Cloud", icon: "cloud", toolTip:"Click to toggle the cloud group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"cloud", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, - { title: "Options", icon: "gear", toolTip:"Click to customize your filter panel", btnType: ButtonType.ClickButton, expertMode: false, toolType:"opts", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, - - + // hack: if there's no dashboard, create default filters. otherwise, just make sure that the Options button is preserved + return (Doc.UserDoc().activeDashboard ? [] : [ + { title: "Star", isSystem: false, icon: "star", toolTip:"Click to toggle the star group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, + { title: "Heart", isSystem: false,icon: "heart", toolTip:"Click to toggle the heart group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"heart", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, + { title: "Bolt", isSystem: false,icon: "bolt", toolTip:"Click to toggle the bolt group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"bolt", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, + { title: "Cloud", isSystem: false,icon: "cloud", toolTip:"Click to toggle the cloud group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"cloud", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, + + // { title: "Group 1", icon, toolTip:"Click to toggle group 1's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"1", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // { title: "Group 2", icon, toolTip:"Click to toggle group 2's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"2", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // { title: "Group 3", icon, toolTip:"Click to toggle group 3's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"3", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, @@ -728,7 +729,9 @@ pie title Minerals in my tap water // { title: "", icon, toolTip:"Click to toggle group 5's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"5", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // { title: "", icon, toolTip:"Click to toggle group 6's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"6", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // { title: "", icon, toolTip:"Click to toggle group 7's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"7", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - ] + ]).concat([ + { title: "Options", isSystem: true,icon: "gear", toolTip:"Click to customize your filter panel", btnType: ButtonType.ClickButton, expertMode: false, toolType:"opts", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}} + ]) } static viewTools(): Button[] { return [ @@ -871,8 +874,9 @@ pie title Minerals in my tap water /// initializes a context menu button for the top bar context menu static setupContextMenuButton(params:Button, btnDoc?:Doc, btnContainer?:Doc) { const reqdOpts:DocumentOptions = { + isSystem: true, ...OmitKeys(params, ["scripts", "funcs", "subMenu"]).omit, - color: Colors.WHITE, isSystem: true, + color: Colors.WHITE, _nativeWidth: params.width ?? 30, _width: params.width ?? 30, _height: 30, _nativeHeight: 30, linearBtnWidth: params.linearBtnWidth, toolType: params.toolType, expertMode: params.expertMode, diff --git a/src/client/views/DocumentButtonBar.scss b/src/client/views/DocumentButtonBar.scss index 374d6ecd3..ede277aae 100644 --- a/src/client/views/DocumentButtonBar.scss +++ b/src/client/views/DocumentButtonBar.scss @@ -29,6 +29,11 @@ $linkGap: 3px; background: black; height: 20px; align-items: center; + + .tags { + width: 40px; + + } } .documentButtonBar-followTypes { width: 20px; diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index c8df66535..c61ebfb4c 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -288,7 +288,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => ( const targetDoc = this.view0?.Document; const metaBtn = (name: string, icon: IconProp) => { - const tooltip = `Show ${name}`; + const tooltip = `Toggle ${name}`; return ( {tooltip}
}>
@@ -298,18 +298,16 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => ( key={icon.toString()} size="sm" icon={icon} - // onPointerEnter={action(() => { - // this.subPin = - // (pinLayoutView ? 'Layout' : '') + - // (pinLayoutView && pinContentView ? ' &' : '') + - // (pinContentView ? ' Content View' : '') + - // (pinLayoutView && pinContentView ? '(shift+alt)' : pinLayoutView ? '(shift)' : pinContentView ? '(alt)' : ''); - // })} - // onPointerLeave={action(() => { - // this.subPin = ''; - // })} onClick={e => { - name === 'tags' ? targetDoc && (targetDoc[DocData].showIconTags = !targetDoc[DocData].showIconTags) : 'hi' + // console.log('wtfff') + // name === 'tags' ?? + if (name === 'tags'){ + (targetDoc && (targetDoc[DocData].showIconTags = !targetDoc[DocData].showIconTags)) + } else { + (targetDoc && (targetDoc[DocData].showLabels = !targetDoc[DocData].showLabels)) + } + + }} @@ -323,24 +321,27 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => ( return !targetDoc ? null : ( +
+
+ {metaBtn('tags', 'star')} + {metaBtn("keywords", 'id-card')} +
+ Open keyword menu
}>
{ - targetDoc[DocData].showLabels = !targetDoc[DocData].showLabels; - }}> + // targetDoc[DocData].showIconTags = !targetDoc[DocData].showIconTags; + }} + > -
- { - metaBtn('tags', "tag") - /* {pinBtn(true, false, 'window-maximize')} - {pinBtn(false, true, 'address-card')} - {pinBtn(true, true, 'id-card')} */} -
+
+
+ ); } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index b5d819b97..f3b4013f7 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -703,6 +703,7 @@ export class DocumentDecorations extends ObservableReactComponent CollectionFreeFormDocumentView.from(v)); + + + const keyWordTrans = doc[DocData].showLabels ? NumCast(doc[DocData].keywordHeight) : 0 + const tagTrans = doc[DocData].showIconTags ? NumCast(doc[DocData].tagHeight) : 0 + + return (
DocumentView.Selected()} /> diff --git a/src/client/views/FilterPanel.scss b/src/client/views/FilterPanel.scss index d6d2956aa..1877cc78b 100644 --- a/src/client/views/FilterPanel.scss +++ b/src/client/views/FilterPanel.scss @@ -1,3 +1,4 @@ + .filterBox-flyout { display: block; text-align: left; @@ -228,6 +229,69 @@ vertical-align: middle; } +.filterHotKey-button { + pointer-events: auto; + // padding-right: 8px; //5px; + width: 100%; //width: 25px; + border-radius: 5px; + // margin-right: 20px; + margin-bottom: 8px; + border-color: #d3d3d3; + border-style: solid; + border-width: thin; + transition: all 0.3s ease-out; + + &:hover{ + border-color: #e9e9e9; + background-color: #878484 + } + + + + &.active { + background-color: #878484; + + + + .icon-panel{ + display: flex + } + } +} + +.hotKeyButtons { + position: relative; + width: 100%; + // margin-top: 3px; + // // grid-column: 1/4; + // width: 100%; + // height: auto; + // display: flex; + // // flex-direction: row; + // // flex-wrap: wrap; + // padding-bottom: 5.5px; +} + +.hotKey-icon-button { + // pointer-events: auto; /* Re-enable pointer events for the buttons */ + + // width: 30px; + // height: 30px; + // border-color: $medium-blue; + background-color: transparent; + &.active{ + + + } + +} + +.icon-panel { + bottom: -14px; + + + +} // .sliderBox-outerDiv { // width: 30%;// width: calc(100% - 14px); // 14px accounts for handles that are at the max value of the slider that would extend outside the box // height: 40; // height: 100%; diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 332a89a96..e5f9fdb51 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -28,6 +28,19 @@ import { CurrentUserUtils } from '../util/CurrentUserUtils'; import { DocumentOptions } from '../documents/Documents'; import { DocUtils } from '../documents/DocUtils'; import { dropActionType } from '../util/DropActionTypes'; +import { Toggle } from 'browndash-components'; +import { SettingsManager } from '../util/SettingsManager'; +import { StrCast } from '../../fields/Types'; +import { ToggleType } from 'browndash-components'; +import { MultiToggle } from 'browndash-components'; +import { Type } from 'browndash-components'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { DocData } from '../../fields/DocSymbols'; +import { DocumentType } from '../documents/DocumentTypes'; +import { Tooltip } from '@mui/material'; +import { useLocalObservable } from 'mobx-react'; +import { useRef } from 'react'; +import { useEffect } from 'react'; interface filterProps { @@ -228,11 +241,14 @@ export class FilterPanel extends ObservableReactComponent { }; addHotkey() { - const buttons = DocCast(Doc.UserDoc().myContextMenuBtns); - const filter = buttons['Filter'] - const filter2 = DocCast(filter) - const but2 = Doc.UserDoc().myContextMenuBtns + const filter = DocCast(buttons.Filter); + const filter2 = DocCast(filter); + const but2 = Doc.UserDoc().myContextMenuBtns; + + console.log(DocCast(filter).data); + + //[idToDoc("0bec0963-95ac-4978-8606-8af4c7b9badd"),idToDoc("f740e910-bf83-4ee3-b13a-1e63c49dd254"),idToDoc("61db82b0-025a-4cb9-937b-97b1290e8f1a"),idToDoc("1046859f-34ac-4421-bc07-ee2f2cf812e2"),idToDoc("badaff47-3c3a-4b78-a7d6-f2cbc8e45ba0")] // const newCol = Docs.Create.CarouselDocument(DocListCast(doc[Doc.LayoutFieldKey(doc)]), { // _width: 250, @@ -251,59 +267,135 @@ export class FilterPanel extends ObservableReactComponent { // DocumentView.getDocumentView(DocCast(buttons['Card']))?.ComponentView?.addDocument?.(hm) - const hi = CurrentUserUtils.contextMenuTools() - - const newKey: Button = { title: "Cloud", icon: "cloud", toolTip:"Click to toggle the cloud group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"cloud", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}} - - - const heyy = [...hi, newKey] - - Doc.UserDoc().myFilterHotKeyIcons = "palette" - Doc.UserDoc().myFilterHotKeyTitles = "hi" - - CurrentUserUtils.setupContextMenuButtons(Doc.UserDoc()); - - - - Doc.UserDoc().hi = Docs.Create.FontIconDocument( - { title: '', - icon: 'map-pin', - - backgroundColor: '#ACCEF7', - layout_hideAllLinks: true, - _width: 15, - _height: 15, - _xPadding: 0, - } - ) - - - // buttons['Filter'] + // const hi = CurrentUserUtils.contextMenuTools() + + const newKey: Button = { + title: 'Bob', + icon: 'cloud', + toolTip: "Click to toggle the cloud group's visibility", + btnType: ButtonType.ToggleButton, + expertMode: false, + toolType: 'cloud', + funcs: {}, + scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}' }, + }; + + // const heyy = [...hi, newKey] + + Doc.UserDoc().myFilterHotKeyTitles = new List(['hi hi', 'supppp']) + + Doc.UserDoc()['hi hi'] = 'heart' + Doc.UserDoc()['supppp'] = 'star' + + // CurrentUserUtils.setupContextMenuButtons(Doc.UserDoc()); + + // Doc.UserDoc().hi = Docs.Create.FontIconDocument( + // { title: '', + // icon: 'map-pin', + + // backgroundColor: '#ACCEF7', + // layout_hideAllLinks: true, + // _width: 15, + // _height: 15, + // _xPadding: 0, + // } + // ) + + // // buttons['Filter'] + + // const reqdCtxtOpts: DocumentOptions = { + // title: 'Filter', + // undoIgnoreFields: new List(['width', 'linearView_IsOpen']), + // flexGap: 0, + // childDragAction: dropActionType.embed, + // childDontRegisterViews: true, + // linearView_IsOpen: true, + // ignoreClick: true, + // linearView_Expandable: false, + // _height: 35, + // }; + const ctxtMenuBtn = CurrentUserUtils.setupContextMenuBtn(newKey, filter); + ctxtMenuBtn.isSystem = ctxtMenuBtn[DocData].isSystem = undefined; + Doc.AddDocToList(filter, 'data', ctxtMenuBtn); + // // // DocUtils.AssignOpts(buttons, reqdCtxtOpts, ctxtMenuBtns); + + // DocUtils.AssignOpts(DocCast(buttons['Filter']), reqdCtxtOpts, [ctxtMenuBtns]); + // newCol && dv.ComponentView?.addDocument?.(newCol); + // console.log(but2 + "omgg") + // doc.cardSort_activeIcons = new List(list.includes(icon) ? list.filter(d => d !== icon) : [...list, icon]); - const reqdCtxtOpts:DocumentOptions = { title: "hi", undoIgnoreFields:new List(['width', "linearView_IsOpen"]), flexGap: 0, childDragAction: dropActionType.embed, childDontRegisterViews: true, linearView_IsOpen: true, ignoreClick: true, linearView_Expandable: false, _height: 35 }; - const ctxtMenuBtns = CurrentUserUtils.setupContextMenuBtn(newKey, buttons); - // DocUtils.AssignOpts(buttons, reqdCtxtOpts, ctxtMenuBtns); + // Doc.UserDoc().myContextMenuBtns = new List([...buttons, newKey as Doc]) + } + hotKeyButtons() { + const selected = DocumentView.SelectedDocs().lastElement(); - DocUtils.AssignOpts(DocCast(buttons['Filter']), reqdCtxtOpts, [ctxtMenuBtns]); + function isAttrFiltered(attr: string) { + if (selected && selected._childFilters != undefined && selected.type === DocumentType.COL) { + return StrListCast(selected._childFilters).some(filter => filter.includes(attr)); + } else { + return false; + } + // return selected._childFilters ? StrListCast(selected._childFilters).some(filter => filter.includes(attr)) : false; + } + const hotKeys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles); - // newCol && dv.ComponentView?.addDocument?.(newCol); + console.log(hotKeys + 'hiihihi'); - // console.log(but2 + "omgg") + const hi = ['star', 'heart', 'bolt']; + - // doc.cardSort_activeIcons = new List(list.includes(icon) ? list.filter(d => d !== icon) : [...list, icon]); + //selecting a button should make t so that the the icon on the top filter panel becomes said icon + const buttons = hotKeys.map((hotKey, i) => ( + //
{ + // // if (e.target === e.currentTarget){ + // isAttrFiltered(hotKey) ? Doc.setDocFilter(selected, hotKey, true, 'remove') : Doc.setDocFilter(selected, hotKey, true, 'match'); + // // } + // }, hotKey)} - // Doc.UserDoc().myContextMenuBtns = new List([...buttons, newKey as Doc]) + // // style = {{backgroundColor: `${isAttrFiltered(hotKey) ? '#878484' : SettingsManager.userBackgroundColor}`}} + + + // > + {/* } + iconPlacement="left" + align="flex-start" + fillWidth + toggleType={ToggleType.BUTTON} + onClick={undoable(() => { + isAttrFiltered(hotKey) ? Doc.setDocFilter(selected, hotKey, true, 'remove') : Doc.setDocFilter(selected, hotKey, true, 'match'); + }, hotKey)} + /> */} + <> + + Click to customize this hotkey's icon
}> + + + + + + )); + + return buttons; } + // @observable iconPanelMap: Map = new Map(); + render() { return (
@@ -376,8 +468,9 @@ export class FilterPanel extends ObservableReactComponent {
-
+ +
{this.hotKeyButtons()}
); } @@ -486,3 +579,113 @@ export class FilterPanel extends ObservableReactComponent { return undefined; } } + + + +interface HotKeyButtonProps { + hotKey: string; + selected?: Doc +} + +const HotKeyIconButton: React.FC = observer(({ hotKey, selected}) => { + const state = useLocalObservable(() => ({ + isActive: false, + toggleActive() { + this.isActive = !this.isActive; + }, + deactivate() { + this.isActive = false; + } + })); + + const panelRef = useRef(null); + + const handleClick = () => { + state.toggleActive(); + + console.log(state.isActive + "hmmm") + }; + + const handleClickOutside = (event: MouseEvent) => { + if (panelRef.current && !panelRef.current.contains(event.target as Node)) { + state.deactivate(); + } + }; + + useEffect(() => { + document.addEventListener('mousedown', handleClickOutside); + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + }, []); + + const iconOpts = ['star', 'heart', 'bolt']; + + const iconPanel = iconOpts.map((icon, i) => ( + + )); + + const hotKeys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles) + + return ( + <> + +
{ + + // if (e.target === e.currentTarget){ + isAttrFiltered(hotKey) ? Doc.setDocFilter(selected, hotKey, true, 'remove') : Doc.setDocFilter(selected, hotKey, true, 'match'); + // } + }, hotKey)} + + // style = {{backgroundColor: `${isAttrFiltered(hotKey) ? '#878484' : SettingsManager.userBackgroundColor}`}} + + + > +
+ Click to customize this hotkey's icon
}> + + + {state.isActive && ( +
+ {iconPanel} +
+ )} + + +
+ +

{hotKey.toUpperCase()}

+ + + + +
+ + + + + + ); +}); + + diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f552540b8..9da359e1b 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -551,7 +551,8 @@ export class MainView extends ObservableReactComponent<{}> { fa.faStar, fa.faCloud, fa.faBolt, - fa.faLightbulb + fa.faLightbulb, + fa.faX ] ); } diff --git a/src/client/views/nodes/IconTagBox.tsx b/src/client/views/nodes/IconTagBox.tsx index 9a2273c3a..73360b684 100644 --- a/src/client/views/nodes/IconTagBox.tsx +++ b/src/client/views/nodes/IconTagBox.tsx @@ -41,24 +41,24 @@ export class IconTagBox extends ObservableReactComponent { this.ref = React.createRef(); } - 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; - } - } - ); - } + // 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): void { - this.height = this.ref.current?.getBoundingClientRect().height ? this.ref.current?.getBoundingClientRect().height : 0; - this._props.doc._keywordHeight = this.height; + // this.height = this.ref.current?.getBoundingClientRect().height ? this.ref.current?.getBoundingClientRect().height : 0; + this._props.doc[DocData].tagHeight = 36*this.currentScale; } /** @@ -93,12 +93,16 @@ export class IconTagBox extends ObservableReactComponent { 3: 'bolt' }; + + return (
Date: Thu, 22 Aug 2024 03:03:03 -0400 Subject: liberty --- src/client/util/CurrentUserUtils.ts | 14 +- src/client/views/FilterPanel.scss | 67 +++- src/client/views/FilterPanel.tsx | 352 ++++++++++----------- .../views/collections/CollectionCardDeckView.tsx | 9 +- src/client/views/nodes/IconTagBox.tsx | 75 ++++- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 2 +- 6 files changed, 324 insertions(+), 195 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 0d8955ced..1a7c0f6e1 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -714,6 +714,17 @@ pie title Minerals in my tap water // ] // } static tagGroupTools(): Button[] { + if (!Doc.UserDoc().activeDashboard){ + Doc.UserDoc().myFilterHotKeyTitles = new List(['Star', 'Heart', 'Bolt', 'Cloud' ]) + + Doc.UserDoc()['Star'] = 'star' + Doc.UserDoc()['Heart'] = 'heart' + Doc.UserDoc()['Bolt'] = 'bolt' + Doc.UserDoc()['Cloud'] = 'cloud' + + } + + // hack: if there's no dashboard, create default filters. otherwise, just make sure that the Options button is preserved return (Doc.UserDoc().activeDashboard ? [] : [ { title: "Star", isSystem: false, icon: "star", toolTip:"Click to toggle the star group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, @@ -730,7 +741,7 @@ pie title Minerals in my tap water // { title: "", icon, toolTip:"Click to toggle group 6's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"6", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // { title: "", icon, toolTip:"Click to toggle group 7's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"7", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, ]).concat([ - { title: "Options", isSystem: true,icon: "gear", toolTip:"Click to customize your filter panel", btnType: ButtonType.ClickButton, expertMode: false, toolType:"opts", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}} + { title: "Options", isSystem: true,icon: "gear", toolTip:"Click to customize your filter panel", btnType: ButtonType.ClickButton, expertMode: false, toolType:"opts", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}} ]) } static viewTools(): Button[] { @@ -1045,6 +1056,7 @@ pie title Minerals in my tap water doc.filterDocCount = 0; doc.treeView_FreezeChildren = "remove|add"; doc.activePage = doc.activeDashboard === undefined ? 'home': doc.activePage; + this.setupLinkDocs(doc, linkDatabaseId); this.setupSharedDocs(doc, sharingDocumentId); // sets up the right sidebar collection for mobile upload documents and sharing this.setupDefaultIconTemplates(doc); // creates a set of icon templates triggered by the document deoration icon diff --git a/src/client/views/FilterPanel.scss b/src/client/views/FilterPanel.scss index 1877cc78b..0b9076f3b 100644 --- a/src/client/views/FilterPanel.scss +++ b/src/client/views/FilterPanel.scss @@ -235,28 +235,62 @@ width: 100%; //width: 25px; border-radius: 5px; // margin-right: 20px; - margin-bottom: 8px; + margin-top: 8px; border-color: #d3d3d3; border-style: solid; border-width: thin; transition: all 0.3s ease-out; + display: flex; + flex-direction: row; + padding: 5px; /* Adjust the padding value as needed */ + &:hover{ border-color: #e9e9e9; - background-color: #878484 + background-color: #6d6c6c } - &.active { - background-color: #878484; + // &.active { + // background-color: #6d6c6c; + + + + // .icon-panel{ + // display: flex + // } + // } + .hotKey-icon, .hotKey-close{ + background-color: transparent; + border-radius: 10%; + padding: 5px; - .icon-panel{ - display: flex + &:hover{ + background-color: #616060; } } + + .hotKey-close{ + right: 30px; + position: fixed; + padding-top: 10px; + +} + + .hotkey-title{ + top: 6px; + position: relative; + } + + .hotkey-title-input{ + background-color: transparent; + border: none; + border-color: transparent; + outline: none; + } } .hotKeyButtons { @@ -287,7 +321,26 @@ } .icon-panel { - bottom: -14px; + // bottom: -14px; + position: absolute; + z-index: 10000; + // background-color: #616060; + // background-color: #323232; + border-color: black; + border-style: solid; + border-width: medium; + border-radius: 10%; + background-color: #323232; + + .icon-panel-button{ + background-color: #323232; + border-radius: 10%; + + + &:hover{ + background-color:#7a7878 + } + } diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index e5f9fdb51..17c5cb173 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -41,6 +41,7 @@ import { Tooltip } from '@mui/material'; import { useLocalObservable } from 'mobx-react'; import { useRef } from 'react'; import { useEffect } from 'react'; +import { useState } from 'react'; interface filterProps { @@ -240,157 +241,74 @@ export class FilterPanel extends ObservableReactComponent { return nonNumbers / facetValues.length > 0.1 ? facetValues.sort() : facetValues.sort((n1: string, n2: string) => Number(n1) - Number(n2)); }; - addHotkey() { + addHotkey(hotKey: string) { const buttons = DocCast(Doc.UserDoc().myContextMenuBtns); const filter = DocCast(buttons.Filter); const filter2 = DocCast(filter); const but2 = Doc.UserDoc().myContextMenuBtns; - console.log(DocCast(filter).data); - - //[idToDoc("0bec0963-95ac-4978-8606-8af4c7b9badd"),idToDoc("f740e910-bf83-4ee3-b13a-1e63c49dd254"),idToDoc("61db82b0-025a-4cb9-937b-97b1290e8f1a"),idToDoc("1046859f-34ac-4421-bc07-ee2f2cf812e2"),idToDoc("badaff47-3c3a-4b78-a7d6-f2cbc8e45ba0")] - - // const newCol = Docs.Create.CarouselDocument(DocListCast(doc[Doc.LayoutFieldKey(doc)]), { - // _width: 250, - // _height: 200, - // _layout_fitWidth: false, - // _layout_autoHeight: true, - // }); - - // CurrentUserUtils.setupContextMenuButtons() - - // const hm = Docs.Create.FontIconDocument() - - // DocumentView.getDocumentView(filter2)?.ComponentView?.addDocument?.(hm) - - // console.log(DocumentView.getDocumentView(filter2) + "hiiiii") - - // DocumentView.getDocumentView(DocCast(buttons['Card']))?.ComponentView?.addDocument?.(hm) - - // const hi = CurrentUserUtils.contextMenuTools() const newKey: Button = { - title: 'Bob', - icon: 'cloud', - toolTip: "Click to toggle the cloud group's visibility", + title: hotKey, + icon: 'bolt', + toolTip: `Click to toggle the ${hotKey}'s group's visibility`, btnType: ButtonType.ToggleButton, expertMode: false, - toolType: 'cloud', + toolType: 'bolt', funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}' }, }; // const heyy = [...hi, newKey] - Doc.UserDoc().myFilterHotKeyTitles = new List(['hi hi', 'supppp']) + const currHotKeys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles) - Doc.UserDoc()['hi hi'] = 'heart' - Doc.UserDoc()['supppp'] = 'star' + Doc.UserDoc().myFilterHotKeyTitles = new List(currHotKeys.concat(hotKey)) - // CurrentUserUtils.setupContextMenuButtons(Doc.UserDoc()); + Doc.UserDoc()[hotKey] = 'bolt' + // Doc.UserDoc()['supppp'] = 'star' - // Doc.UserDoc().hi = Docs.Create.FontIconDocument( - // { title: '', - // icon: 'map-pin', - // backgroundColor: '#ACCEF7', - // layout_hideAllLinks: true, - // _width: 15, - // _height: 15, - // _xPadding: 0, - // } - // ) + const newBtn = CurrentUserUtils.setupContextMenuBtn(newKey, filter); + newBtn.isSystem = newBtn[DocData].isSystem = undefined; - // // buttons['Filter'] + const subDocs = DocListCast(filter.data) + const opts = subDocs[subDocs.length-1] + Doc.AddDocToList(filter, 'data', newBtn, opts, true); - // const reqdCtxtOpts: DocumentOptions = { - // title: 'Filter', - // undoIgnoreFields: new List(['width', 'linearView_IsOpen']), - // flexGap: 0, - // childDragAction: dropActionType.embed, - // childDontRegisterViews: true, - // linearView_IsOpen: true, - // ignoreClick: true, - // linearView_Expandable: false, - // _height: 35, - // }; - const ctxtMenuBtn = CurrentUserUtils.setupContextMenuBtn(newKey, filter); - ctxtMenuBtn.isSystem = ctxtMenuBtn[DocData].isSystem = undefined; - Doc.AddDocToList(filter, 'data', ctxtMenuBtn); - // // // DocUtils.AssignOpts(buttons, reqdCtxtOpts, ctxtMenuBtns); - - // DocUtils.AssignOpts(DocCast(buttons['Filter']), reqdCtxtOpts, [ctxtMenuBtns]); + - // newCol && dv.ComponentView?.addDocument?.(newCol); + // console.log(filter[DocData].data + 'ok') + // // console.log(filter[DocData][0] + 'help') + // console.log(filter[DocData] + 'good grief') - // console.log(but2 + "omgg") + // console.log(DocCast(DocCast(filter.data))[0]) + // this.removeHotKey() - // doc.cardSort_activeIcons = new List(list.includes(icon) ? list.filter(d => d !== icon) : [...list, icon]); + // console.log(DocCast(filter.data) + 'HI') + // console.log(DocListCast(filter.data) + 'WOOOOO') + // console.log(DocCast(filter.data)[0] + 'hm :(') - // Doc.UserDoc().myContextMenuBtns = new List([...buttons, newKey as Doc]) } + + hotKeyButtons() { const selected = DocumentView.SelectedDocs().lastElement(); - function isAttrFiltered(attr: string) { - if (selected && selected._childFilters != undefined && selected.type === DocumentType.COL) { - return StrListCast(selected._childFilters).some(filter => filter.includes(attr)); - } else { - return false; - } - // return selected._childFilters ? StrListCast(selected._childFilters).some(filter => filter.includes(attr)) : false; - } + // console.log(StrListCast(Doc.UserDoc().myFilterHotKeyTitles) + "hiii") const hotKeys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles); - console.log(hotKeys + 'hiihihi'); - - const hi = ['star', 'heart', 'bolt']; - - - - - //selecting a button should make t so that the the icon on the top filter panel becomes said icon - + // hotKeys.forEach(l => console.log(l + "render")) + + // Selecting a button should make it so that the icon on the top filter panel becomes said icon const buttons = hotKeys.map((hotKey, i) => ( - //
{ - - // // if (e.target === e.currentTarget){ - // isAttrFiltered(hotKey) ? Doc.setDocFilter(selected, hotKey, true, 'remove') : Doc.setDocFilter(selected, hotKey, true, 'match'); - // // } - // }, hotKey)} - - // // style = {{backgroundColor: `${isAttrFiltered(hotKey) ? '#878484' : SettingsManager.userBackgroundColor}`}} - - - // > - {/* } - iconPlacement="left" - align="flex-start" - fillWidth - toggleType={ToggleType.BUTTON} - onClick={undoable(() => { - isAttrFiltered(hotKey) ? Doc.setDocFilter(selected, hotKey, true, 'remove') : Doc.setDocFilter(selected, hotKey, true, 'match'); - }, hotKey)} - /> */} - <> - - Click to customize this hotkey's icon
}> - - - - - + Click to customize this hotkey's icon
}> + + )); - + return buttons; } @@ -465,7 +383,7 @@ export class FilterPanel extends ObservableReactComponent {
- +
@@ -590,28 +508,87 @@ interface HotKeyButtonProps { const HotKeyIconButton: React.FC = observer(({ hotKey, selected}) => { const state = useLocalObservable(() => ({ isActive: false, + isEditing: false, + myHotKey: hotKey, + toggleActive() { this.isActive = !this.isActive; }, deactivate() { this.isActive = false; + }, + startEditing() { + this.isEditing = true; + }, + stopEditing() { + this.isEditing = false; + }, + setHotKey(newHotKey: string) { + this.myHotKey = newHotKey; } })); const panelRef = useRef(null); + const inputRef = useRef(null); const handleClick = () => { state.toggleActive(); - - console.log(state.isActive + "hmmm") + // console.log(state.isActive + "hmmm") }; + const hotKeys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles) + + const myHotKeyDoc = () => { + const buttons = DocCast(Doc.UserDoc().myContextMenuBtns); + const filter = DocCast(buttons.Filter); + const hotKeyDocs = DocListCast(filter.data) + return hotKeyDocs.filter(k => StrCast(k.title) === hotKey)[0] + + } + + const removeHotKey = () => { + const buttons = DocCast(Doc.UserDoc().myContextMenuBtns); + const filter = DocCast(buttons.Filter); + + Doc.RemoveDocFromList(filter, 'data', myHotKeyDoc()); + + + + + + // console.log((DocListCast(filter.data)[0].title) + "emmanuel") + + + // console.log(DocCast(filter.data) + 'HI') + // console.log(DocCast(filter.data)[0] + 'hm :(') + + } const handleClickOutside = (event: MouseEvent) => { if (panelRef.current && !panelRef.current.contains(event.target as Node)) { state.deactivate(); + if (state.isEditing) { + state.stopEditing(); + + updateFromInput() + + + + // Doc.UserDoc().myFilterHotKeyTitles = new List(hotKeys.map(k => k === hotKey ? state.myHotKey : k)); + // Doc.UserDoc()[state.myHotKey] = StrCast(Doc.UserDoc()[hotKey]) + + } } }; + const updateFromInput = () => { + const hi = myHotKeyDoc() + Doc.UserDoc().myFilterHotKeyTitles = new List(hotKeys.map(k => k === hotKey ? state.myHotKey : k)); + Doc.UserDoc()[state.myHotKey] = StrCast(Doc.UserDoc()[hotKey]) + hi.title = state.myHotKey + hi.toolTip = `Click to toggle the ${state.myHotKey}'s group's visibility` + } + + useEffect(() => { document.addEventListener('mousedown', handleClickOutside); return () => { @@ -619,73 +596,96 @@ const HotKeyIconButton: React.FC = observer(({ hotKey, select }; }, []); - const iconOpts = ['star', 'heart', 'bolt']; + const iconOpts = ['star', 'heart', 'bolt', 'satellite', 'palette', 'robot', 'lightbulb', 'highlighter', 'book', 'chalkboard' ]; const iconPanel = iconOpts.map((icon, i) => ( - - )); + + )); -
{ + function isAttrFiltered(attr: string) { + if (selected && selected._childFilters !== undefined && selected.type === DocumentType.COL) { + return StrListCast(selected._childFilters).some(filter => filter.includes(attr)); + } else { + return false; + } + } - // if (e.target === e.currentTarget){ - isAttrFiltered(hotKey) ? Doc.setDocFilter(selected, hotKey, true, 'remove') : Doc.setDocFilter(selected, hotKey, true, 'match'); - // } - }, hotKey)} - // style = {{backgroundColor: `${isAttrFiltered(hotKey) ? '#878484' : SettingsManager.userBackgroundColor}`}} - - + return ( +
{ + e.stopPropagation(); + state.startEditing(); + setTimeout(() => inputRef.current?.focus(), 0); + }} + > +
+ Click to customize this hotkey's icon
}> + + + {state.isActive && ( +
+ {iconPanel} +
+ )} +
+ {state.isEditing ? ( + state.setHotKey(e.target.value)} + onBlur={() => { + state.stopEditing(); + updateFromInput() }} + onKeyDown={(e) => { + if (e.key === 'Enter') { + state.stopEditing(); + updateFromInput() - > - - - - {state.isActive && ( -
- {iconPanel} -
+ } + }} + className='hotkey-title-input' + /> + ) : ( +

{hotKey.toUpperCase()}

)} - - -
- -

{hotKey.toUpperCase()}

- - - - + - - - - - ); -}); - - +}) diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 736cc2354..52f01e239 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -95,7 +95,14 @@ export class CollectionCardView extends CollectionSubView() { }; componentDidMount(): void { + this.Document.childFilters_boolean = 'OR' + this.childDocsWithoutLinks.forEach(c => { + c[DocData].showIconTags = true + + }); + + this._disposers.sort = reaction( () => ({ cardSort: this.cardSort }), ({ cardSort}) => (cardSort === cardSortings.Chat ? this.openChatPopup() : GPTPopup.Instance.setVisible(false)) @@ -672,7 +679,7 @@ export class CollectionCardView extends CollectionSubView() { }} onMouseEnter={() => this.setHoveredNodeIndex(index)}> {this.displayDoc(doc, childScreenToLocal)} - {this.renderButtons(doc, this.cardSort)} + {/* {this.renderButtons(doc, this.cardSort)} */} ); }); diff --git a/src/client/views/nodes/IconTagBox.tsx b/src/client/views/nodes/IconTagBox.tsx index 73360b684..cdf2075cb 100644 --- a/src/client/views/nodes/IconTagBox.tsx +++ b/src/client/views/nodes/IconTagBox.tsx @@ -16,6 +16,15 @@ import { BoolCast } from "../../../fields/Types"; import { DocCast } from "../../../fields/Types"; import './IconTagBox.scss'; import { AclAdmin, AclAugment, AclEdit, DocData } from '../../../fields/DocSymbols'; +import { StrListCast } from "../../../fields/Doc"; +import { StrCast } from "../../../fields/Types"; +import { DocListCast } from "../../../fields/Doc"; +import { List } from "../../../fields/List"; +import { action } from "mobx"; +import { DragManager } from "../../util/DragManager"; +import { setupMoveUpEvents } from "../../../ClientUtils"; +import { returnFalse } from "../../../ClientUtils"; +import { emptyFunction } from "../../../Utils"; export interface IconTagProps { @@ -61,6 +70,53 @@ export class IconTagBox extends ObservableReactComponent { this._props.doc[DocData].tagHeight = 36*this.currentScale; } + // createCollection = () => { + // // Get the documents that contain the keyword. + // const selected = DocListCast(this.getKeywordCollectionDocs()!); + // const newEmbeddings = selected.map(doc => Doc.MakeEmbedding(doc)); + + // // Create a new collection and set up configurations. + // const newCollection = ((doc: Doc) => { + // const docData = doc[DocData]; + // docData.data = new List(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; + + // // Add the collection to the keyword document's list of associated smart collections. + // this._props.keywordDoc.collections = new List([...DocListCast(this._props.keywordDoc.collections), newCollection]); + // newCollection[DocData].data_labels = new List([this._props.keyword]); + // newCollection[DocData][`${this._props.keyword}`] = true; + // newCollection[DocData].showLabels = true; + // 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(); + // } + // }; + /** * Renders the buttons to customize sorting depending on which group the card belongs to and the amount of total groups * @param doc @@ -70,7 +126,10 @@ export class IconTagBox extends ObservableReactComponent { renderButtons = (doc: Doc): JSX.Element | null => { // if (cardSort !== cardSortings.Custom) return null; - const amButtons = 4 + const amButtons = StrListCast(Doc.UserDoc().myFilterHotKeyTitles).length + + const keys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles) + // const amButtons = Math.max( // 4, @@ -86,11 +145,9 @@ export class IconTagBox extends ObservableReactComponent { const totalWidth = amButtons * 35 + amButtons * 2 * 5 + 6; - const iconMap: { [key: number]: any } = { - 0: 'star', - 1: 'heart', - 2: 'cloud', - 3: 'bolt' + const iconMap = (buttonID: number) => { + return StrCast(Doc.UserDoc()[keys[buttonID]]) + }; @@ -108,9 +165,9 @@ export class IconTagBox extends ObservableReactComponent { }} > {numberRange(amButtons).map(i => ( - Click to add/remove this card from the {iconMap[i]} group}> - ))} diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index a41c33a4d..d216cc421 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -484,7 +484,7 @@ export class GPTPopup extends ObservableReactComponent { e.stopPropagation(); }} type="text" - placeholder={`${isSort ? 'How do you want to sort your cards?' : 'What is the selected card?'}`} + placeholder={`${isSort ? 'How do you want to sort your cards?' : 'Define the selected card?'}`} id="search-input" style={{ width: '100%' }} /> -- cgit v1.2.3-70-g09d2 From a5ac17898151df59c748547acbcb0d2ac63d357d Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 4 Sep 2024 13:21:52 -0400 Subject: start of conversion of Calendar into a CollectionView --- src/client/documents/DocumentTypes.ts | 1 - src/client/documents/Documents.ts | 14 +++++++++----- src/client/util/CurrentUserUtils.ts | 2 +- src/client/views/DashboardView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 4 +++- src/client/views/nodes/calendarBox/CalendarBox.tsx | 16 +++------------- 6 files changed, 17 insertions(+), 22 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index b055546fc..56d505681 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -39,7 +39,6 @@ export enum DocumentType { COMPARISON = 'comparison', PUSHPIN = 'pushpin', MAPROUTE = 'maproute', - CALENDAR = 'calendar', SCRIPTDB = 'scriptdb', // database of scripts GROUPDB = 'groupdb', // database of groups diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 1acc6bb46..d5a7b0465 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -913,7 +913,15 @@ export namespace Docs { } export function CalendarDocument(options: DocumentOptions, documents: Array) { - return InstanceFromProto(Prototypes.get(DocumentType.CALENDAR), new List(documents), { ...options }); + const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { + _layout_nativeDimEditable: true, + _layout_reflowHorizontal: true, + _layout_reflowVertical: true, + ...options, + _type_collection: CollectionViewType.Calendar, + }); + documents.forEach(d => Doc.SetContainer(d, inst)); + return inst; } // shouldn't ever need to create a KVP document-- instead set the LayoutTemplateString to be a KeyValueBox for the DocumentView (see addDocTab in TabDocView) @@ -970,10 +978,6 @@ export namespace Docs { return doc; } - export function CalendarCollectionDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _type_collection: CollectionViewType.Calendar }); - } - export function StackingDocument(documents: Array, options: DocumentOptions, id?: string, protoId?: string) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _type_collection: CollectionViewType.Stacking }, id, undefined, protoId); } diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 14fb65252..f042f33ce 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -787,7 +787,7 @@ pie title Minerals in my tap water CollectionViewType.Stacking, CollectionViewType.Masonry, CollectionViewType.Multicolumn, CollectionViewType.Multirow, CollectionViewType.Time, CollectionViewType.Carousel, CollectionViewType.Carousel3D, CollectionViewType.Card, CollectionViewType.Linear, CollectionViewType.Map, - CollectionViewType.Grid, CollectionViewType.NoteTaking, ]), + CollectionViewType.Calendar, CollectionViewType.Grid, CollectionViewType.NoteTaking, ]), title: "Perspective", toolTip: "View", btnType: ButtonType.DropdownList, ignoreClick: true, width: 100, scripts: { script: '{ return setView(value, _readOnly_); }'}}, { title: "Pin", icon: "map-pin", toolTip: "Pin View to Trail", btnType: ButtonType.ClickButton, expertMode: false, width: 30, scripts: { onClick: 'pinWithView(altKey)'}, funcs: {hidden: "IsNoneSelected()"}}, { title: "Header", icon: "heading", toolTip: "Doc Titlebar Color", btnType: ButtonType.ColorButton, expertMode: false, ignoreClick: true, scripts: { script: 'return setHeaderColor(value, _readOnly_)'} }, diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx index 33e905a54..eced64524 100644 --- a/src/client/views/DashboardView.tsx +++ b/src/client/views/DashboardView.tsx @@ -465,7 +465,7 @@ export class DashboardView extends ObservableReactComponent { isSystem: true, layout_explainer: 'All of the calendars that you have created will appear here.', }; - const myCalendars = DocUtils.AssignScripts(Docs.Create.CalendarCollectionDocument([], reqdOpts)); + const myCalendars = DocUtils.AssignScripts(Docs.Create.StackingDocument([], reqdOpts)); // { treeView_ChildDoubleClick: 'openPresentation(documentView.rootDoc)' } return new PrefetchProxy(myCalendars); } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index ab93abab6..c9e934448 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -34,6 +34,7 @@ import { CollectionLinearView } from './collectionLinear'; import { CollectionMulticolumnView } from './collectionMulticolumn/CollectionMulticolumnView'; import { CollectionMultirowView } from './collectionMulticolumn/CollectionMultirowView'; import { CollectionSchemaView } from './collectionSchema/CollectionSchemaView'; +import { CalendarBox } from '../nodes/calendarBox/CalendarBox'; @observer export class CollectionView extends ViewBoxAnnotatableComponent() { @@ -91,7 +92,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent; - case CollectionViewType.Calendar: return ; + case CollectionViewType.Calendar: return ; case CollectionViewType.Docking: return ; case CollectionViewType.Tree: return ; case CollectionViewType.Multicolumn: return ; @@ -126,6 +127,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent func(CollectionViewType.Masonry), icon: 'columns' }, { description: 'Carousel', event: () => func(CollectionViewType.Carousel), icon: 'columns' }, { description: '3D Carousel', event: () => func(CollectionViewType.Carousel3D), icon: 'columns' }, + { description: 'Calendar', event: () => func(CollectionViewType.Calendar), icon: 'columns' }, { description: 'Pivot/Time', event: () => func(CollectionViewType.Time), icon: 'columns' }, { description: 'Map', event: () => func(CollectionViewType.Map), icon: 'globe-americas' }, { description: 'Grid', event: () => func(CollectionViewType.Grid), icon: 'th-list' }, diff --git a/src/client/views/nodes/calendarBox/CalendarBox.tsx b/src/client/views/nodes/calendarBox/CalendarBox.tsx index ca35d85b3..20650d648 100644 --- a/src/client/views/nodes/calendarBox/CalendarBox.tsx +++ b/src/client/views/nodes/calendarBox/CalendarBox.tsx @@ -12,21 +12,18 @@ import { Docs } from '../../../documents/Documents'; import { ViewBoxBaseComponent } from '../../DocComponent'; import { FieldView, FieldViewProps } from '../FieldView'; import './CalendarBox.scss'; +import { CollectionSubView, SubCollectionViewProps } from '../../collections/CollectionSubView'; type CalendarView = 'month' | 'multi-month' | 'week'; @observer -export class CalendarBox extends ViewBoxBaseComponent() { - public static LayoutString(fieldKey: string = 'calendar') { - return FieldView.LayoutString(CalendarBox, fieldKey); - } - +export class CalendarBox extends CollectionSubView() { _calendarRef: HTMLDivElement | null = null; _calendar: Calendar | undefined; _oldWheel: HTMLElement | null = null; _observer: ResizeObserver | undefined; - constructor(props: FieldViewProps) { + constructor(props: SubCollectionViewProps) { super(props); makeObservable(this); } @@ -78,9 +75,6 @@ export class CalendarBox extends ViewBoxBaseComponent() { if (Math.abs(startDate.getDay() - endDate.getDay()) > 7) return 'month'; return 'week'; } - @computed get childDocs() { - return DocListCast(this.dataDoc[this.fieldKey]); - } eventToColor(event: Doc): string { // TODO: Return a different color based on the event type @@ -149,7 +143,3 @@ export class CalendarBox extends ViewBoxBaseComponent() { ); } } -Docs.Prototypes.TemplateMap.set(DocumentType.CALENDAR, { - layout: { view: CalendarBox, dataField: 'data' }, - options: { acl: '', _layout_nativeDimEditable: true, _layout_reflowHorizontal: true, _layout_reflowVertical: true }, -}); -- cgit v1.2.3-70-g09d2 From 4e34335e600b5d9d29e8a4af99fda6b2a6d3ba69 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Tue, 10 Sep 2024 10:54:29 -0400 Subject: more chat features --- src/client/apis/gpt/GPT.ts | 34 ++- src/client/util/CurrentUserUtils.ts | 20 +- src/client/views/FilterPanel.scss | 18 ++ src/client/views/FilterPanel.tsx | 3 + src/client/views/InkingStroke.tsx | 14 +- .../views/collections/CollectionCardDeckView.tsx | 221 +++++++------- src/client/views/global/globalScripts.ts | 26 +- src/client/views/nodes/IconTagBox.tsx | 23 +- src/client/views/pdf/GPTPopup/GPTPopup.scss | 56 +++- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 319 ++++++++++++++++----- 10 files changed, 525 insertions(+), 209 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index d95e564c7..f9183d3e2 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -12,7 +12,10 @@ enum GPTCallType { DESCRIBE = 'describe', MERMAID = 'mermaid', DATA = 'data', - RUBRIC = 'rubric' + RUBRIC = 'rubric', + TYPE = 'type', + SUBSET = 'subset', + INFO = 'info' } type GPTCallOpts = { @@ -45,7 +48,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { model: 'gpt-4o', maxTokens: 2048, temp: 0.25, - prompt: "The user is going to give you a list of descriptions. Each one is separated by `======` on either side. Descriptions will vary in length, so make sure to only separate when you see `======`. Sort them by shared content. Make sure each description is only in the list once. Each item should be separated by `======`. Immediately afterward, surrounded by `------` on BOTH SIDES, provide some insight into your reasoning for the way you sorted (and mention nothing about the formatting details given in this description). It is VERY important that you format it exactly as described, ensuring the proper number of `=` and `-` (6 of each) and no commas" + prompt: "The user is going to give you a list of descriptions. Each one is separated by `======` on either side. Descriptions will vary in length, so make sure to only separate when you see `======`. Sort them by the user's specifications. Make sure each description is only in the list once. Each item should be separated by `======`. Immediately afterward, surrounded by `------` on BOTH SIDES, provide some insight into your reasoning for the way you sorted (and mention nothing about the formatting details given in this description). It is VERY important that you format it exactly as described, ensuring the proper number of `=` and `-` (6 of each) and NO commas" // prompt: "I'm going to give you a list of descriptions. Each one is separated by `======` on either side. Descriptions will vary in length, so make sure to only separate when you see `======`. Sort them into lists by shared content. Make sure each description is in only one list. Each list should be separated by `======` with the elements within it separated by `~~~~~~`. Immediately afterward, surrounded by `------` on BOTH SIDES, provide some insight into your reasoning for the way you sorted. It is VERY important that you format it exactly as described, ensuring the proper number of `=` `~` and `-` (6 of each) and no commas.Try to create around 4 groups, but a little more or less is ok. Also, I may provide some more insight after this colon:" }, describe: { model: 'gpt-4-vision-preview', maxTokens: 2048, temp: 0, prompt: 'Describe these images in 3-5 words' }, @@ -54,15 +57,38 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { model: 'gpt-4-turbo', maxTokens: 1024, temp: 0, - prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If there are no differences, say correct', + prompt: "BRIEFLY (<50 words) describe any differences between the rubric and the user's answer answer in second person. If there are no differences, say correct", }, rubric: { model: 'gpt-4-turbo', maxTokens: 1024, temp: 0, - prompt: "Provide a definition for the vollowing term. It will be used as a rubric to evaluate the user's understanding of the topic", + prompt: "BRIEFLY (<75 words) provide a definition for the following term. It will be used as a rubric to evaluate the user's understanding of the topic", }, + + type: { + model: 'gpt-4-turbo', + maxTokens: 1024, + temp: 0, + prompt: "I'm going to provide you with a question. Based on the question, is the user asking you to 1. Assigns docs with tags(like star / heart etc)/labels, 2. Filter docs, 3. Provide information about a specific doc 4. Provide a specific doc based on a question/information 5. Provide general information 6. Put cards in a specific order. Answer with only the number for 2-6. For number one, provide the number (1) and the appropriate tag", + }, + + subset: { + model: 'gpt-4-turbo', + maxTokens: 1024, + temp: 0, + prompt: "I'm going to give you a list of descriptions. Each one is separated by `======` on either side. Descriptions will vary in length, so make sure to only separate when you see `======`. Based on the question the user asks, provide a subset of the given descriptions that best matches the user's specifications. Make sure each description is only in the list once. Each item should be separated by `======`. Immediately afterward, surrounded by `------` on BOTH SIDES, provide some insight into your reasoning in the 2nd person (and mention nothing about the formatting details given in this description). It is VERY important that you format it exactly as described, ensuring the proper number of `=` and `-` (6 of each) and no commas" + }, + + info: { + model: 'gpt-4-turbo', + maxTokens: 1024, + temp: 0, + prompt: "Answer the user's question with a short (<100 word) response. If a particular document is selected I will provide that information (which may help with your response)" + }, + + }; let lastCall = ''; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 1a7c0f6e1..6a81f9125 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -675,7 +675,8 @@ pie title Minerals in my tap water { title: "Time", icon:"hourglass-half", toolTip:"Sort by most recent document creation", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"time", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Type", icon:"eye", toolTip:"Sort by document type", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"docType",funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "AI Sort", icon:"robot", toolTip:"Have Chat GPT sort your cards for you !", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Tags", icon:"bolt", toolTip:"Sort by document's tags", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"tag", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // { title: "AI Sort", icon:"robot", toolTip:"Have Chat GPT sort your cards for you !", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Pile", icon:"layer-group", toolTip:"View the cards as a pile in the free form view !", btnType: ButtonType.ClickButton, expertMode: false, toolType:"pile", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Chat Popup", icon:"lightbulb", toolTip:"Toggle the chat popup's visibility!", width: 45 ,btnType: ButtonType.ToggleButton, expertMode: false, toolType:"toggle-chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, @@ -845,6 +846,9 @@ pie title Minerals in my tap water { title: "Back", icon: "chevron-left", toolTip: "Prev Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, width: 30, scripts: { onClick: 'prevKeyFrame(_readOnly_)'}}, { title: "Num", icon:"", toolTip: "Frame # (click to toggle edit mode)",btnType: ButtonType.TextButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)', buttonText: 'selectedDocs()?.lastElement()?.currentFrame?.toString()'}, width: 20, scripts: { onClick: '{ return curKeyFrame(_readOnly_);}'}}, { title: "Fwd", icon: "chevron-right", toolTip: "Next Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, width: 30, scripts: { onClick: 'nextKeyFrame(_readOnly_)'}}, + + + { title: "Text", icon: "Text", toolTip: "Text functions", subMenu: CurrentUserUtils.textTools(), expertMode: false, toolType:DocumentType.RTF, funcs: { linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available { title: "Ink", icon: "Ink", toolTip: "Ink functions", subMenu: CurrentUserUtils.inkTools(), expertMode: false, toolType:DocumentType.INK, funcs: {hidden: `IsExploreMode()`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`}, scripts: { onClick: 'setInkToolDefaults()'} }, // Always available { title: "Doc", icon: "Doc", toolTip: "Freeform Doc tools", subMenu: CurrentUserUtils.freeTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode, true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available @@ -863,6 +867,13 @@ pie title Minerals in my tap water // { title: "Visibility", icon:"Visibility", toolTip:"Filter stars", width: 80, subMenu: this.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("star", true)`, width: 100, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // // { title: "Custom", icon:"cloud", toolTip:"Add Idea labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"idea", funcs: {hidden:`showFreeform ("idea", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // { title: "Visibility", icon:"Visibility", toolTip:"Filter ideas", width: 80, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`,width: 100, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, + + { title: "Card", icon: "Card", toolTip: "Card View Tools", subMenu: CurrentUserUtils.cardTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available + // { title: "Create", icon: "Create", toolTip: "Assign card labels", subMenu: CurrentUserUtils.labelTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available + { title: "Web", icon: "Web", toolTip: "Web functions", subMenu: CurrentUserUtils.webTools(), expertMode: false, toolType:DocumentType.WEB, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when Web is selected + { title: "Video", icon: "Video", toolTip: "Video functions", subMenu: CurrentUserUtils.videoTools(), expertMode: false, toolType:DocumentType.VID, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when video is selected + { title: "Image", icon: "Image", toolTip: "Image functions", subMenu: CurrentUserUtils.imageTools(), expertMode: false, toolType:DocumentType.IMG, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when image is selected + { title: "Schema", icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(),expertMode: false,toolType:CollectionViewType.Schema,funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when Schema is selected { title: "Filter", icon:"=", toolTip:"Filter cards by tags", btnType: ButtonType.MultiToggleButton, width: 150, ignoreClick: true,toolType:DocumentType.COL, subMenu: this.tagGroupTools(), funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, // [ @@ -873,13 +884,8 @@ pie title Minerals in my tap water // ] }, - { title: "Card", icon: "Card", toolTip: "Card View Tools", subMenu: CurrentUserUtils.cardTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available - // { title: "Create", icon: "Create", toolTip: "Assign card labels", subMenu: CurrentUserUtils.labelTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available - { title: "Web", icon: "Web", toolTip: "Web functions", subMenu: CurrentUserUtils.webTools(), expertMode: false, toolType:DocumentType.WEB, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when Web is selected - { title: "Video", icon: "Video", toolTip: "Video functions", subMenu: CurrentUserUtils.videoTools(), expertMode: false, toolType:DocumentType.VID, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when video is selected - { title: "Image", icon: "Image", toolTip: "Image functions", subMenu: CurrentUserUtils.imageTools(), expertMode: false, toolType:DocumentType.IMG, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when image is selected - { title: "Schema", icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(),expertMode: false,toolType:CollectionViewType.Schema,funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when Schema is selected ]; + } /// initializes a context menu button for the top bar context menu diff --git a/src/client/views/FilterPanel.scss b/src/client/views/FilterPanel.scss index 0b9076f3b..34c3d2fc1 100644 --- a/src/client/views/FilterPanel.scss +++ b/src/client/views/FilterPanel.scss @@ -283,6 +283,8 @@ .hotkey-title{ top: 6px; position: relative; + cursor: text; + } .hotkey-title-input{ @@ -290,6 +292,8 @@ border: none; border-color: transparent; outline: none; + cursor: text; + } } @@ -344,6 +348,20 @@ +} + +.drawing-box{ + position: absolute; + z-index: 10000; + border-color: black; + border-style: solid; + border-width: medium; + border-radius: 10%; + background-color: #323232; + + + + } // .sliderBox-outerDiv { // width: 30%;// width: calc(100% - 14px); // 14px accounts for handles that are at the max value of the slider that would extend outside the box diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 17c5cb173..ca4e4df84 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -51,10 +51,13 @@ interface filterProps { @observer export class FilterPanel extends ObservableReactComponent { @observable _selectedFacetHeaders = new Set(); + public static Instance: FilterPanel; + constructor(props: any) { super(props); makeObservable(this); + FilterPanel.Instance = this; } /** diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 62b79dd5a..a117ff3c3 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -447,13 +447,13 @@ export class InkingStroke extends ViewBoxAnnotatableComponent() }), icon: 'paint-brush', }); - cm?.addItem({ - description: 'Create a hotkey', - event: action(() => { - InkStrokeProperties.Instance._controlButton = !InkStrokeProperties.Instance._controlButton; - }), - icon: 'satellite', - }); + // cm?.addItem({ + // description: 'Create a hotkey', + // event: action(() => { + // InkStrokeProperties.Instance._controlButton = !InkStrokeProperties.Instance._controlButton; + // }), + // icon: 'satellite', + // }); }, }; return ( diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 52f01e239..5dafb1088 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -28,6 +28,8 @@ import { SettingsManager } from '../../util/SettingsManager'; import { Tooltip } from '@mui/material'; import { dropActionType } from '../../util/DropActionTypes'; import { List } from '../../../fields/List'; +import { DocCast } from '../../../fields/Types'; +import { SelectionManager } from '../../util/SelectionManager'; enum cardSortings { Time = 'time', @@ -35,6 +37,7 @@ enum cardSortings { Color = 'color', Custom = 'custom', Chat = 'chat', + Tag = 'tag', None = '', } @observer @@ -91,7 +94,9 @@ export class CollectionCardView extends CollectionSubView() { childPairStringListAndUpdateSortDesc = async () => { const sortDesc = await this.childPairStringList(); // Await the promise to get the string result GPTPopup.Instance.setSortDesc(sortDesc.join()); - GPTPopup.Instance.onSortComplete = (sortResult: string) => this.processGptOutput(sortResult); + GPTPopup.Instance.onSortComplete = (sortResult: string, questionType: string, tag?: string) => this.processGptOutput(sortResult, questionType, tag); + GPTPopup.Instance.onQuizRandom = () => this.quizMode() + }; componentDidMount(): void { @@ -103,9 +108,17 @@ export class CollectionCardView extends CollectionSubView() { }); + // Reaction to cardSort changes this._disposers.sort = reaction( - () => ({ cardSort: this.cardSort }), - ({ cardSort}) => (cardSort === cardSortings.Chat ? this.openChatPopup() : GPTPopup.Instance.setVisible(false)) + () => this.cardSort, + (cardSort) => { + if (cardSort === cardSortings.Chat) { + this.openChatPopup(); + } else { + GPTPopup.Instance.setVisible(false); + } + // Force re-render to see if this resolves the sorting issue + } ); @@ -121,6 +134,7 @@ export class CollectionCardView extends CollectionSubView() { } @computed get cardSort() { + // console.log(StrCast(this.Document.cardSort) as any as cardSortings) return StrCast(this.Document.cardSort) as any as cardSortings; } @@ -151,6 +165,16 @@ export class CollectionCardView extends CollectionSubView() { return regularDocs; } + quizMode () { + + const randomIndex = Math.floor(Math.random() * this.childDocs.length) + console.log('hiiiiiii') + + SelectionManager.DeselectAll() + DocumentView.SelectView(DocumentView.getDocumentView(this.childDocs[randomIndex]), false) + + } + /** @@ -290,13 +314,48 @@ export class CollectionCardView extends CollectionSubView() { }; - @computed get sortedDocs() { + get sortedDocs() { // console.log("hi hi hi") // console.log(this.layoutDoc.cardSort_isDesc + "layoutdoc desc") - console.log(this.cardSort + "card sort") + // console.log(this.cardSort + "card sort") - return this.sort(this.childDocsWithoutLinks, this.cardSort, BoolCast(this.layoutDoc.cardSort_isDesc), this._docDraggedIndex); + return this.sort(this.childDocsWithoutLinks, this.cardSort, BoolCast(this.Document.cardSort_isDesc), this._docDraggedIndex); } + + tagValue(doc: Doc) { + const keys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles); + + const isTagActive = (buttonID: number) => { + return BoolCast(doc[StrCast(Doc.UserDoc()[keys[buttonID]])]); + }; + + let base = ''; + let fraction = ''; + + for (let i = 0; i < keys.length; i++) { + if (isTagActive(i)) { + if (base === '') { + base = i.toString(); // First active tag becomes the base + } else { + fraction += i.toString(); // Subsequent active tags become part of the fraction + } + } + } + + // If no tag was active, return 0 by default + if (base === '') { + return 0; + } + + // Construct the final number by appending the fraction if it exists + const numberString = fraction ? `${base}.${fraction}` : base; + + // Convert the result to a number and return + return Number(numberString); + } + + + /** * Called in the sortedDocsType method. Compares the cards' value in regards to the desired sort type-- earlier cards are move to the * front, latter cards to the back @@ -305,7 +364,8 @@ export class CollectionCardView extends CollectionSubView() { * @param isDesc * @returns */ - sort = (docs: Doc[], sortType: cardSortings, isDesc: boolean, dragIndex: number) => { + @action sort = (docs: Doc[], sortType: cardSortings, isDesc: boolean, dragIndex: number) => { + // console.log('hiiii') // if (sortType === cardSortings.None) return docs; // if(sortType !== cardSortings.None){ @@ -319,12 +379,13 @@ export class CollectionCardView extends CollectionSubView() { case cardSortings.Color: return [ClientUtils.hexToHsv(StrCast(docA.backgroundColor)), ClientUtils.hexToHsv(StrCast(docB.backgroundColor))]; - case cardSortings.Custom: - return [CollectionCardView.getButtonGroup(this.cardSort_customField, docA) ?? 9999, - CollectionCardView.getButtonGroup(this.cardSort_customField, docB) ?? 9999]; + case cardSortings.Tag: + return [this.tagValue(docA) ?? 9999, + this.tagValue(docB) ?? 9999]; case cardSortings.Chat: - return [NumCast(docA.chat) ?? 9999, - NumCast(docB.chat) ?? 9999] + return [NumCast(docA.chatIndex) ?? 9999, + NumCast(docB.chatIndex) ?? 9999] + default: return [StrCast(docA.type), StrCast(docB.type)] @@ -487,12 +548,19 @@ export class CollectionCardView extends CollectionSubView() { * Converts the gpt output into a hashmap that can be used for sorting. lists are seperated by ==== while elements within the list are seperated by ~~~~~~ * @param gptOutput */ - @action processGptOutput = (gptOutput: string) => { + @action processGptOutput = (gptOutput: string, questionType: string, tag?: string) => { console.log("HIIII") console.log(StrCast(this.Document.cardSort) + "cardSort") // Split the string into individual list items const listItems = gptOutput.split('======').filter(item => item.trim() !== ''); + + + if (questionType == '2' || questionType == '4'){ + this.childDocs.forEach(d => { + d['chatFilter'] = false + }) + } // console.log(listItems + " LISTT"); // Debug: print the map contents @@ -509,10 +577,47 @@ export class CollectionCardView extends CollectionSubView() { // console.log("ITEM:", normalizedItem); if (doc) { - doc.chat = index; + switch (questionType){ + case '6': + doc.chatIndex = index + console.log(index) + break + case '1': + const allHotKeys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles) + + let myTag = '' + + if (tag){ + for (let i=0; i< allHotKeys.length; i++){ + if (tag.includes(allHotKeys[i])){ + myTag = StrCast(Doc.UserDoc()[allHotKeys[i]]) + break + } + + else if (tag.includes(StrCast(Doc.UserDoc()[allHotKeys[i]]))){ + myTag = StrCast(Doc.UserDoc()[allHotKeys[i]]) + break + } + } + + if (myTag != ''){ + doc[myTag] = true + } + } + break + case '2': + case '4': + doc['chatFilter'] = true + Doc.setDocFilter(DocCast(this.Document.embedContainer), 'chatFilter', true, 'match'); + break + + + + } } else { console.warn(`No matching document found for item: ${normalizedItem}`); } + }); } @@ -528,100 +633,20 @@ export class CollectionCardView extends CollectionSubView() { const sortDesc = await this.childPairStringList(); // Await the promise to get the string result GPTPopup.Instance.setCardsDoneLoading(true); // Set dataDoneLoading to true after data is loaded GPTPopup.Instance.setSortDesc(sortDesc.join()); - GPTPopup.Instance.onSortComplete = (sortResult: string) => this.processGptOutput(sortResult); - }; - - /** - * Renders the buttons to customize sorting depending on which group the card belongs to and the amount of total groups - * @param doc - * @param cardSort - * @returns - */ - renderButtons = (doc: Doc, cardSort: cardSortings): JSX.Element | null => { - // if (cardSort !== cardSortings.Custom) return null; - - const amButtons = 4 - - // const amButtons = Math.max( - // 4, - // this.childDocs?.reduce((set, d) => { - // if (this.cardSort_customField) { - // set.add(NumCast(d[this.cardSort_customField])); - // } - // return set; - // }, new Set()).size ?? 0 - // ); - - // const activeButtonIndex = CollectionCardView.getButtonGroup(this.cardSort_customField, doc); - - const totalWidth = amButtons * 72 + amButtons * 2 * 5 + 6; - - const iconMap: { [key: number]: any } = { - 0: 'star', - 1: 'heart', - 2: 'cloud', - 3: 'bolt' - }; - - return ( -
- {numberRange(amButtons).map(i => ( - Click to add/remove this card from the {iconMap[i]} group
}> - - - ))} - - ); - }; - - /** - * Toggles the buttons between on and off when creating custom sort groupings/changing those created by gpt - * @param childPairIndex - * @param buttonID - * @param doc - */ - toggleButton = undoable((doc: Doc, icon: string) => { - - - - // this.cardSort_customField && (doc[this.cardSort_customField] = buttonID); - - // doc.cardSort_activeIcons = new List() - - - // const list = StrListCast(doc.cardSort_activeIcons); - // doc.cardSort_activeIcons = new List(list.includes(icon) ? list.filter(d => d !== icon) : [...list, icon]); - - BoolCast(doc[icon]) ? doc[icon] = false : doc[icon] = true - - - - // StrListCast(doc.cardSort_activeIcons).push(iconMap[buttonID]) - }, 'toggle card tag'); - - - getButtonIcon = (doc: Doc, icon: any): JSX.Element => { - - // const isActive = StrListCast(doc.cardSort_activeIcons).includes(icon) - const isActive = doc[icon] - - // console.log(StrListCast(doc.cardSort_activeIcons)) - const color = isActive ? '#4476f7' : '#323232'; - - return ; + GPTPopup.Instance.onSortComplete = (sortResult: string, questionType: string, tag?: string) => this.processGptOutput(sortResult, questionType, tag); + GPTPopup.Instance.onQuizRandom = () => this.quizMode() }; /** * Actually renders all the cards */ renderCards = () => { + // console.log('christ') const anySelected = this.childDocs.some(doc => DocumentView.SelectedDocs().includes(doc)); const isEmpty = this.childDocsWithoutLinks.length === 0; const isDesc = BoolCast(this.Document.cardSort_isDesc) - console.log(this.childDocsWithoutLinks.length + "length") + // console.log(this.childDocsWithoutLinks.length + "length") if (isEmpty) { return ( diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index a48e3f9d9..1efcd84e4 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -146,7 +146,7 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' } // prettier-ignore - const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'chat' | 'up' | 'down' | 'pile' | 'toggle-chat', + const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'chat' | 'up' | 'down' | 'pile' | 'toggle-chat' | 'tag', { waitForRender?: boolean; checkResult: (doc: Doc) => any; @@ -193,6 +193,10 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "color", setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort === "color" ? doc.cardSort = '' : doc.cardSort = 'color', }], + ['tag', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "tag", + setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort === "tag" ? doc.cardSort = '' : doc.cardSort = 'tag', + }], // ['heart', { // checkResult: (doc: Doc) => isAttrFiltered('heart'), // setDoc: (doc: Doc, dv: DocumentView) => { @@ -221,16 +225,16 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' // } // }], - ['chat', { - checkResult: (doc: Doc) => { + // ['chat', { + // checkResult: (doc: Doc) => { - if (StrCast(doc?.cardSort) === "chat"){ - return true - }} , - setDoc: (doc: Doc, dv: DocumentView) => { - doc.cardSort === "chat" ? doc.cardSort = '' : doc.cardSort = 'chat'; - }, - }], + // if (StrCast(doc?.cardSort) === "chat"){ + // return true + // }} , + // setDoc: (doc: Doc, dv: DocumentView) => { + // doc.cardSort === "chat" ? doc.cardSort = '' : doc.cardSort = 'chat'; + // }, + // }], ['up', { checkResult: (doc: Doc) => BoolCast(!doc?.cardSort_isDesc), setDoc: (doc: Doc, dv: DocumentView) => { @@ -248,6 +252,8 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' setDoc: (doc: Doc, dv: DocumentView) => { GPTPopup.Instance.setVisible(!GPTPopup.Instance.visible); GPTPopup.Instance.setMode(GPTPopupMode.SORT); + doc.cardSort === "chat" ? doc.cardSort = '' : doc.cardSort = 'chat'; + }, }], diff --git a/src/client/views/nodes/IconTagBox.tsx b/src/client/views/nodes/IconTagBox.tsx index c72d48ef5..8aa6bff2b 100644 --- a/src/client/views/nodes/IconTagBox.tsx +++ b/src/client/views/nodes/IconTagBox.tsx @@ -26,6 +26,9 @@ import { setupMoveUpEvents } from "../../../ClientUtils"; import { returnFalse } from "../../../ClientUtils"; import { emptyFunction } from "../../../Utils"; import { CollectionViewType } from "../../documents/DocumentTypes"; +import { SnappingManager } from "../../util/SnappingManager"; +import { MainView } from "../MainView"; +import { PropertiesView } from "../PropertiesView"; export interface IconTagProps { @@ -129,7 +132,7 @@ export class IconTagBox extends ObservableReactComponent { renderButtons = (doc: Doc): JSX.Element | null => { // if (cardSort !== cardSortings.Custom) return null; - const amButtons = StrListCast(Doc.UserDoc().myFilterHotKeyTitles).length + const amButtons = (StrListCast(Doc.UserDoc().myFilterHotKeyTitles).length) + 1 const keys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles) @@ -146,7 +149,7 @@ export class IconTagBox extends ObservableReactComponent { // const activeButtonIndex = CollectionCardView.getButtonGroup(this.cardSort_customField, doc); - const totalWidth = amButtons * 35 + amButtons * 2 * 5 + 6; + const totalWidth = (amButtons -1) * 35 + (amButtons -1) * 2 * 5 + 6; const iconMap = (buttonID: number) => { return StrCast(Doc.UserDoc()[keys[buttonID]]) @@ -169,17 +172,31 @@ export class IconTagBox extends ObservableReactComponent { fontSize: '50px' }} > - {numberRange(amButtons).map(i => ( + {numberRange(amButtons-1).map(i => ( Click to add/remove this card from the {iconMap(i)} group}> ))} + + {/* Click to customize these icons}> + + */} ); }; + openHotKeyMenu = () => { + SnappingManager.PropertiesWidth < 5 && SnappingManager.SetPropertiesWidth(0); + SnappingManager.SetPropertiesWidth(MainView.Instance.propertiesWidth() < 15 ? Math.min(MainView.Instance._dashUIWidth - 50, 250) : 0); + + PropertiesView.Instance.CloseAll() + PropertiesView.Instance.openFilters = true + } + /** * Toggles the buttons between on and off when creating custom sort groupings/changing those created by gpt * @param childPairIndex diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.scss b/src/client/views/pdf/GPTPopup/GPTPopup.scss index eaa3eaebf..1defd1a7f 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.scss +++ b/src/client/views/pdf/GPTPopup/GPTPopup.scss @@ -78,15 +78,63 @@ $highlightedText: #82e0ff; align-items: center; flex-direction: column; - transform: translateY(30px); + .inputWrapper{ + display: flex; + justify-content: center; + align-items: center; + height: 60px; + position: absolute; + bottom: 0; + width: 100%; + background-color: white; + + } .searchBox-input{ - transform: translateY(-15px); - height: 50px; + height: 40px; border-radius: 10px; + position: absolute; + bottom: 10px; border-color: #5b97ff; + width: 90% + } + + .chat-wrapper { + display: flex; + flex-direction: column; + width: 100%; + max-height: calc(100vh - 80px); /* Height minus the input box and some padding */ + overflow-y: auto; + padding-bottom: 60px; /* Space for the input */ + } + + .chat-bubbles { + margin-top: 20px; + display: flex; + flex-direction: column; + flex-grow: 1; + } + + .chat-bubble { + padding: 10px; + margin-bottom: 10px; + border-radius: 10px; + max-width: 60%; } + + .user-message { + background-color: #283d53; + align-self: flex-end; + color: whitesmoke; + } + + .chat-message { + background-color: #367ae7; + align-self: flex-start; + color:whitesmoke; + } + @@ -98,6 +146,8 @@ $highlightedText: #82e0ff; + + } // button { diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index d216cc421..1b44508d7 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -34,6 +34,13 @@ export enum GPTPopupMode { QUIZ } +export enum GPTQuizType { + CURRENT = 0, + CHOOSE = 1, + MULTIPLE = 2 + +} + @@ -151,7 +158,8 @@ export class GPTPopup extends ObservableReactComponent { this.sortDesc = t; }; - @observable onSortComplete?: (sortResult: string) => void; + @observable onSortComplete?: (sortResult: string, questionType: string, tag?: string) => void; + @observable onQuizRandom?: () => void; @observable cardsDoneLoading = false; @action setCardsDoneLoading(done: boolean) { @@ -165,6 +173,9 @@ export class GPTPopup extends ObservableReactComponent { this.sortRespText = resp } + //mode where gpt says to select a specific card + // + @observable chatSortPrompt: string = "" @@ -179,39 +190,65 @@ export class GPTPopup extends ObservableReactComponent { this.quizAnswer = e.target.value; }); + + @observable correctAnswer: string = '' + @observable setCorrectAnswer = (s: string) => { + this.correctAnswer = s + } + generateQuiz = async () => { this.setLoading(true); this.setSortDone(false); + const quizType = this.quizMode; const selected = DocumentView.SelectedDocs().lastElement(); - const questionText = 'Question: ' + StrCast(selected['gptInputText']); - if (StrCast(selected['gptRubric']) === '') { - const rubricText = 'Rubric: ' + await this.generateRubric(StrCast(selected['gptInputText']), selected) - } + const questionText = 'Question: ' + StrCast(selected['gptInputText']); - const rubricText = 'Rubric: ' + (StrCast(selected['gptRubric'])) - // const rubricText = 'Rubric: ' + StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_0']).text)?.Text); - const queryText = questionText + ' UserAnswer: ' + this.quizAnswer + '. ' + 'Rubric' + rubricText; + if (StrCast(selected['gptRubric']) === '') { + const rubricText = 'Rubric: ' + await this.generateRubric(StrCast(selected['gptInputText']), selected) + } - try { - const res = await gptAPICall(queryText, GPTCallType.QUIZ); - if (!res) { - console.error('GPT call failed'); - return; - } - console.log(res) - this.setQuizResp(res) + const rubricText = 'Rubric: ' + (StrCast(selected['gptRubric'])) + // const rubricText = 'Rubric: ' + StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_0']).text)?.Text); + const queryText = questionText + ' UserAnswer: ' + this.quizAnswer + '. ' + 'Rubric' + rubricText; - this.setLoading(false); - this.setSortDone(true); + try { + const res = await gptAPICall(queryText, GPTCallType.QUIZ); + if (!res) { + console.error('GPT call failed'); + return; + } + console.log(res) + this.setQuizResp(res) + this.conversationArray.push(res) + + this.setLoading(false); + this.setSortDone(true); + + // this._outputValue = res; + } catch (err) { + console.error('GPT call failed'); + } + + + if (this.onQuizRandom){ + this.onQuizRandom() + } - // this._outputValue = res; - } catch (err) { - console.error('GPT call failed'); - } + + + + + // switch(quizType){ + // default: + + // } + + + } @@ -254,11 +291,7 @@ export class GPTPopup extends ObservableReactComponent { } - - /** - * Sorts cards in the CollectionCardDeckView - */ - generateSort = async () => { + generateCard = async () => { console.log(this.chatSortPrompt + "USER PROMPT") this.setLoading(true); this.setSortDone(false); @@ -268,17 +301,50 @@ export class GPTPopup extends ObservableReactComponent { } try { - const res = await gptAPICall(this.sortDesc, GPTCallType.SORT, this.chatSortPrompt); + // const res = await gptAPICall(this.sortDesc, GPTCallType.SORT, this.chatSortPrompt); + const questionType = await gptAPICall(this.chatSortPrompt, GPTCallType.TYPE); + const questionNumber = questionType.split(' ')[0] + console.log(questionType) + 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 res = await gptAPICall(this.sortDesc, GPTCallType.SUBSET, this.chatSortPrompt); // Trigger the callback with the result if (this.onSortComplete) { - this.onSortComplete(res || 'Something went wrong :('); + this.onSortComplete(res || 'Something went wrong :(', questionNumber, questionType.split(' ').slice(1).join(' ')); + + let explanation = res + + if (questionType != '5' && questionType != '3'){ // Extract explanation surrounded by ------ at the top or both at the top and bottom const explanationMatch = res.match(/------\s*([\s\S]*?)\s*(?:------|$)/) || []; - const explanation = explanationMatch[1] ? explanationMatch[1].trim() : 'No explanation found'; + explanation = explanationMatch[1] ? explanationMatch[1].trim() : 'No explanation found'; + } // Set the extracted explanation to sortRespText this.setSortRespText(explanation); + this.conversationArray.push(this.sortRespText) + this.scrollToBottom() console.log(res); } @@ -289,6 +355,43 @@ export class GPTPopup extends ObservableReactComponent { this.setLoading(false); this.setSortDone(true); }; + + + // /** + // * Sorts cards in the CollectionCardDeckView + // */ + // generateSort = async () => { + // console.log(this.chatSortPrompt + "USER PROMPT") + // this.setLoading(true); + // this.setSortDone(false); + + // if (this.regenerateCallback) { + // await this.regenerateCallback(); + // } + + // try { + // const res = await gptAPICall(this.sortDesc, GPTCallType.SORT, this.chatSortPrompt); + + // // Trigger the callback with the result + // if (this.onSortComplete) { + // this.onSortComplete(res || 'Something went wrong :('); + + // // Extract explanation surrounded by ------ at the top or both at the top and bottom + // const explanationMatch = res.match(/------\s*([\s\S]*?)\s*(?:------|$)/) || []; + // const explanation = explanationMatch[1] ? explanationMatch[1].trim() : 'No explanation found'; + + // // Set the extracted explanation to sortRespText + // this.setSortRespText(explanation); + + // console.log(res); + // } + // } catch (err) { + // console.error(err); + // } + + // this.setLoading(false); + // this.setSortDone(true); + // }; /** @@ -422,19 +525,40 @@ export class GPTPopup extends ObservableReactComponent { super(props); makeObservable(this); GPTPopup.Instance = this; + this.messagesEndRef = React.createRef(); + } + private messagesEndRef: React.RefObject; + + + scrollToBottom = () => { + setTimeout(() => { + // Code to execute after 1 second (1000 ms) + if (this.messagesEndRef.current) { + + this.messagesEndRef.current.scrollIntoView({ behavior: 'smooth', block: 'end' }); + } + + }, 50); + } + componentDidUpdate = () => { if (this.loading) { this.setDone(false); } }; + @observable quizMode : GPTQuizType = GPTQuizType.CURRENT + @action setQuizMode (g: GPTQuizType) { + this.quizMode = g + } + cardMenu = () => (
) + + @observable conversationArray: string[] = ["Hi! In this pop up, you can ask ChatGPT questions about your documents and filter / sort them. If you're not sure if something is possible-- just ask!"] + + + handleKeyPress = async (e: React.KeyboardEvent, isSort: boolean) => { + if (e.key === 'Enter') { + e.stopPropagation(); + + if (isSort) { + this.conversationArray.push(this.chatSortPrompt); + await this.generateCard(); + this.chatSortPrompt = '' + + } else { + this.conversationArray.push(this.quizAnswer); + await this.generateQuiz(); + this.quizAnswer = '' + + } + + this.scrollToBottom(); + } + } cardActual = (opt: GPTPopupMode) => { const isSort = opt === GPTPopupMode.SORT // if (opt === GPTPopupMode.SORT) { return ( - !this.sortDone ? ( - <> -
+ // !this.sortDone ? ( + // <> +
+ {/* Chat bubble container with scroll */} +
+
+ {this.conversationArray.map((message, index) => ( +
+ {message} +
+ ))} + + {/* Conditional Loading message */} + {(!this.cardsDoneLoading || this.loading) && ( +
+ ... +
+ )} +
+ +
+ +
+ +
{ - if (e.key === 'Enter') { - isSort ? this.generateSort() : this.generateQuiz(); + onKeyDown={(e) => { + this.handleKeyPress(e, isSort) + + } - e.stopPropagation(); - }} + } type="text" - placeholder={`${isSort ? 'How do you want to sort your cards?' : 'Define the selected card?'}`} - id="search-input" - style={{ width: '100%' }} - /> - {/*
-
*/} -
- - ) : ( -
-
-

{this.text === 'Something went wrong :(' ? 'Something went wrong :(' : `${isSort ? this.sortRespText : this.quizRespText}`}

- this.setSortDone(false)} - icon={} - color={StrCast(Doc.UserDoc().userVariantColor)} + placeholder={`${isSort ? 'Have ChatGPT sort, tag, define, or filter your cards for you!' : 'Define the selected card!'}`} />
- ) + + + // + // ) : ( + //
+ //
+ //

{this.text === 'Something went wrong :(' ? 'Something went wrong :(' : `${isSort ? this.sortRespText : this.quizRespText}`}

+ // this.setSortDone(false)} + // icon={} + // color={StrCast(Doc.UserDoc().userVariantColor)} + // /> + //
+ //
+ // ) ); // } else if (opt === GPTPopupMode.QUIZ) { // return ( @@ -563,10 +728,10 @@ export class GPTPopup extends ObservableReactComponent { }; sortBox = () => ( -
+
{this.heading(this.mode === GPTPopupMode.SORT ? 'SORTING' : 'QUIZ')} <> - {!this.cardsDoneLoading || this.loading ? ( + {!this.cardsDoneLoading? (
@@ -737,7 +902,7 @@ export class GPTPopup extends ObservableReactComponent { tooltip="back" icon={} onClick={() => this.mode = GPTPopupMode.CARD} - style = {{right: '-20%'}} + style = {{right: '50px', position: 'absolute'}} /> )} Date: Tue, 10 Sep 2024 14:54:44 -0400 Subject: moved TagsView up into DocumentView so that one row of tags will be visible. fixed setting pixel size of images to resize annotations so they don't appear to change. added vert/horiz centering for stacking views. fixed pres box to not have scroll bars. fixed resizing properties panel. --- src/client/documents/Documents.ts | 3 ++- src/client/util/CurrentUserUtils.ts | 12 ++++++----- src/client/views/MainView.tsx | 8 +++++--- src/client/views/SidebarAnnos.tsx | 1 + src/client/views/StyleProvider.tsx | 2 +- src/client/views/TagsView.tsx | 7 +++++-- .../views/collections/CollectionCalendarView.tsx | 1 + .../views/collections/CollectionStackingView.scss | 7 ++----- .../views/collections/CollectionStackingView.tsx | 13 +++++++++--- .../CollectionStackingViewFieldColumn.tsx | 24 ++++++++++------------ src/client/views/collections/TreeView.tsx | 2 +- .../collectionFreeForm/FaceCollectionBox.tsx | 1 + src/client/views/global/globalScripts.ts | 14 ++++++++----- src/client/views/nodes/DocumentView.scss | 2 +- src/client/views/nodes/FieldView.tsx | 1 + src/client/views/nodes/ImageBox.tsx | 14 +++++++++++-- 16 files changed, 70 insertions(+), 42 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d5a7b0465..fbdf361dd 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -260,6 +260,7 @@ export class DocumentOptions { _layout_noSidebar?: BOOLt = new BoolInfo('whether to display the sidebar toggle button'); layout_boxShadow?: string; // box-shadow css string OR "standard" to use dash standard box shadow layout_maxShown?: NUMt = new NumInfo('maximum number of children to display at one time (see multicolumnview)'); + _layout_dontCenter?: STRt = new StrInfo("whether collections will center their content - values of 'x', 'xy', or 'y'"); _layout_autoHeight?: BOOLt = new BoolInfo('whether document automatically resizes vertically to display contents'); _layout_autoHeightMargins?: NUMt = new NumInfo('Margin heights to be added to the computed auto height of a Doc'); _layout_curPage?: NUMt = new NumInfo('current page of a PDF or other? paginated document', false); @@ -979,7 +980,7 @@ export namespace Docs { } export function StackingDocument(documents: Array, options: DocumentOptions, id?: string, protoId?: string) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _type_collection: CollectionViewType.Stacking }, id, undefined, protoId); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _layout_dontCenter: 'y', ...options, _type_collection: CollectionViewType.Stacking }, id, undefined, protoId); } export function NoteTakingDocument(documents: Array, options: DocumentOptions, id?: string, protoId?: string) { diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index f042f33ce..2014c48e1 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -368,7 +368,7 @@ pie title Minerals in my tap water {key: "Chat", creator: Docs.Create.ChatDocument, opts: { _width: 300, _height: 300, }}, {key: "Header", creator: headerTemplate, opts: { _width: 300, _height: 120, _header_pointerEvents: "all", _header_height: 50, _header_fontSize: 9,_layout_autoHeightMargins: 50, _layout_autoHeight: true, treeView_HideUnrendered: true}}, {key: "ViewSlide", creator: slideView, opts: { _width: 400, _height: 300, _xMargin: 3, _yMargin: 3,}}, - {key: "Trail", creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 30, _type_collection: CollectionViewType.Stacking, dropAction: dropActionType.embed, treeView_HideTitle: true, _layout_fitWidth:true, layout_boxShadow: "0 0" }}, + {key: "Trail", creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 30, _type_collection: CollectionViewType.Stacking, _layout_dontCenter:'xy', dropAction: dropActionType.embed, treeView_HideTitle: true, _layout_fitWidth:true, layout_boxShadow: "0 0" }}, {key: "Tab", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 500, _height: 800, _layout_fitWidth: true, _freeform_backgroundGrid: true, }}, {key: "Slide", creator: opts => Docs.Create.TreeDocument([], opts), opts: { _width: 300, _height: 200, _type_collection: CollectionViewType.Tree, treeView_HasOverlay: true, _text_fontSize: "20px", _layout_autoHeight: true, @@ -477,6 +477,7 @@ pie title Minerals in my tap water const reqdStackOpts:DocumentOptions ={ title: "menuItemPanel", childDragAction: dropActionType.same, layout_boxShadow: "rgba(0,0,0,0)", dontRegisterView: true, ignoreClick: true, + _layout_dontCenter: 'y', _chromeHidden: true, _gridGap: 0, _yMargin: 0, _xMargin: 0, _layout_autoHeight: false, _width: 60, _columnWidth: 60, _lockedPosition: true, isSystem: true, }; return DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.StackingDocument(items??[], opts), reqdStackOpts, menuBtns, { dropConverter: "convertToButtons(dragData)" }); @@ -510,7 +511,7 @@ pie title Minerals in my tap water // doc.myUserBtns = new PrefetchProxy(userBtns); const reqdToolOps:DocumentOptions = { title: "My Tools", isSystem: true, ignoreClick: true, layout_boxShadow: "0 0", - layout_explainer: "This is a palette of documents that can be created.", + layout_explainer: "This is a palette of documents that can be created.", _layout_dontCenter: "y", _layout_showTitle: "title", _width: 500, _yMargin: 20, _lockedPosition: true, _forceActive: true, _dragOnlyWithinContainer: true, layout_hideContextMenu: true, _chromeHidden: true, }; return DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.StackingDocument(items??[], opts), reqdToolOps, [creatorBtns, userBtns]); @@ -663,7 +664,8 @@ pie title Minerals in my tap water } static stackTools(): Button[] { return [ - { title: "Center", icon: "align-center", toolTip: "Center Align Stack", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"center", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform + { title: "V. Align", icon: "pallet", toolTip: "Center Align Stack", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"vcenter", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform + { title: "Center", icon: "align-center", toolTip: "Center Align Stack", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"hcenter", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform ] } static cardTools(): Button[] { @@ -777,8 +779,8 @@ pie title Minerals in my tap water } static imageTools() { return [ - { title: "Pixels",toolTip: "Set Native Pixel Sizze", btnType: ButtonType.ClickButton, icon: "portrait", scripts: { onClick: 'imageSetPixelSize();' }}, - { title: "Rotate",toolTip: "Rotate 90", btnType: ButtonType.ClickButton, icon: "redo-alt", scripts: { onClick: 'imageRotate90();' }}, + { title: "Pixels",toolTip: "Set Native Pixel Size", btnType: ButtonType.ClickButton, icon: "portrait", scripts: { onClick: 'imageSetPixelSize();' }}, + { title: "Rotate",toolTip: "Rotate 90", btnType: ButtonType.ClickButton, icon: "redo-alt", scripts: { onClick: 'imageRotate90();' }}, ]; } static contextMenuTools():Button[] { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 9f1c7da3d..393abea53 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -3,7 +3,7 @@ import { faBuffer, faHireAHelper } from '@fortawesome/free-brands-svg-icons'; import * as far from '@fortawesome/free-regular-svg-icons'; import * as fa from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, configure, makeObservable, observable, reaction, runInAction } from 'mobx'; +import { action, computed, configure, makeObservable, observable, reaction, runInAction, trace } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import ResizeObserver from 'resize-observer-polyfill'; @@ -707,8 +707,8 @@ export class MainView extends ObservableReactComponent { setupMoveUpEvents( this, e, - action(() => { - SnappingManager.SetPropertiesWidth(Math.max(0, this._dashUIWidth - e.clientX)); + action(moveEv => { + SnappingManager.SetPropertiesWidth(Math.max(0, this._dashUIWidth - moveEv.clientX)); return !SnappingManager.PropertiesWidth; }), action(() => { @@ -807,6 +807,7 @@ export class MainView extends ObservableReactComponent { childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} + dontCenter="y" /> ); @@ -832,6 +833,7 @@ export class MainView extends ObservableReactComponent { }; @computed get mainInnerContent() { + trace(); const leftMenuFlyoutWidth = this._leftMenuFlyoutWidth + this.leftMenuWidth(); const width = this.propertiesWidth() + leftMenuFlyoutWidth; return ( diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index 8f0a35df0..dd60bfa65 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -246,6 +246,7 @@ export class SidebarAnnos extends ObservableReactComponent, props: Opt ); }; - const tags = () => props?.DocumentView?.() && CollectionFreeFormDocumentView.from(props.DocumentView()) ? : null; + const tags = () => props?.DocumentView?.() ? : null; return ( <> {paint()} diff --git a/src/client/views/TagsView.tsx b/src/client/views/TagsView.tsx index 65e70e8fc..8047363d9 100644 --- a/src/client/views/TagsView.tsx +++ b/src/client/views/TagsView.tsx @@ -91,7 +91,7 @@ export class TagItem extends ObservableReactComponent { const tagCollection = TagItem.findTagCollectionDoc(tag) ?? TagItem.createTagCollectionDoc(tag); // If the document is of type COLLECTION, make it a smart collection, otherwise, add the tag to the document. - if (doc.type === DocumentType.COL) { + if (doc.type === DocumentType.COL && !doc.annotationOn) { Doc.AddDocToList(tagCollection[DocData], 'collections', doc); // Iterate through the tag Doc collections and add a copy of the document to each collection @@ -257,6 +257,7 @@ export class TagsView extends ObservableReactComponent { super(props); makeObservable(this); } + InsetDist = 25; // how far tag panel is moved up to overlap DocumentView. @observable _panelHeightDirty = 0; @observable _currentInput = ''; @@ -328,7 +329,7 @@ export class TagsView extends ObservableReactComponent { return !this._props.View.Document.showTags ? null : (
r && new ResizeObserver(action(() => (this._props.View.TagPanelHeight = r?.getBoundingClientRect().height ?? 0))).observe(r)} + ref={r => r && new ResizeObserver(action(() => (this._props.View.TagPanelHeight = Math.max(0, (r?.getBoundingClientRect().height ?? 0) - this.InsetDist)))).observe(r)} style={{ transformOrigin: 'top left', maxWidth: `${100 * this.currentScale}%`, @@ -336,6 +337,8 @@ export class TagsView extends ObservableReactComponent { transform: `scale(${1 / this.currentScale})`, backgroundColor: this.isEditing ? Colors.LIGHT_GRAY : Colors.TRANSPARENT, borderColor: this.isEditing ? Colors.BLACK : Colors.TRANSPARENT, + position: 'relative', + top: `calc(-${this.InsetDist} * ${1 / this.currentScale}px)`, }}>
diff --git a/src/client/views/collections/CollectionCalendarView.tsx b/src/client/views/collections/CollectionCalendarView.tsx index 30fd9fc2b..0ea9f8ebc 100644 --- a/src/client/views/collections/CollectionCalendarView.tsx +++ b/src/client/views/collections/CollectionCalendarView.tsx @@ -82,6 +82,7 @@ export class CollectionCalendarView extends CollectionSubView() { isAnnotationOverlay={false} // select={emptyFunction} What does this mean? isAnyChildContentActive={returnTrue} // ?? + dontCenter="y" // childDocumentsActive={} // whenChildContentsActiveChanged={} childHideDecorationTitle={false} diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 6225cc52a..6400a0a8e 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -54,11 +54,8 @@ } .collectionStackingViewFieldColumn { - height: max-content; - } - - .collectionStackingViewFieldColumnDragging { - height: 100%; + display: flex; + flex-direction: column; } .collectionSchemaView-previewDoc { diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 6402ef16c..2cfe9329a 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -146,7 +146,7 @@ export class CollectionStackingView extends CollectionSubView @@ -343,7 +343,7 @@ export class CollectionStackingView extends CollectionSubView Array.from(this.Sections); // what a section looks like if we're in stacking view sectionStacking = (heading: SchemaHeaderField | undefined, docList: Doc[]) => { @@ -565,6 +571,7 @@ export class CollectionStackingView extends CollectionSubView ); }; diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 5ae08e535..aba6b51d4 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -41,6 +41,7 @@ interface CSVFieldColumnProps { columnWidth: number; numGroupColumns: number; gridGap: number; + dontCenter: 'x' | 'xy' | 'y'; type: 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | undefined; headings: () => object[]; // I think that stacking view actually has a single column and then supposedly you can add more columns? Unsure @@ -345,15 +346,6 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< - {/* {evContents === noValueHeader ? null : ( -
- - - -
- )} */}
{this._props.Document._columnsHideIfEmpty ? null : headingView} {this.collapsed ? null : ( -
+
headings.indexOf(i) === idx); return (
{ }; docTransform = () => this.refTransform(this._dref?.ContentDiv); getTransform = () => this.refTransform(this._tref.current); - embeddedPanelWidth = () => this._props.panelWidth() / (this.treeView._props.NativeDimScaling?.() || 1); + embeddedPanelWidth = () => this._props.panelWidth() / (this.treeView._props.NativeDimScaling?.() || 1) - 3 /* paddingRight for bullet */; embeddedPanelHeight = () => { const layoutDoc = (temp => temp && Doc.expandTemplateLayout(temp, this.Document))(this.treeView._props.childLayoutTemplate?.()) || this.layoutDoc; return Math.min( diff --git a/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx b/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx index 717081666..f9f6c81ab 100644 --- a/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx +++ b/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx @@ -264,6 +264,7 @@ export class FaceCollectionBox extends ViewBoxBaseComponent() { isContentActive={returnTrue} isAnyChildContentActive={returnTrue} childHideDecorations={true} + dontCenter="y" />
); diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 2c7920bdd..934ed6c3e 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -133,10 +133,10 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { }); // eslint-disable-next-line prefer-arrow-callback -ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' | 'clusters' | 'viewAll' | 'fitOnce', checkResult?: boolean, persist?: boolean) { +ScriptingGlobals.add(function showFreeform(attr: 'hcenter' | 'vcenter' | 'grid' | 'snaplines' | 'clusters' | 'viewAll' | 'fitOnce', checkResult?: boolean, persist?: boolean) { const selected = DocumentView.SelectedDocs().lastElement(); // prettier-ignore - const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'like' | 'star' | 'idea' | 'chat' | '1' | '2' | '3' | '4', + const map: Map<'flashcards' | 'hcenter' | 'vcenter' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'like' | 'star' | 'idea' | 'chat' | '1' | '2' | '3' | '4', { waitForRender?: boolean; checkResult: (doc: Doc) => boolean; @@ -158,9 +158,13 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' else (dv.ComponentView as CollectionFreeFormView)?.fitContentOnce(); }, }], - ['center', { - checkResult: (doc:Doc) => BoolCast(doc?._stacking_alignCenter, false), - setDoc: (doc:Doc) => { doc._stacking_alignCenter = !doc._stacking_alignCenter; }, + ['vcenter', { + checkResult: (doc:Doc) => !StrCast(doc?._layout_dontCenter).includes('y'), + setDoc: (doc:Doc) => { doc._layout_dontCenter = StrCast(doc.layout_dontCenter).includes('y') ? StrCast(doc.layout_dontCenter).replace(/y/,"") : StrCast(doc.layout_dontCenter) + 'y'; }, + }], + ['hcenter', { + checkResult: (doc:Doc) => !StrCast(doc?._layout_dontCenter).includes('x'), + setDoc: (doc:Doc) => { doc._layout_dontCenter = StrCast(doc.layout_dontCenter).includes('x') ? StrCast(doc.layout_dontCenter).replace(/x/,"") : 'x'+ StrCast(doc.layout_dontCenter); }, }], ['clusters', { waitForRender: true, // flags that undo batch should terminate after a re-render giving the script the chance to fire diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index 23dada260..2873b4bba 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -242,7 +242,7 @@ .contentFittingDocumentView { position: relative; - display: flex; + display: block; width: 100%; height: 100%; transition: inherit; diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index dd71fd946..c269c7bcb 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -82,6 +82,7 @@ export interface FieldViewSharedProps { // eslint-disable-next-line no-use-before-define onKey?: (e: React.KeyboardEvent, fieldProps: FieldViewProps) => boolean | undefined; fitWidth?: (doc: Doc) => boolean | undefined; + dontCenter?: 'x' | 'y' | 'xy' | undefined; searchFilterDocs: () => Doc[]; showTitle?: () => string; whenChildContentsActiveChanged: (isActive: boolean) => void; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index d0a7fc6ac..be3525544 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -11,7 +11,7 @@ import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; import { ObjectField } from '../../../fields/ObjectField'; -import { Cast, ImageCast, NumCast, StrCast } from '../../../fields/Types'; +import { Cast, ImageCast, NumCast, RTFCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; import { emptyFunction } from '../../../Utils'; @@ -188,8 +188,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { @undoBatch setNativeSize = action(() => { + const oldnativeWidth = NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']); const nscale = NumCast(this._props.PanelWidth()) * NumCast(this.layoutDoc._freeform_scale, 1); - const nw = nscale / NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']); + const nw = nscale / oldnativeWidth; this.dataDoc[this.fieldKey + '_nativeHeight'] = NumCast(this.dataDoc[this.fieldKey + '_nativeHeight']) * nw; this.dataDoc[this.fieldKey + '_nativeWidth'] = NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']) * nw; this.dataDoc._freeform_panX = nw * NumCast(this.dataDoc._freeform_panX); @@ -198,6 +199,15 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { this.dataDoc._freeform_panX_min = this.dataDoc._freeform_panX_min ? nw * NumCast(this.dataDoc._freeform_panX_min) : undefined; this.dataDoc._freeform_panY_max = this.dataDoc._freeform_panY_max ? nw * NumCast(this.dataDoc._freeform_panY_max) : undefined; this.dataDoc._freeform_panY_min = this.dataDoc._freeform_panY_min ? nw * NumCast(this.dataDoc._freeform_panY_min) : undefined; + const newnativeWidth = NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']); + DocListCast(this.dataDoc[this.annotationKey]).forEach(doc => { + doc.x = (NumCast(doc.x) / oldnativeWidth) * newnativeWidth; + doc.y = (NumCast(doc.y) / oldnativeWidth) * newnativeWidth; + if (!RTFCast(doc[Doc.LayoutFieldKey(doc)])) { + doc.width = (NumCast(doc.width) / oldnativeWidth) * newnativeWidth; + doc.height = (NumCast(doc.height) / oldnativeWidth) * newnativeWidth; + } + }); }); @undoBatch rotate = action(() => { -- cgit v1.2.3-70-g09d2 From 313b3d3e67689b175cdc85426ff6af809d476622 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Tue, 17 Sep 2024 12:55:38 -0400 Subject: done with comments-- pull request --- eslint.config.mjs | 66 +----- package-lock.json | 176 +++++++++------ package.json | 12 +- src/client/apis/gpt/GPT.ts | 8 +- src/client/documents/Documents.ts | 2 - src/client/util/CurrentUserUtils.ts | 79 +------ src/client/util/Scripting.ts | 4 +- src/client/views/FilterPanel.scss | 12 -- src/client/views/FilterPanel.tsx | 145 +++++-------- src/client/views/PropertiesView.tsx | 2 +- src/client/views/StyleProvider.tsx | 6 + .../views/collections/CollectionCardDeckView.tsx | 41 ++-- src/client/views/global/globalScripts.ts | 240 ++------------------- src/client/views/nodes/IconTagBox.tsx | 141 ++---------- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 5 +- src/typings/index.d.ts | 2 +- 16 files changed, 255 insertions(+), 686 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/eslint.config.mjs b/eslint.config.mjs index 619966f20..c69209327 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,57 +1,13 @@ -import pluginJs from '@eslint/js'; -import pluginReactConfig from 'eslint-plugin-react/configs/recommended.js'; -import globals from 'globals'; -import tseslint from 'typescript-eslint'; +import globals from "globals"; +import pluginJs from "@eslint/js"; +import tseslint from "typescript-eslint"; +import pluginReact from "eslint-plugin-react"; -export default [ - { - languageOptions: { globals: { ...globals.browser, ...globals.node } }, - }, - pluginJs.configs.recommended, - ...tseslint.configs.recommended, - { - rules: { - 'node/no-missing-import': 0, - 'no-console': 'off', - 'func-names': 'off', - 'no-process-exit': 'off', - 'object-shorthand': 'off', - 'class-methods-use-this': 'off', - 'single-quote': 'off', - 'max-classes-per-file': 0, - - 'react/jsx-filename-extension': [ - 2, - { - extensions: ['.js', '.jsx', '.ts', '.tsx'], - }, - ], - 'import/prefer-default-export': 'off', - 'no-unused-expressions': 'off', - '@typescript-eslint/no-unused-expressions': 'off', - 'prefer-template': 'off', - 'no-inner-declarations': 'off', - 'no-plusplus': 'off', - 'no-multi-assign': 'off', - 'no-underscore-dangle': 'off', - 'no-nested-ternary': 'off', - 'lines-between-class-members': 'off', - 'no-shadow': 'off', - '@typescript-eslint/no-shadow': 'warn', - 'no-unused-vars': 'off', - '@typescript-eslint/no-unused-vars': 'error', - '@typescript-eslint/no-namespace': 'off', - 'react/destructuring-assignment': 0, - 'prefer-arrow-callback': 'error', - 'no-return-assign': 'error', - 'no-await-in-loop': 'error', - 'no-loop-func': 'error', - 'no-cond-assign': 'error', - 'no-use-before-define': 'error', - 'no-explicit-any': 'error', - 'no-restricted-globals': ['error', 'event'], - }, - }, - pluginReactConfig, -]; +export default [ + {files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"]}, + {languageOptions: { globals: globals.browser }}, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + pluginReact.configs.flat.recommended, +]; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 1e738fcb1..3c9c5c81b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -92,7 +92,7 @@ "D": "^1.0.0", "d3": "^7.8.5", "depcheck": "^1.4.7", - "dotenv": "^16.3.1", + "dotenv": "^16.4.5", "eslint-webpack-plugin": "^4.1.0", "exif": "^0.6.0", "exifr": "^7.1.3", @@ -130,6 +130,7 @@ "image-data-uri": "^2.0.1", "image-size": "^1.0.2", "image-size-stream": "^1.1.0", + "install": "^0.13.0", "is-plain-obj": "^4.1.0", "jimp": "^0.22.10", "jpeg-autorotate": "^9.0.0", @@ -154,7 +155,7 @@ "node-stream-zip": "^1.15.0", "nodemailer": "^6.9.7", "nodemon": "^3.0.2", - "npm": "^10.2.5", + "npm": "^10.8.1", "openai": "^4.26.0", "p-limit": "^6.1.0", "passport": "^0.7.0", @@ -188,6 +189,7 @@ "react-compound-slider": "^3.4.0", "react-datepicker": "^7.3.0", "react-dom": "^18.2.0", + "react-draggable": "^4.4.6", "react-grid-layout": "^1.4.4", "react-icons": "^5.0.1", "react-jsx-parser": "^2.0.0", @@ -246,7 +248,7 @@ "xregexp": "^5.1.1" }, "devDependencies": { - "@eslint/js": "^9.1.1", + "@eslint/js": "^9.10.0", "@types/adm-zip": "^0.5.5", "@types/animejs": "^3.1.12", "@types/archiver": "^6.0.2", @@ -295,9 +297,9 @@ "@types/youtube": "^0.1.0", "chai": "^5.0.0", "cross-env": "^7.0.3", - "eslint": "^9.9.0", - "eslint-plugin-react": "^7.34.1", - "globals": "^15.1.0", + "eslint": "^9.10.0", + "eslint-plugin-react": "^7.36.1", + "globals": "^15.9.0", "jsdom": "^25.0.0", "mocha": "^10.2.0", "prettier": "^3.1.0", @@ -306,7 +308,7 @@ "ts-loader": "^9.5.1", "ts-node": "^10.9.1", "ts-node-dev": "^2.0.0", - "typescript-eslint": "^8.2.0", + "typescript-eslint": "^8.6.0", "webpack-dev-server": "^5.0.4" }, "engines": { @@ -2675,9 +2677,10 @@ } }, "node_modules/@eslint/js": { - "version": "9.9.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz", - "integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==", + "version": "9.10.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz", + "integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==", + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -2690,6 +2693,17 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/plugin-kit": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.1.0.tgz", + "integrity": "sha512-autAXT203ixhqei9xt+qkYOvY8l6LAFIdT2UXc/RPNeUVfqRF1BV94GTJyVPFKT8nFM6MyVJhjLj9E8JWvf5zQ==", + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@ffmpeg/core": { "version": "0.12.6", "resolved": "https://registry.npmjs.org/@ffmpeg/core/-/core-0.12.6.tgz", @@ -9993,16 +10007,17 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.3.0.tgz", - "integrity": "sha512-FLAIn63G5KH+adZosDYiutqkOkYEx0nvcwNNfJAf+c7Ae/H35qWwTYvPZUKFj5AS+WfHG/WJJfWnDnyNUlp8UA==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.6.0.tgz", + "integrity": "sha512-UOaz/wFowmoh2G6Mr9gw60B1mm0MzUtm6Ic8G2yM1Le6gyj5Loi/N+O5mocugRGY+8OeeKmkMmbxNqUCq3B4Sg==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/type-utils": "8.3.0", - "@typescript-eslint/utils": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/type-utils": "8.6.0", + "@typescript-eslint/utils": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -10026,15 +10041,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.3.0.tgz", - "integrity": "sha512-h53RhVyLu6AtpUzVCYLPhZGL5jzTD9fZL+SYf/+hYOx2bDkyQXztXSc4tbvKYHzfMXExMLiL9CWqJmVz6+78IQ==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.6.0.tgz", + "integrity": "sha512-eQcbCuA2Vmw45iGfcyG4y6rS7BhWfz9MQuk409WD47qMM+bKCGQWXxvoOs1DUp+T7UBMTtRTVT+kXr7Sh4O9Ow==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/typescript-estree": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/typescript-estree": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", "debug": "^4.3.4" }, "engines": { @@ -10054,13 +10070,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.3.0.tgz", - "integrity": "sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.6.0.tgz", + "integrity": "sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0" + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -10071,13 +10088,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.3.0.tgz", - "integrity": "sha512-wrV6qh//nLbfXZQoj32EXKmwHf4b7L+xXLrP3FZ0GOUU72gSvLjeWUl5J5Ue5IwRxIV1TfF73j/eaBapxx99Lg==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.6.0.tgz", + "integrity": "sha512-dtePl4gsuenXVwC7dVNlb4mGDcKjDT/Ropsk4za/ouMBPplCLyznIaR+W65mvCvsyS97dymoBRrioEXI7k0XIg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.3.0", - "@typescript-eslint/utils": "8.3.0", + "@typescript-eslint/typescript-estree": "8.6.0", + "@typescript-eslint/utils": "8.6.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -10095,10 +10113,11 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.3.0.tgz", - "integrity": "sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz", + "integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -10108,13 +10127,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.3.0.tgz", - "integrity": "sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz", + "integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -10140,6 +10160,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -10155,6 +10176,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -10163,15 +10185,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.3.0.tgz", - "integrity": "sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.6.0.tgz", + "integrity": "sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/typescript-estree": "8.3.0" + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/typescript-estree": "8.6.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -10185,12 +10208,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.3.0.tgz", - "integrity": "sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz", + "integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.3.0", + "@typescript-eslint/types": "8.6.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -10206,6 +10230,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -17448,15 +17473,17 @@ } }, "node_modules/eslint": { - "version": "9.9.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz", - "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==", + "version": "9.10.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.10.0.tgz", + "integrity": "sha512-Y4D0IgtBZfOcOUAIQTSXBKoNGfY0REGqHJG6+Q81vNippW5YlKjHFj4soMxamKK1NXHUWuBZTLdU3Km+L/pcHw==", + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.18.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.9.1", + "@eslint/js": "9.10.0", + "@eslint/plugin-kit": "^0.1.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", @@ -17479,7 +17506,6 @@ "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", @@ -17506,10 +17532,11 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.35.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", - "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", + "version": "7.36.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.36.1.tgz", + "integrity": "sha512-/qwbqNXZoq+VP30s1d4Nc1C5GTxjJQjk4Jzs4Wq2qzxFM7dSmuG2UkIjg2USMLh3A/aVcUNrK7v0J5U1XEGGwA==", "dev": true, + "license": "MIT", "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", @@ -18101,6 +18128,7 @@ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -18117,6 +18145,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -19305,6 +19334,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -19458,7 +19488,8 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/grid-index": { "version": "1.1.0", @@ -20727,6 +20758,14 @@ "inspect-function": "^0.3.1" } }, + "node_modules/install": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/install/-/install-0.13.0.tgz", + "integrity": "sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/internal-slot": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", @@ -27554,6 +27593,7 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -37377,6 +37417,7 @@ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -38075,14 +38116,15 @@ "integrity": "sha512-7sI4e/bZijOzyURng88oOFZCISQPTHozfE2sUu5AviFYk5QV7fYGb6YiDl+vKjF/pICA354JImBImL9XJWUvdQ==" }, "node_modules/typescript-eslint": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.3.0.tgz", - "integrity": "sha512-EvWjwWLwwKDIJuBjk2I6UkV8KEQcwZ0VM10nR1rIunRDIP67QJTZAHBXTX0HW/oI1H10YESF8yWie8fRQxjvFA==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.6.0.tgz", + "integrity": "sha512-eEhhlxCEpCd4helh3AO1hk0UP2MvbRi9CtIAJTVPQjuSXOOO2jsEacNi4UdcJzZJbeuVg1gMhtZ8UYb+NFYPrA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.3.0", - "@typescript-eslint/parser": "8.3.0", - "@typescript-eslint/utils": "8.3.0" + "@typescript-eslint/eslint-plugin": "8.6.0", + "@typescript-eslint/parser": "8.6.0", + "@typescript-eslint/utils": "8.6.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" diff --git a/package.json b/package.json index cb4633c6d..f92a533a9 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "tsc": "tsc -t es5" }, "devDependencies": { - "@eslint/js": "^9.1.1", + "@eslint/js": "^9.10.0", "@types/adm-zip": "^0.5.5", "@types/animejs": "^3.1.12", "@types/archiver": "^6.0.2", @@ -72,9 +72,9 @@ "@types/youtube": "^0.1.0", "chai": "^5.0.0", "cross-env": "^7.0.3", - "eslint": "^9.9.0", - "eslint-plugin-react": "^7.34.1", - "globals": "^15.1.0", + "eslint": "^9.10.0", + "eslint-plugin-react": "^7.36.1", + "globals": "^15.9.0", "jsdom": "^25.0.0", "mocha": "^10.2.0", "prettier": "^3.1.0", @@ -83,7 +83,7 @@ "ts-loader": "^9.5.1", "ts-node": "^10.9.1", "ts-node-dev": "^2.0.0", - "typescript-eslint": "^8.2.0", + "typescript-eslint": "^8.6.0", "webpack-dev-server": "^5.0.4" }, "dependencies": { @@ -132,7 +132,6 @@ "@types/web": "^0.0.157", "@types/webpack-hot-middleware": "^2.25.9", "@webscopeio/react-textarea-autocomplete": "^4.9.2", - "D": "^1.0.0", "adm-zip": "^0.5.10", "archiver": "^7.0.1", "async": "^3.2.5", @@ -169,6 +168,7 @@ "csv-parser": "^3.0.0", "csv-stringify": "^6.4.4", "csvtojson": "^2.0.10", + "D": "^1.0.0", "d3": "^7.8.5", "depcheck": "^1.4.7", "dotenv": "^16.4.5", diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 0b1a5160c..2657bf12e 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -49,7 +49,6 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { maxTokens: 2048, temp: 0.25, prompt: "The user is going to give you a list of descriptions. Each one is separated by `======` on either side. Descriptions will vary in length, so make sure to only separate when you see `======`. Sort them by the user's specifications. Make sure each description is only in the list once. Each item should be separated by `======`. Immediately afterward, surrounded by `------` on BOTH SIDES, provide some insight into your reasoning for the way you sorted (and mention nothing about the formatting details given in this description). It is VERY important that you format it exactly as described, ensuring the proper number of `=` and `-` (6 of each) and NO commas" - // prompt: "I'm going to give you a list of descriptions. Each one is separated by `======` on either side. Descriptions will vary in length, so make sure to only separate when you see `======`. Sort them into lists by shared content. Make sure each description is in only one list. Each list should be separated by `======` with the elements within it separated by `~~~~~~`. Immediately afterward, surrounded by `------` on BOTH SIDES, provide some insight into your reasoning for the way you sorted. It is VERY important that you format it exactly as described, ensuring the proper number of `=` `~` and `-` (6 of each) and no commas.Try to create around 4 groups, but a little more or less is ok. Also, I may provide some more insight after this colon:" }, describe: { model: 'gpt-4-vision-preview', maxTokens: 2048, temp: 0, prompt: 'Describe these images in 3-5 words' }, chatcard: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'Answer the following question as a short flashcard response. Do not include a label.' }, @@ -64,7 +63,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { model: 'gpt-4-turbo', maxTokens: 1024, temp: 0, - prompt: "BRIEFLY (<75 words) provide a definition for the following term. It will be used as a rubric to evaluate the user's understanding of the topic", + prompt: "BRIEFLY (<25 words) provide a definition for the following term. It will be used as a rubric to evaluate the user's understanding of the topic", }, type: { @@ -106,11 +105,6 @@ const gptAPICall = async (inputTextIn: string, callType: GPTCallType, prompt?: a try { lastCall = inputText; - // const configuration: ClientOptions = { - // apiKey: process.env.OPENAI_KEY, - // dangerouslyAllowBrowser: true, - // }; - const usePrompt = prompt ? prompt + opts.prompt : opts.prompt; const messages: ChatCompletionMessageParam[] = [ { role: 'system', content: usePrompt }, diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 188f07991..83e236cba 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -493,8 +493,6 @@ export class DocumentOptions { // cardSort_visibleSortGroups?: List; // which sorting values are being filtered (shown) cardSort_isDesc?: BOOLt = new BoolInfo('whether the cards are sorted ascending or descending'); // test?: STRt = new StrInfo('testing for filtering') - keywords?: MAPt = new MapInfo('keywords', true); - } export const DocOptions = new DocumentOptions(); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 702d6e6e5..997d5c5a9 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -669,15 +669,10 @@ pie title Minerals in my tap water } static cardTools(): Button[] { return [ - // { btnList: new List(["Time", "Type", "Color", "Chat GPT", "Custom 1", "Custom 2", "Custom 3" ]), - // title: "Sort Type", toolTip: "Card Sort Type", btnType: ButtonType.DropdownList, ignoreClick: true, width: 100, scripts: { script: '{ return setCardSort(value, _readOnly_); }'}}, - // { title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, toolType:"font", ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'}, - // btnList: new List(["Roboto", "Roboto Mono", "Nunito", "Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]) }, { title: "Time", icon:"hourglass-half", toolTip:"Sort by most recent document creation", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"time", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Type", icon:"eye", toolTip:"Sort by document type", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"docType",funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Tags", icon:"bolt", toolTip:"Sort by document's tags", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"tag", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "AI Sort", icon:"robot", toolTip:"Have Chat GPT sort your cards for you !", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Pile", icon:"layer-group", toolTip:"View the cards as a pile in the free form view !", btnType: ButtonType.ClickButton, expertMode: false, toolType:"pile", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Chat Popup", icon:"lightbulb", toolTip:"Toggle the chat popup's visibility!", width: 45 ,btnType: ButtonType.ToggleButton, expertMode: false, toolType:"toggle-chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, @@ -686,62 +681,23 @@ pie title Minerals in my tap water { title: "Ascending", toolTip: "Sort the cards in ascending order", btnType: ButtonType.ToggleButton, icon: "sort-up", toolType:"up", ignoreClick: true, scripts: {onClick: '{ return showFreeform(this.toolType, _readOnly_);}' }}, { title: "Descending", toolTip: "Sort the cards in descending order",btnType: ButtonType.ToggleButton, icon: "sort-down",toolType:"down",ignoreClick: true, scripts: {onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, ]}, - - // { title: "Filter", icon:"Filter", toolTip:"Filter cards by tags", width: 150, subMenu: this.cardGroupTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - - - - - - - // // { title: "AIs", icon:"Visibility", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("robot"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - // // { title: "Custom", icon:"heart", toolTip:"Add Like labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"like", funcs: {hidden:`showFreeform ("like", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "1st", icon:"Visibility", toolTip:"Filter likes", width: 150, subMenu: this.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("like", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - // // { title: "Custom", icon:"star", toolTip:"Add Star labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {hidden:`showFreeform ("star", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "2nd", icon:"Visibility", toolTip:"Filter stars", width: 150, subMenu: this.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("star", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - // // { title: "Custom", icon:"cloud", toolTip:"Add Idea labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"idea", funcs: {hidden:`showFreeform ("idea", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "3rd", icon:"Visibility", toolTip:"Filter ideas", width: 150, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, ] } - // static labelTools(): Button[] { - // return [ - // // { title: "Smart", icon:"robot", toolTip:"Have ChatGPT Label and sort your cards for you!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {hidden:`showFreeform ("chat", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "AIs", icon:"AI Sort", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("robot"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - // // { title: "Custom", icon:"heart", toolTip:"Add Like labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"like", funcs: {hidden:`showFreeform ("like", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "1st", icon:"1st", toolTip:"Filter likes", width: 10, subMenu: this.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("like", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - // // { title: "Custom", icon:"star", toolTip:"Add Star labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {hidden:`showFreeform ("star", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "2nd", icon:"2nd", toolTip:"Filter stars", width: 80, subMenu: this.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("star", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - // // { title: "Custom", icon:"cloud", toolTip:"Add Idea labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"idea", funcs: {hidden:`showFreeform ("idea", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "3rd", icon:"3rd", toolTip:"Filter ideas", width: 80, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - // ] - // } + static tagGroupTools(): Button[] { - if (!Doc.UserDoc().activeDashboard){ - Doc.UserDoc().myFilterHotKeyTitles = new List(['Star', 'Heart', 'Bolt', 'Cloud' ]) - - Doc.UserDoc()['Star'] = 'star' - Doc.UserDoc()['Heart'] = 'heart' - Doc.UserDoc()['Bolt'] = 'bolt' - Doc.UserDoc()['Cloud'] = 'cloud' + if (!Doc.UserDoc().activeDashboard) { + Doc.UserDoc().myFilterHotKeyTitles = new List(['Star', 'Heart', 'Bolt', 'Cloud']); - } - - + ['Star', 'Heart', 'Bolt', 'Cloud'].forEach(key => { + Doc.UserDoc()[key] = key.toLowerCase(); + }); +} // hack: if there's no dashboard, create default filters. otherwise, just make sure that the Options button is preserved return (Doc.UserDoc().activeDashboard ? [] : [ { title: "Star", isSystem: false, icon: "star", toolTip:"Click to toggle the star group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, { title: "Heart", isSystem: false,icon: "heart", toolTip:"Click to toggle the heart group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"heart", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, { title: "Bolt", isSystem: false,icon: "bolt", toolTip:"Click to toggle the bolt group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"bolt", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, { title: "Cloud", isSystem: false,icon: "cloud", toolTip:"Click to toggle the cloud group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"cloud", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, - - - // { title: "Group 1", icon, toolTip:"Click to toggle group 1's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"1", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "Group 2", icon, toolTip:"Click to toggle group 2's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"2", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "Group 3", icon, toolTip:"Click to toggle group 3's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"3", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "Group 4", icon, toolTip:"Click to toggle group 4's visibility", btnType: ButtonType.ToggleButton, width: 40, expertMode: false, toolType:"4", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "", icon, toolTip:"Click to toggle group 5's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"5", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "", icon, toolTip:"Click to toggle group 6's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"6", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "", icon, toolTip:"Click to toggle group 7's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"7", funcs: {hidden:`!cardHasLabel(this.toolType)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, ]).concat([ { title: "Options", isSystem: true,icon: "gear", toolTip:"Click to customize your filter panel", btnType: ButtonType.ClickButton, expertMode: false, toolType:"opts", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}} ]) @@ -856,19 +812,6 @@ pie title Minerals in my tap water { title: "View", icon: "View", toolTip: "View tools", subMenu: CurrentUserUtils.viewTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available { title: "Stack", icon: "View", toolTip: "Stacking tools", subMenu: CurrentUserUtils.stackTools(), expertMode: false, toolType:CollectionViewType.Stacking, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available - - // { title: "SortType", btnList: new List(["Time", "Type", "Color", "ChatGPT", "Custom 1", "Custom 2", "Custom 3" ]), - // toolTip: "Card Sort Type", btnType: ButtonType.DropdownList, ignoreClick: true, width: 100, scripts: { script: '{ return showFreeform(value, _readOnly_); }' }, - // // funcs: {hidden: `!SelectedDocType("card", this.expertMode)`} - // }, - // { title: "Visibility", icon:"Visibility", toolTip:"Filter AI labels", subMenu: this.cardGroupTools("robot"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("chat", true)`, width: 100, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - // // { title: "Custom", icon:"heart", toolTip:"Add Like labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"like", funcs: {hidden:`showFreeform ("like", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "Visibility", icon:"Visibility", toolTip:"Filter likes", width: 10, subMenu: this.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("like", true)`, width: 100, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - // // { title: "Custom", icon:"star", toolTip:"Add Star labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {hidden:`showFreeform ("star", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "Visibility", icon:"Visibility", toolTip:"Filter stars", width: 80, subMenu: this.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("star", true)`, width: 100, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - // // { title: "Custom", icon:"cloud", toolTip:"Add Idea labels", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"idea", funcs: {hidden:`showFreeform ("idea", true)`},scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "Visibility", icon:"Visibility", toolTip:"Filter ideas", width: 80, subMenu: this.cardGroupTools("cloud"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden:`!showFreeform("idea", true)`,width: 100, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, - { title: "Card", icon: "Card", toolTip: "Card View Tools", subMenu: CurrentUserUtils.cardTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available // { title: "Create", icon: "Create", toolTip: "Assign card labels", subMenu: CurrentUserUtils.labelTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available { title: "Web", icon: "Web", toolTip: "Web functions", subMenu: CurrentUserUtils.webTools(), expertMode: false, toolType:DocumentType.WEB, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when Web is selected @@ -877,13 +820,7 @@ pie title Minerals in my tap water { title: "Schema", icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(),expertMode: false,toolType:CollectionViewType.Schema,funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when Schema is selected { title: "Filter", icon:"=", toolTip:"Filter cards by tags", btnType: ButtonType.MultiToggleButton, width: 150, ignoreClick: true,toolType:DocumentType.COL, subMenu: this.tagGroupTools(), funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, - // [ - // { title: "Star", icon: "star", toolTip:"Click to toggle the star group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "Heart", icon: "heart", toolTip:"Click to toggle the heart group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"heart", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "Bolt", icon: "bolt", toolTip:"Click to toggle the bolt group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"bolt", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - // { title: "Cloud", icon: "cloud", toolTip:"Click to toggle the cloud group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"cloud", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - - // ] + }, ]; diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index c63d3d7cb..cb314e3f1 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -1,7 +1,7 @@ // export const ts = (window as any).ts; // import * as typescriptlib from '!!raw-loader!../../../node_modules/typescript/lib/lib.d.ts' // import * as typescriptes5 from '!!raw-loader!../../../node_modules/typescript/lib/lib.es5.d.ts' -import typescriptlib from 'type_decls.d'; +// import typescriptlib from 'type_decls.d'; import * as ts from 'typescript'; import { Doc, FieldType } from '../../fields/Doc'; import { RefField } from '../../fields/RefField'; @@ -248,7 +248,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp const funcScript = `(function(${paramString})${reqTypes} { ${body} })`; host.writeFile('file.ts', funcScript); - if (typecheck) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib); + // if (typecheck) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib); const program = ts.createProgram(['file.ts'], {}, host); const testResult = program.emit(); const outputText = host.readFile('file.js'); diff --git a/src/client/views/FilterPanel.scss b/src/client/views/FilterPanel.scss index 34c3d2fc1..fbdebde0d 100644 --- a/src/client/views/FilterPanel.scss +++ b/src/client/views/FilterPanel.scss @@ -350,19 +350,7 @@ } -.drawing-box{ - position: absolute; - z-index: 10000; - border-color: black; - border-style: solid; - border-width: medium; - border-radius: 10%; - background-color: #323232; - - - -} // .sliderBox-outerDiv { // width: 30%;// width: calc(100% - 14px); // 14px accounts for handles that are at the max value of the slider that would extend outside the box // height: 40; // height: 100%; diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index e15285007..e73d9c2c9 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -11,7 +11,7 @@ import { List } from '../../fields/List'; import { RichTextField } from '../../fields/RichTextField'; import { SearchUtil } from '../util/SearchUtil'; import { SnappingManager } from '../util/SnappingManager'; -import { undoable } from '../util/UndoManager'; +import { undoable, undoBatch } from '../util/UndoManager'; import { FieldsDropdown } from './FieldsDropdown'; import './FilterPanel.scss'; import { DocumentView } from './nodes/DocumentView'; @@ -20,26 +20,14 @@ import { ObservableReactComponent } from './ObservableReactComponent'; import { Button } from '../util/CurrentUserUtils'; import { ButtonType } from './nodes/FontIconBox/FontIconBox'; import { DocCast } from '../../fields/Types'; -// import { Docs } from '../../documents/Documents'; -import { Docs } from '../documents/Documents'; import { CurrentUserUtils } from '../util/CurrentUserUtils'; -import { DocumentOptions } from '../documents/Documents'; -import { DocUtils } from '../documents/DocUtils'; -import { dropActionType } from '../util/DropActionTypes'; -import { Toggle } from 'browndash-components'; -import { SettingsManager } from '../util/SettingsManager'; import { StrCast } from '../../fields/Types'; -import { ToggleType } from 'browndash-components'; -import { MultiToggle } from 'browndash-components'; -import { Type } from 'browndash-components'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { DocData } from '../../fields/DocSymbols'; -import { DocumentType } from '../documents/DocumentTypes'; import { Tooltip } from '@mui/material'; import { useLocalObservable } from 'mobx-react'; import { useRef } from 'react'; import { useEffect } from 'react'; -import { useState } from 'react'; interface filterProps { @@ -242,12 +230,14 @@ export class FilterPanel extends ObservableReactComponent { return nonNumbers / facetValues.length > 0.1 ? facetValues.sort() : facetValues.sort((n1: string, n2: string) => Number(n1) - Number(n2)); }; - addHotkey(hotKey: string) { + /** + * Allows users to add a filter hotkey to the properties panel. Will also update the multitoggle at the top menu and the + * icontags tht are displayed on the documents themselves + * @param hotKey tite of the new hotkey + */ + addHotkey = (hotKey: string) => { const buttons = DocCast(Doc.UserDoc().myContextMenuBtns); const filter = DocCast(buttons.Filter); - const filter2 = DocCast(filter); - const but2 = Doc.UserDoc().myContextMenuBtns; - const newKey: Button = { title: hotKey, @@ -260,15 +250,11 @@ export class FilterPanel extends ObservableReactComponent { scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}' }, }; - // const heyy = [...hi, newKey] - const currHotKeys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles) Doc.UserDoc().myFilterHotKeyTitles = new List(currHotKeys.concat(hotKey)) Doc.UserDoc()[hotKey] = 'bolt' - // Doc.UserDoc()['supppp'] = 'star' - const newBtn = CurrentUserUtils.setupContextMenuBtn(newKey, filter); newBtn.isSystem = newBtn[DocData].isSystem = undefined; @@ -276,32 +262,16 @@ export class FilterPanel extends ObservableReactComponent { const subDocs = DocListCast(filter.data) const opts = subDocs[subDocs.length-1] Doc.AddDocToList(filter, 'data', newBtn, opts, true); - - - - // console.log(filter[DocData].data + 'ok') - // // console.log(filter[DocData][0] + 'help') - // console.log(filter[DocData] + 'good grief') - - // console.log(DocCast(DocCast(filter.data))[0]) - // this.removeHotKey() - - // console.log(DocCast(filter.data) + 'HI') - // console.log(DocListCast(filter.data) + 'WOOOOO') - // console.log(DocCast(filter.data)[0] + 'hm :(') - } - - hotKeyButtons() { + /** + * Renders the newly formed hotkey icon buttons + * @returns the buttons to be rendered + */ + hotKeyButtons = () => { const selected = DocumentView.SelectedDocs().lastElement(); - - // console.log(StrListCast(Doc.UserDoc().myFilterHotKeyTitles) + "hiii") - const hotKeys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles); - - // hotKeys.forEach(l => console.log(l + "render")) // Selecting a button should make it so that the icon on the top filter panel becomes said icon const buttons = hotKeys.map((hotKey, i) => ( @@ -506,6 +476,10 @@ interface HotKeyButtonProps { selected?: Doc } +/** + * Renders the buttons that correspond to each icon tag in the properties view. Allows users to change the icon, + * title, and delete. + */ const HotKeyIconButton: React.FC = observer(({ hotKey, selected}) => { const state = useLocalObservable(() => ({ isActive: false, @@ -534,36 +508,34 @@ const HotKeyIconButton: React.FC = observer(({ hotKey, select const handleClick = () => { state.toggleActive(); - // console.log(state.isActive + "hmmm") }; const hotKeys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles) + const buttons = DocCast(Doc.UserDoc().myContextMenuBtns); + const filter = DocCast(buttons.Filter); + /** + * The doc of the button in the context menu that corresponds to the current hotkey + * @returns + */ const myHotKeyDoc = () => { - const buttons = DocCast(Doc.UserDoc().myContextMenuBtns); - const filter = DocCast(buttons.Filter); const hotKeyDocs = DocListCast(filter.data) return hotKeyDocs.filter(k => StrCast(k.title) === hotKey)[0] } + /** + * Removes a hotkey from list + */ const removeHotKey = () => { - const buttons = DocCast(Doc.UserDoc().myContextMenuBtns); - const filter = DocCast(buttons.Filter); - Doc.RemoveDocFromList(filter, 'data', myHotKeyDoc()); - - - - - // console.log((DocListCast(filter.data)[0].title) + "emmanuel") - - - // console.log(DocCast(filter.data) + 'HI') - // console.log(DocCast(filter.data)[0] + 'hm :(') - } + + /** + * Deselects if the user clicks outside the button + * @param event + */ const handleClickOutside = (event: MouseEvent) => { if (panelRef.current && !panelRef.current.contains(event.target as Node)) { state.deactivate(); @@ -571,23 +543,22 @@ const HotKeyIconButton: React.FC = observer(({ hotKey, select state.stopEditing(); updateFromInput() - - - - // Doc.UserDoc().myFilterHotKeyTitles = new List(hotKeys.map(k => k === hotKey ? state.myHotKey : k)); - // Doc.UserDoc()[state.myHotKey] = StrCast(Doc.UserDoc()[hotKey]) - } } }; - const updateFromInput = () => { - const hi = myHotKeyDoc() + /** + * Updates the list of hotkeys based on the users input. replaces the old title with the new one and then assigns this new + * hotkey with the current icon + */ + const updateFromInput = undoable (() => { + const myDoc = myHotKeyDoc() Doc.UserDoc().myFilterHotKeyTitles = new List(hotKeys.map(k => k === hotKey ? state.myHotKey : k)); Doc.UserDoc()[state.myHotKey] = StrCast(Doc.UserDoc()[hotKey]) - hi.title = state.myHotKey - hi.toolTip = `Click to toggle the ${state.myHotKey}'s group's visibility` - } + Doc.UserDoc()[hotKey] = '' + myDoc.title = state.myHotKey + myDoc.toolTip = `Click to toggle the ${state.myHotKey}'s group's visibility` + }, '') useEffect(() => { @@ -599,31 +570,25 @@ const HotKeyIconButton: React.FC = observer(({ hotKey, select const iconOpts = ['star', 'heart', 'bolt', 'satellite', 'palette', 'robot', 'lightbulb', 'highlighter', 'book', 'chalkboard' ]; + /** + * Panel of icons the user can choose from to represent their tag + */ const iconPanel = iconOpts.map((icon, i) => ( - )); - function isAttrFiltered(attr: string) { - if (selected && selected._childFilters !== undefined && selected.type === DocumentType.COL) { - return StrListCast(selected._childFilters).some(filter => filter.includes(attr)); - } else { - return false; - } - } - + /** + * Actually renders the buttons + */ return ( -
{ e.stopPropagation(); state.startEditing(); @@ -673,20 +638,12 @@ const HotKeyIconButton: React.FC = observer(({ hotKey, select )}
); -}) +}) \ No newline at end of file diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index daa8e1720..e940ba6f9 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -54,7 +54,7 @@ export class PropertiesView extends ObservableReactComponent Doc.toggleLockedPosition(doc), 'toggleBackground'); @@ -368,6 +369,11 @@ export function DefaultStyleProvider(doc: Opt, props: Opt props?.DocumentView?.() && CollectionFreeFormDocumentView.from(props.DocumentView()) ? : null; + const iconTags = () => { + if (doc && doc![DocData].showIconTags) + {return ()} + } + return ( <> {paint()} diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 2390d162c..3d9f28a49 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -23,6 +23,8 @@ import { dropActionType } from '../../util/DropActionTypes'; import { DocCast } from '../../../fields/Types'; import { SelectionManager } from '../../util/SelectionManager'; + + enum cardSortings { Time = 'time', Type = 'type', @@ -32,6 +34,14 @@ enum cardSortings { Tag = 'tag', None = '', } + +/** + * New view type specifically for studying more dynamically. Allows you to reorder docs however you see fit, easily + * sort and filter using presets, and customize your experience with chat gpt. + * + * This file contains code as to how the docs are to be rendered (there place geographically and also in regards to sorting), + * and callback functions for the gpt popup + */ @observer export class CollectionCardView extends CollectionSubView() { private _dropDisposer?: DragManager.DragDropDisposer; @@ -40,10 +50,8 @@ export class CollectionCardView extends CollectionSubView() { private _textToDoc = new Map(); @observable _forceChildXf = false; - // @observable _isLoading = false; @observable _hoveredNodeIndex = -1; @observable _docRefs = new ObservableMap(); - _draggerRef = React.createRef(); @observable _maxRowCount = 10; @observable _docDraggedIndex: number = -1; @observable _isACardBeingDragged: boolean = false; @@ -99,12 +107,12 @@ export class CollectionCardView extends CollectionSubView() { // Reaction to cardSort changes this._disposers.sort = reaction( - () => this.cardSort, - cardSort => { - if (cardSort === cardSortings.Chat) { + () => GPTPopup.Instance.visible, + isVis => { + if (isVis) { this.openChatPopup(); } else { - GPTPopup.Instance.setVisible(false); + this.Document.cardSort = (this.cardSort === cardSortings.Chat) ? '' : this.Document.cardSort; } } ); @@ -296,7 +304,7 @@ export class CollectionCardView extends CollectionSubView() { * @param de drop event * @returns true if a card has been dropped, falls if not */ - onInternalDrop = (e: Event, de: DragManager.DropEvent) => { + onInternalDrop = undoable((e: Event, de: DragManager.DropEvent) => { if (de.complete.docDragData) { this._isACardBeingDragged = false; this._docDraggedIndex = -1; @@ -304,7 +312,7 @@ export class CollectionCardView extends CollectionSubView() { return true; } return false; - }; + }, '' ); get sortedDocs() { return this.sort(this.childDocsWithoutLinks, this.cardSort, BoolCast(this.Document.cardSort_isDesc), this._docDraggedIndex); @@ -511,8 +519,6 @@ export class CollectionCardView extends CollectionSubView() { image[DocData].description = response.trim(); return response; // Return the response from gptImageLabel } catch (error) { - console.log('bad things have happened'); - console.log(error); } return ''; @@ -523,18 +529,22 @@ export class CollectionCardView extends CollectionSubView() { * usable code * @param gptOutput */ - @action processGptOutput = (gptOutput: string, questionType: string, tag?: string) => { - console.log('HIIII'); - console.log(StrCast(this.Document.cardSort) + 'cardSort'); + @action + + processGptOutput = undoable((gptOutput: string, questionType: string, tag?: string) => { // Split the string into individual list items const listItems = gptOutput.split('======').filter(item => item.trim() !== ''); - if (questionType == '2' || questionType == '4') { + if (questionType === '2' || questionType === '4') { this.childDocs.forEach(d => { d['chatFilter'] = false; }); } + if (questionType ==='6'){ + this.Document.cardSort = 'chat' + } + listItems.forEach((item, index) => { const normalizedItem = item.trim(); @@ -545,7 +555,6 @@ export class CollectionCardView extends CollectionSubView() { switch (questionType) { case '6': doc.chatIndex = index; - console.log(index); break; case '1': const allHotKeys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles); @@ -578,7 +587,7 @@ export class CollectionCardView extends CollectionSubView() { console.warn(`No matching document found for item: ${normalizedItem}`); } }); - }; + }, ''); /** diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 8b9f128e0..9e56d313e 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -198,44 +198,6 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "tag", setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort === "tag" ? doc.cardSort = '' : doc.cardSort = 'tag', }], - // ['heart', { - // checkResult: (doc: Doc) => isAttrFiltered('heart'), - // setDoc: (doc: Doc, dv: DocumentView) => { - // isAttrFiltered('heart') ? Doc.setDocFilter(doc, 'heart', true, 'remove') : Doc.setDocFilter(doc, 'heart', true, 'match'); - - // } - // }], - // ['star', { - // checkResult: (doc: Doc) => isAttrFiltered('star'), - - // setDoc: (doc: Doc, dv: DocumentView) => { - // isAttrFiltered('star') ? Doc.setDocFilter(doc, 'star', true, 'remove') : Doc.setDocFilter(doc, 'star', true, 'match'); - // } - // }], - // ['bolt', { - // checkResult: (doc: Doc) => isAttrFiltered('bolt'), - // setDoc: (doc: Doc, dv: DocumentView) => { - // isAttrFiltered('bolt') ? Doc.setDocFilter(doc, 'bolt', true, 'remove') : Doc.setDocFilter(doc, 'bolt', true, 'match'); - - // } - // }], - // ['cloud', { - // checkResult: (doc: Doc) => isAttrFiltered('cloud'), - // setDoc: (doc: Doc, dv: DocumentView) => { - // isAttrFiltered('cloud') ? Doc.setDocFilter(doc, 'cloud', true, 'remove') : Doc.setDocFilter(doc, 'cloud', true, 'match'); - - // } - // }], - // ['chat', { - // checkResult: (doc: Doc) => { - - // if (StrCast(doc?.cardSort) === "chat"){ - // return true - // }} , - // setDoc: (doc: Doc, dv: DocumentView) => { - // doc.cardSort === "chat" ? doc.cardSort = '' : doc.cardSort = 'chat'; - // }, - // }], ['up', { checkResult: (doc: Doc) => BoolCast(!doc?.cardSort_isDesc), setDoc: (doc: Doc, dv: DocumentView) => { @@ -251,10 +213,17 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' ['toggle-chat', { checkResult: (doc: Doc) => GPTPopup.Instance.visible, setDoc: (doc: Doc, dv: DocumentView) => { - GPTPopup.Instance.setVisible(!GPTPopup.Instance.visible); - GPTPopup.Instance.setMode(GPTPopupMode.SORT); - doc.cardSort === "chat" ? doc.cardSort = '' : doc.cardSort = 'chat'; + if (GPTPopup.Instance.visible){ + doc.cardSort = '' + GPTPopup.Instance.setVisible(false); + + } else { + GPTPopup.Instance.setVisible(true); + GPTPopup.Instance.setMode(GPTPopupMode.CARD); + GPTPopup.Instance.setCardsDoneLoading(true); + } + }, }], @@ -293,9 +262,6 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' if (checkResult) { return map.get(attr)?.checkResult(selected); } - const filters = StrListCast(selected._childFilters).concat(StrListCast(selected?._childFiltersByRanges).filter((filter, i) => !(i % 3))); - - // console.log(filters.some(filter => filter.includes('star'))+ "SUOOOOPPP") const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; DocumentView.Selected().map(dv => map.get(attr)?.setDoc(dv.layoutDoc, dv)); @@ -303,7 +269,9 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' return undefined; }); - +/** + * Applies a filter to the selected document (or, if the settins button is pressed, opens the filter panel) + */ ScriptingGlobals.add(function handleTags(value?: any, checkResult?: boolean) { const selected = DocumentView.SelectedDocs().lastElement(); @@ -312,7 +280,7 @@ ScriptingGlobals.add(function handleTags(value?: any, checkResult?: boolean) { } if (checkResult) { - return value=== 'opts' ? PropertiesView.Instance.openFilters : isAttrFiltered(value) + return value=== 'opts' ? PropertiesView.Instance?.openFilters : isAttrFiltered(value) } if (value != 'opts'){ @@ -321,8 +289,7 @@ ScriptingGlobals.add(function handleTags(value?: any, checkResult?: boolean) { else { SnappingManager.PropertiesWidth < 5 && SnappingManager.SetPropertiesWidth(0); SnappingManager.SetPropertiesWidth(MainView.Instance.propertiesWidth() < 15 ? Math.min(MainView.Instance._dashUIWidth - 50, 250) : 0); - - PropertiesView.Instance.CloseAll() + PropertiesView.Instance?.CloseAll() PropertiesView.Instance.openFilters = true } @@ -330,183 +297,6 @@ ScriptingGlobals.add(function handleTags(value?: any, checkResult?: boolean) { return undefined; }, ''); - - -// ScriptingGlobals.add(function cardHasLabel(label: string) { -// const selected = DocumentView.SelectedDocs().lastElement(); -// const labelNum = Number(label) - 1; -// return labelNum < 4 || (selected && DocListCast(selected[Doc.LayoutFieldKey(selected)]).some(doc => doc[StrCast(selected.cardSort_customField)] == labelNum)); -// }, ''); - -// ScriptingGlobals.add(function setCardSort(attr: "Time" | "Type"| "Color"| "ChatGPT"| "Custom 1"| "Custom 2"| "Custom 3", value?: any, checkResult?: boolean) { -// // const editorView = RichTextMenu.Instance?.TextView?.EditorView; -// const selected = DocumentView.SelectedDocs().lastElement(); - -// // prettier-ignore -// const map: Map<"Time" | "Type"| "Color"| "ChatGPT"| "Custom 1"| "Custom 2"| "Custom 3", { checkResult: (doc: Doc) => any; setDoc: (doc: Doc) => void;}> = new Map([ -// ['Time', { - -// checkResult: (doc: Doc) => {StrCast(doc?.cardSort); -// console.log(StrCast(doc?.cardSort + "card sort"))}, -// setDoc: (doc: Doc) => {doc.cardSort = "time" -// console.log("hewwo")} - -// , -// }], -// ['Type', { -// checkResult: (doc: Doc) => StrCast(doc?.cardSort), -// setDoc: (doc: Doc) => doc.cardSort = "type", -// }], -// ['Color', { -// checkResult: (doc: Doc) => StrCast(doc?.cardSort), -// setDoc: (doc: Doc) => doc.cardSort = "color", -// }], -// // ['links', { -// // checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "links", -// // setDoc: (doc: Doc) => doc.cardSort = "links", -// // }], -// ['Custom 1', { -// checkResult: (doc: Doc) => StrCast(doc?.cardSort) + " 1", -// setDoc: (doc: Doc) => { -// doc.cardSort = "custom"; -// doc.cardSort_customField = "like"; -// doc.cardSort_visibleSortGroups = new List(); -// } -// }], -// ['Custom 2', { -// checkResult: (doc: Doc) => StrCast(doc?.cardSort) + " 2", -// setDoc: (doc: Doc) => { -// doc.cardSort = "custom"; -// doc.cardSort_customField = "star"; -// doc.cardSort_visibleSortGroups = new List(); -// } -// }], -// ['Custom 3', { -// checkResult: (doc: Doc) => StrCast(doc?.cardSort) + " 3", -// setDoc: (doc: Doc) => { -// doc.cardSort = "custom"; -// doc.cardSort_customField = "idea"; -// doc.cardSort_visibleSortGroups = new List(); -// } -// }], -// ['ChatGPT', { -// checkResult: (doc: Doc) => StrCast(doc?.cardSort_customField), -// setDoc: (doc: Doc) => { -// doc.cardSort = "custom"; -// doc.cardSort_customField = "chat"; -// doc.cardSort_visibleSortGroups = new List(); -// }, -// }], -// ]); - -// for (let i = 0; i < 8; i++) { -// map.set((i + 1 + '') as any, { -// checkResult: (doc: Doc) => NumListCast(doc?.cardSort_visibleSortGroups).includes(i), -// setDoc: (doc: Doc) => { -// const list = NumListCast(doc.cardSort_visibleSortGroups); -// doc.cardSort_visibleSortGroups = new List(list.includes(i) ? list.filter(d => d !== i) : [...list, i]); -// }, -// }); -// } - -// if (checkResult) { -// console.log(attr + "attricute") -// console.log(map.get(attr)?.checkResult(selected) + "check result") -// return map.get(attr)?.checkResult(selected); -// } - -// console.log(attr + "attricute lol") - -// // const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; -// DocumentView.Selected().map(dv => map.get(attr)?.setDoc(dv.layoutDoc)); -// // setTimeout(() => batch.end(), 100); -// return undefined; - -// // map.get(attr)?.setDoc?.(); -// // return undefined; -// }); - -// ScriptingGlobals.add(function setCardSort(value?: any, checkResult?: boolean) { -// // const editorView = RichTextMenu.Instance?.TextView?.EditorView; -// const selected = DocumentView.SelectedDocs().lastElement(); -// if (checkResult) { -// // console.log(attr + "attricute") -// // console.log(map.get(attr)?.checkResult(selected) + "check result") -// console.log(StrCast(selected?.cardSort) + 'check'); -// const hi = StrCast(selected?.cardSort); -// return StrCast(selected?.cardSortForDropDown) ?? 'Time'; -// } -// function docFields(doc: Doc): void { -// switch (value) { -// case 'Custom 1': -// doc.cardSort_customField = 'like'; -// break; -// case 'Custom 2': -// doc.cardSort_customField = 'star'; -// break; -// case 'Custom 3': -// doc.cardSort_customField = 'idea'; -// break; -// case 'Chat GPT': -// doc.cardSort = 'custom'; -// doc.cardSort_customField = 'chat'; -// break; -// default: -// break; -// } - -// doc.cardSort_visibleSortGroups = new List(); -// } - -// // const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; -// DocumentView.Selected().map(dv => { -// dv.Document.cardSortForDropDown = value; - -// if (value != 'Chat GPT') { -// dv.Document.cardSort = value.trim().split(/\s+/)[0].toLowerCase(); -// } -// docFields(dv.Document); -// }); - -// return undefined; - -// // map.get(attr)?.setDoc?.(); -// // return undefined; -// }); - -// ScriptingGlobals.add(function setCardSortAttr(attr: 'time' | 'docType' | 'color', value: any, checkResult?: boolean) { -// // const editorView = RichTextMenu.Instance?.TextView?.EditorView; -// const selected = SelectionManager.Docs.lastElement(); -// // prettier-ignore -// const map: Map<'time' | 'docType' | 'color', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc, dv:DocumentView) => void;}> = new Map([ -// ['time', { -// checkResult: (doc:Doc) => StrCast(doc?.cardSort), -// setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "time", -// }], -// ['docType', { -// checkResult: (doc:Doc) => StrCast(doc?.cardSort), -// setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "type", -// }], -// ['color', { -// checkResult: (doc:Doc) => StrCast(doc?.cardSort), -// setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "color", -// }], -// // ['custom', { -// // checkResult: () => RichTextMenu.Instance.textAlign, -// // setDoc: () => value && editorView?.state ? RichTextMenu.Instance.align(editorView, editorView.dispatch, value):(Doc.UserDoc().textAlign = value), -// // }] -// // , -// ]); - -// if (checkResult) { -// return map.get(attr)?.checkResult(selected); -// } - -// console.log('hey') -// SelectionManager.Views.map(dv => map.get(attr)?.setDoc(dv.layoutDoc, dv)); -// console.log('success') -// }); - // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highlight' | 'fontSize' | 'alignment', value: string | number, checkResult?: boolean) { const editorView = RichTextMenu.Instance?.TextView?.EditorView; diff --git a/src/client/views/nodes/IconTagBox.tsx b/src/client/views/nodes/IconTagBox.tsx index 8aa6bff2b..370ce51d1 100644 --- a/src/client/views/nodes/IconTagBox.tsx +++ b/src/client/views/nodes/IconTagBox.tsx @@ -1,13 +1,9 @@ import React from "react"; import { observer } from "mobx-react"; import { computed } from "mobx"; - import { ObservableReactComponent } from "../ObservableReactComponent"; import { NumCast } from "../../../fields/Types"; -import { makeObservable } from "mobx"; import { Doc } from "../../../fields/Doc"; -import { Reaction } from "mobx"; -import { reaction } from "mobx"; import { numberRange } from "../../../Utils"; import { Tooltip } from "@mui/material"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -15,16 +11,9 @@ import { undoable } from "../../util/UndoManager"; import { BoolCast } from "../../../fields/Types"; import { DocCast } from "../../../fields/Types"; import './IconTagBox.scss'; -import { AclAdmin, AclAugment, AclEdit, DocData } from '../../../fields/DocSymbols'; +import {DocData } from '../../../fields/DocSymbols'; import { StrListCast } from "../../../fields/Doc"; import { StrCast } from "../../../fields/Types"; -import { DocListCast } from "../../../fields/Doc"; -import { List } from "../../../fields/List"; -import { action } from "mobx"; -import { DragManager } from "../../util/DragManager"; -import { setupMoveUpEvents } from "../../../ClientUtils"; -import { returnFalse } from "../../../ClientUtils"; -import { emptyFunction } from "../../../Utils"; import { CollectionViewType } from "../../documents/DocumentTypes"; import { SnappingManager } from "../../util/SnappingManager"; import { MainView } from "../MainView"; @@ -33,95 +22,28 @@ import { PropertiesView } from "../PropertiesView"; export interface IconTagProps { doc: Doc; - - } +/** + * Renders the icon tags that rest under the document. The icons rendered are determined by the values of + * each icon in the userdoc. + */ @observer export class IconTagBox extends ObservableReactComponent { - private ref: React.RefObject; - private height: number = 0; - - @computed get currentScale() { - // console.log(NumCast((this._props.doc.embedContainer as Doc)?._freeform_scale, 1)) return NumCast((this._props.doc.embedContainer as Doc)?._freeform_scale, 1); } constructor(props: any) { super(props); - makeObservable(this); - this.ref = React.createRef(); } - // 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): void { - // this.height = this.ref.current?.getBoundingClientRect().height ? this.ref.current?.getBoundingClientRect().height : 0; this._props.doc[DocData].tagHeight = 36*this.currentScale; } - // createCollection = () => { - // // Get the documents that contain the keyword. - // const selected = DocListCast(this.getKeywordCollectionDocs()!); - // const newEmbeddings = selected.map(doc => Doc.MakeEmbedding(doc)); - - // // Create a new collection and set up configurations. - // const newCollection = ((doc: Doc) => { - // const docData = doc[DocData]; - // docData.data = new List(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; - - // // Add the collection to the keyword document's list of associated smart collections. - // this._props.keywordDoc.collections = new List([...DocListCast(this._props.keywordDoc.collections), newCollection]); - // newCollection[DocData].data_labels = new List([this._props.keyword]); - // newCollection[DocData][`${this._props.keyword}`] = true; - // newCollection[DocData].showLabels = true; - // 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(); - // } - // }; /** * Renders the buttons to customize sorting depending on which group the card belongs to and the amount of total groups @@ -130,25 +52,10 @@ export class IconTagBox extends ObservableReactComponent { * @returns */ renderButtons = (doc: Doc): JSX.Element | null => { - // if (cardSort !== cardSortings.Custom) return null; - const amButtons = (StrListCast(Doc.UserDoc().myFilterHotKeyTitles).length) + 1 const keys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles) - - - // const amButtons = Math.max( - // 4, - // this.childDocs?.reduce((set, d) => { - // if (this.cardSort_customField) { - // set.add(NumCast(d[this.cardSort_customField])); - // } - // return set; - // }, new Set()).size ?? 0 - // ); - - // const activeButtonIndex = CollectionCardView.getButtonGroup(this.cardSort_customField, doc); - + const totalWidth = (amButtons -1) * 35 + (amButtons -1) * 2 * 5 + 6; const iconMap = (buttonID: number) => { @@ -179,16 +86,14 @@ export class IconTagBox extends ObservableReactComponent { ))} - - {/* Click to customize these icons
}> - - */}
); }; + /** + * Opens the filter panel in the properties menu + */ + openHotKeyMenu = () => { SnappingManager.PropertiesWidth < 5 && SnappingManager.SetPropertiesWidth(0); SnappingManager.SetPropertiesWidth(MainView.Instance.propertiesWidth() < 15 ? Math.min(MainView.Instance._dashUIWidth - 50, 250) : 0); @@ -204,31 +109,19 @@ export class IconTagBox extends ObservableReactComponent { * @param doc */ toggleButton = undoable((doc: Doc, icon: string) => { - - - - // this.cardSort_customField && (doc[this.cardSort_customField] = buttonID); - - // doc.cardSort_activeIcons = new List() - - - // const list = StrListCast(doc.cardSort_activeIcons); - // doc.cardSort_activeIcons = new List(list.includes(icon) ? list.filter(d => d !== icon) : [...list, icon]); - BoolCast(doc[icon]) ? doc[icon] = false : doc[icon] = true - - - // StrListCast(doc.cardSort_activeIcons).push(iconMap[buttonID]) }, 'toggle card tag'); + /** + * Determines whether or not the given icon is active depending on the doc's data + * @param doc + * @param icon + * @returns + */ getButtonIcon = (doc: Doc, icon: any): JSX.Element => { - - // const isActive = StrListCast(doc.cardSort_activeIcons).includes(icon) const isActive = doc[icon] - - // console.log(StrListCast(doc.cardSort_activeIcons)) const color = isActive ? '#4476f7' : '#323232'; return ; @@ -244,8 +137,6 @@ export class IconTagBox extends ObservableReactComponent { } - - } diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index 002e82332..53bedbb65 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -279,7 +279,7 @@ export class GPTPopup extends ObservableReactComponent { } /** - * Generates a response to the user's questoin depending on the type of their question + * Generates a response to the user's question depending on the type of their question */ generateCard = async () => { console.log(this.chatSortPrompt + "USER PROMPT") @@ -798,7 +798,8 @@ export class GPTPopup extends ObservableReactComponent { color={StrCast(SettingsManager.userVariantColor)} tooltip="close" icon={} - onClick={() => this.setVisible(false)} + onClick={() => { + this.setVisible(false)}} /> diff --git a/src/typings/index.d.ts b/src/typings/index.d.ts index bee79a38d..fea88cdcb 100644 --- a/src/typings/index.d.ts +++ b/src/typings/index.d.ts @@ -12,7 +12,7 @@ declare module 'fit-curve'; declare module 'iink-js'; declare module 'pdfjs-dist/web/pdf_viewer'; declare module 'react-jsx-parser'; -declare module 'type_decls.d'; +// declare module 'type_decls.d'; declare module '@react-pdf/renderer' { import * as React from 'react'; -- cgit v1.2.3-70-g09d2 From d95730d904612640184ca6fdc00864b0c81b0c0c Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 18 Sep 2024 20:46:38 -0400 Subject: lots of changes to fix dragging cards, integrate iconTags with other tags, sizing docs when selected to fit window, --- eslint.config.mjs | 1 + src/client/util/CurrentUserUtils.ts | 14 +- src/client/util/DragManager.ts | 3 +- src/client/views/DocumentButtonBar.tsx | 44 ++---- src/client/views/DocumentDecorations.tsx | 4 +- src/client/views/StyleProvider.tsx | 4 - src/client/views/TagsView.tsx | 20 +-- .../views/collections/CollectionCardDeckView.scss | 8 +- .../views/collections/CollectionCardDeckView.tsx | 152 ++++++++++++--------- .../views/collections/CollectionCarouselView.tsx | 1 - .../views/collections/CollectionStackingView.tsx | 3 - src/client/views/collections/CollectionSubView.tsx | 4 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 5 +- src/client/views/nodes/DocumentView.tsx | 5 + src/client/views/nodes/IconTagBox.scss | 24 ++-- src/client/views/nodes/IconTagBox.tsx | 106 +++++++------- .../views/nodes/formattedText/FormattedTextBox.tsx | 1 + src/client/views/search/FaceRecognitionHandler.tsx | 3 +- 18 files changed, 198 insertions(+), 204 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/eslint.config.mjs b/eslint.config.mjs index 8926afd7c..f7063caa5 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -36,6 +36,7 @@ export default [ 'no-multi-assign': 'off', 'no-underscore-dangle': 'off', 'no-nested-ternary': 'off', + 'no-param-reassign': 'error', 'lines-between-class-members': 'off', 'no-shadow': 'off', '@typescript-eslint/no-shadow': 'warn', diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index eee6be937..262916312 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -2,7 +2,7 @@ import { reaction, runInAction } from "mobx"; import * as rp from 'request-promise'; import { ClientUtils, OmitKeys } from "../../ClientUtils"; -import { Doc, DocListCast, DocListCastAsync, FieldType, Opt } from "../../fields/Doc"; +import { Doc, DocListCast, DocListCastAsync, FieldType, Opt, StrListCast } from "../../fields/Doc"; import { DocData } from "../../fields/DocSymbols"; import { InkTool } from "../../fields/InkField"; import { List } from "../../fields/List"; @@ -688,18 +688,18 @@ pie title Minerals in my tap water static tagGroupTools(): Button[] { if (!Doc.UserDoc().activeDashboard) { - Doc.UserDoc().myFilterHotKeyTitles = new List(['Star', 'Heart', 'Bolt', 'Cloud']); + Doc.UserDoc().myFilterHotKeyTitles = new List(['star', 'heart', 'bolt', 'cloud']); - ['Star', 'Heart', 'Bolt', 'Cloud'].forEach(key => { + StrListCast(Doc.UserDoc().myFilterHotKeyTitles).forEach(key => { Doc.UserDoc()[key] = key.toLowerCase(); }); } // hack: if there's no dashboard, create default filters. otherwise, just make sure that the Options button is preserved return (Doc.UserDoc().activeDashboard ? [] : [ - { title: "Star", isSystem: false, icon: "star", toolTip:"Click to toggle the star group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, - { title: "Heart", isSystem: false,icon: "heart", toolTip:"Click to toggle the heart group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"heart", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, - { title: "Bolt", isSystem: false,icon: "bolt", toolTip:"Click to toggle the bolt group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"bolt", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, - { title: "Cloud", isSystem: false,icon: "cloud", toolTip:"Click to toggle the cloud group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"cloud", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, + { title: "star", isSystem: false,icon: "star", toolTip:"Click to toggle the star group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, + { title: "heart", isSystem: false,icon: "heart", toolTip:"Click to toggle the heart group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"heart", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, + { title: "bolt", isSystem: false,icon: "bolt", toolTip:"Click to toggle the bolt group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"bolt", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, + { title: "cloud", isSystem: false,icon: "cloud", toolTip:"Click to toggle the cloud group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"cloud", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, ]).concat([ { title: "Options", isSystem: true,icon: "gear", toolTip:"Click to customize your filter panel", btnType: ButtonType.ClickButton, expertMode: false, toolType:"opts", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}} ]) diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index d55d193cc..81ea840f1 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -29,7 +29,7 @@ import { dropActionType } from './DropActionTypes'; import { SnappingManager } from './SnappingManager'; import { UndoManager } from './UndoManager'; -// eslint-disable-next-line @typescript-eslint/no-var-requires +// eslint-disable-next-line @typescript-eslint/no-require-imports const { contextMenuZindex } = require('../views/global/globalCssVariables.module.scss'); // prettier-ignore /** @@ -101,7 +101,6 @@ export namespace DragManager { // event called when the drag operation results in a drop action export class DropEvent { - // eslint-disable-next-line no-useless-constructor constructor( readonly x: number, readonly y: number, diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 87dd5f45a..32bf67df1 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -9,7 +9,7 @@ import * as React from 'react'; import { FaEdit } from 'react-icons/fa'; import { returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick } from '../../ClientUtils'; import { emptyFunction } from '../../Utils'; -import { Doc } from '../../fields/Doc'; +import { Doc, DocListCast } from '../../fields/Doc'; import { Cast, DocCast } from '../../fields/Types'; import { DocUtils, IsFollowLinkScript } from '../documents/DocUtils'; import { CalendarManager } from '../util/CalendarManager'; @@ -28,7 +28,6 @@ import { DocumentLinksButton } from './nodes/DocumentLinksButton'; import { DocumentView } from './nodes/DocumentView'; import { OpenWhere } from './nodes/OpenWhere'; import { DashFieldView } from './nodes/formattedText/DashFieldView'; -import { DocData } from '../../fields/DocSymbols'; @observer export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (DocumentView | undefined)[]; stack?: unknown }> { @@ -287,44 +286,27 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => ( get keywordButton() { const targetDoc = this.view0?.Document; - const metaBtn = (name: string, icon: IconProp) => { - const tooltip = `Toggle ${name}`; - return ( - {tooltip}
}> -
- { - if (name === 'tags') { - targetDoc && (targetDoc[DocData].showIconTags = !targetDoc[DocData].showIconTags); - } else { - targetDoc && (targetDoc[DocData].showLabels = !targetDoc[DocData].showLabels); - } - }} - /> -
- - ); - }; - return !targetDoc ? null : (
-
+ {/*
{metaBtn('tags', 'star')} {metaBtn('keywords', 'id-card')} -
+
*/} Open keyword menu
}>
{ - // targetDoc[DocData].showIconTags = !targetDoc[DocData].showIconTags; - }}> + onClick={undoable(e => { + const showing = DocumentView.Selected().some(dv => dv.showTags); + DocumentView.Selected().forEach(dv => { + dv.layoutDoc._layout_showTags = !showing; + if (e.shiftKey) + DocListCast(dv.Document[Doc.LayoutFieldKey(dv.Document) + '_annotations']).forEach(doc => { + if (doc.face) doc.hidden = showing; + }); + }); + }, 'show Doc tags')}>
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 5e7908725..2ba96c2a9 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -837,7 +837,7 @@ export class DocumentDecorations extends ObservableReactComponent 1 ? 0 : `${seldocview.Document._layout_showTags ? 4 + seldocview.TagPanelHeight : 4}px`, + top: DocumentView.Selected().length > 1 ? 0 : `${seldocview.showTags ? 4 + seldocview.TagPanelHeight : 4}px`, transform: `translate(${-this._resizeBorderWidth / 2 + 10}px, ${this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `, }}> DocumentView.Selected()} /> @@ -846,7 +846,7 @@ export class DocumentDecorations extends ObservableReactComponent {DocumentView.Selected().length > 1 ? : null} diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index eb434db40..3545afcee 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -9,7 +9,6 @@ import { BsArrowDown, BsArrowDownUp, BsArrowUp } from 'react-icons/bs'; import { FaFilter } from 'react-icons/fa'; import { ClientUtils, DashColor, lightOrDark } from '../../ClientUtils'; import { Doc, Opt, StrListCast } from '../../fields/Doc'; -import { DocData } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; import { ScriptField } from '../../fields/ScriptField'; import { BoolCast, Cast, DocCast, ImageCast, NumCast, ScriptCast, StrCast } from '../../fields/Types'; @@ -22,7 +21,6 @@ import { TreeSort } from './collections/TreeSort'; import { Colors } from './global/globalEnums'; import { DocumentView, DocumentViewProps } from './nodes/DocumentView'; import { FieldViewProps } from './nodes/FieldView'; -import { IconTagBox } from './nodes/IconTagBox'; import { StyleProp } from './StyleProp'; import './StyleProvider.scss'; import { TagsView } from './TagsView'; @@ -366,7 +364,6 @@ export function DefaultStyleProvider(doc: Opt, props: Opt docView?.() ? : null; - const iconTags = () => doc?.[DocData].showIconTags ? : null; return ( <> @@ -375,7 +372,6 @@ export function DefaultStyleProvider(doc: Opt, props: Opt ); } diff --git a/src/client/views/TagsView.tsx b/src/client/views/TagsView.tsx index be2c28185..a678d5580 100644 --- a/src/client/views/TagsView.tsx +++ b/src/client/views/TagsView.tsx @@ -18,6 +18,7 @@ import { ObservableReactComponent } from './ObservableReactComponent'; import './TagsView.scss'; import { DocumentView } from './nodes/DocumentView'; import { FaceRecognitionHandler } from './search/FaceRecognitionHandler'; +import { IconTagBox } from './nodes/IconTagBox'; /** * The TagsView is a metadata input/display panel shown at the bottom of a DocumentView in a freeform collection. @@ -59,7 +60,7 @@ export class TagItem extends ObservableReactComponent { * @param tag tag string * @returns tag collection Doc or undefined */ - public static findTagCollectionDoc = (tag: String) => TagItem.AllTagCollectionDocs.find(doc => doc.title === tag); + public static findTagCollectionDoc = (tag: string) => TagItem.AllTagCollectionDocs.find(doc => doc.title === tag); /** * Creates a Doc that collects Docs with the specified tag / value @@ -148,7 +149,7 @@ export class TagItem extends ObservableReactComponent { private _ref: React.RefObject; - constructor(props: any) { + constructor(props: TagItemProps) { super(props); makeObservable(this); this._ref = React.createRef(); @@ -225,7 +226,7 @@ export class TagItem extends ObservableReactComponent { type="checkbox" onClick={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()} - onChange={undoable(e => (this.doc[metadata] = !this.doc[metadata]), 'metadata toggle')} + onChange={undoable(() => (this.doc[metadata] = !this.doc[metadata]), 'metadata toggle')} checked={this.doc[metadata] as boolean} /> ) : ( @@ -257,7 +258,7 @@ interface TagViewProps { */ @observer export class TagsView extends ObservableReactComponent { - constructor(props: any) { + constructor(props: TagViewProps) { super(props); makeObservable(this); } @@ -271,7 +272,7 @@ export class TagsView extends ObservableReactComponent { componentDidMount() { this._heightDisposer = reaction( () => this.View.screenToContentsTransform(), - xf => { + () => { this._panelHeightDirty = this._panelHeightDirty + 1; } ); @@ -288,7 +289,7 @@ export class TagsView extends ObservableReactComponent { return this._props.Views.length > 1 ? 1 : Math.max(1, 1 / this.View.screenToLocalScale()); } @computed get isEditing() { - return this._isEditing && (this._props.Views.length > 1 || DocumentView.SelectedDocs().includes(this.View.Document)); + return this._isEditing && (this._props.Views.length > 1 || (DocumentView.Selected().length === 1 && DocumentView.Selected().includes(this.View))); } /** @@ -336,7 +337,7 @@ export class TagsView extends ObservableReactComponent { ); this._panelHeightDirty; - return this.View.ComponentView?.isUnstyledView?.() || (!this.View.Document._layout_showTags && this._props.Views.length === 1) ? null : ( + return this.View.ComponentView?.isUnstyledView?.() || (!this.View.showTags && this._props.Views.length === 1) ? null : (
r && new ResizeObserver(action(() => this._props.Views.length === 1 && (this.View.TagPanelHeight = Math.max(0, (r?.getBoundingClientRect().height ?? 0) - this.InsetDist)))).observe(r)} @@ -352,9 +353,10 @@ export class TagsView extends ObservableReactComponent { }}>
- {!tagsList.size && !facesList.size ? null : ( // + {this._props.Views.length === 1 && !this.View.showTags ? null : ( // this.setToEditing(!this._isEditing)} icon={} /> )} + {Array.from(tagsList).map((tag, i) => ( { />
- {TagItem.AllTagCollectionDocs.map((doc, i) => { + {TagItem.AllTagCollectionDocs.map(doc => { const tag = StrCast(doc.title); return ( - - ))} -
- ); - }; /** * Opens the filter panel in the properties menu @@ -93,13 +50,13 @@ export class IconTagBox extends ObservableReactComponent { }; /** - * Toggles the buttons between on and off when creating custom sort groupings/changing those created by gpt - * @param childPairIndex * @param buttonID * @param doc */ - toggleButton = undoable((doc: Doc, icon: string) => { - BoolCast(doc[icon]) ? (doc[icon] = false) : (doc[icon] = true); + setIconTag = undoable((icon: string, state: boolean) => { + this._props.Views.forEach(view => { + view.dataDoc[icon] = state; + }); }, 'toggle card tag'); /** @@ -112,10 +69,43 @@ export class IconTagBox extends ObservableReactComponent { const isActive = doc[icon.toString()]; const color = isActive ? '#4476f7' : '#323232'; - return ; + return ; }; + /** + * Renders the buttons to customize sorting depending on which group the card belongs to and the amount of total groups + */ render() { - return <>{this.renderButtons(this._props.doc)}; + const amButtons = StrListCast(Doc.UserDoc().myFilterHotKeyTitles).length + 1; + + const keys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles); + + const iconMap = (buttonID: number) => { + return StrCast(Doc.UserDoc()[keys[buttonID]]) as IconProp; + }; + const buttons = numberRange(amButtons - 1) + .filter(i => this._props.IsEditing || this.View.Document[iconMap(i).toString()] || (DocumentView.Selected.length === 1 && this.View.IsSelected)) + .map(i => ( + Click to add/remove this card from the {iconMap(i).toString()} group
}> + + + )); + return !buttons.length ? null : ( +
+ {buttons} +
+ ); } } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 343e255dc..e0331a422 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -275,6 +275,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent 1; - imgDocFaceDescriptions.forEach((fd, i) => { + imgDocFaceDescriptions.forEach(fd => { const faceDescriptor = new List(Array.from(fd.descriptor)); const matchedUniqueFace = this.findMatchingFaceDoc(fd.descriptor) ?? this.createUniqueFaceDoc(activeDashboard); const faceAnno = Docs.Create.FreeformDocument([], { -- cgit v1.2.3-70-g09d2 From 3c8af89e3d5370b748fea27c411b3e62758b9a45 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 19 Sep 2024 17:50:48 -0400 Subject: changed backend for filtering buttons to store only one list - the list of icon buttons in Doc.MyFilterHotKeys. --- src/client/util/CurrentUserUtils.ts | 85 +++++++++----------- src/client/views/FilterPanel.tsx | 86 ++++++++++---------- src/client/views/PropertiesView.tsx | 2 +- src/client/views/TagsView.tsx | 55 ++++++------- .../views/collections/CollectionCardDeckView.tsx | 27 +++---- src/client/views/global/globalScripts.ts | 18 +++-- src/client/views/nodes/FontIconBox/FontIconBox.tsx | 4 +- src/client/views/nodes/IconTagBox.tsx | 91 ++++++++-------------- src/fields/Doc.ts | 8 +- 9 files changed, 168 insertions(+), 208 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 262916312..21df0fd3b 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -671,38 +671,33 @@ pie title Minerals in my tap water } static cardTools(): Button[] { return [ - { title: "Time", icon:"hourglass-half", toolTip:"Sort by most recent document creation", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"time", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Type", icon:"eye", toolTip:"Sort by document type", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"docType",funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Tags", icon:"bolt", toolTip:"Sort by document's tags", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"tag", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Pile", icon:"layer-group", toolTip:"View the cards as a pile in the free form view !", btnType: ButtonType.ClickButton, expertMode: false, toolType:"pile", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Chat Popup", icon:"lightbulb", toolTip:"Toggle the chat popup's visibility!", width: 45 ,btnType: ButtonType.ToggleButton, expertMode: false, toolType:"toggle-chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, + { title: "Time", icon:"hourglass-half", toolTip:"Sort by most recent document creation", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"time", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Type", icon:"eye", toolTip:"Sort by document type", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"docType", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Tags", icon:"bolt", toolTip:"Sort by document's tags", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"tag", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Pile", icon:"layer-group", toolTip:"View the cards as a pile in the free form view!",btnType: ButtonType.ClickButton, expertMode: false, toolType:"pile", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Chat Popup",icon:"lightbulb", toolTip:"Toggle the chat popup's visibility!", width: 45, btnType: ButtonType.ToggleButton, expertMode: false, toolType:"toggle-chat",funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, - { title: "Sort", toolTip: "Manage sort order / lock status", icon: "sort" , btnType: ButtonType.MultiToggleButton, toolType:"alignment", ignoreClick: true, + { title: "Sort", icon: "sort" , toolTip: "Manage sort order / lock status", btnType: ButtonType.MultiToggleButton, toolType:"alignment", ignoreClick: true, subMenu: [ - { title: "Ascending", toolTip: "Sort the cards in ascending order", btnType: ButtonType.ToggleButton, icon: "sort-up", toolType:"up", ignoreClick: true, scripts: {onClick: '{ return showFreeform(this.toolType, _readOnly_);}' }}, - { title: "Descending", toolTip: "Sort the cards in descending order",btnType: ButtonType.ToggleButton, icon: "sort-down",toolType:"down",ignoreClick: true, scripts: {onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, + { title: "Ascending", toolTip: "Sort the cards in ascending order", btnType: ButtonType.ToggleButton, icon: "sort-up", toolType:"up", ignoreClick: true, scripts: {onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, + { title: "Descending",toolTip: "Sort the cards in descending order",btnType: ButtonType.ToggleButton, icon: "sort-down",toolType:"down",ignoreClick: true, scripts: {onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, ]}, ] } static tagGroupTools(): Button[] { - if (!Doc.UserDoc().activeDashboard) { - Doc.UserDoc().myFilterHotKeyTitles = new List(['star', 'heart', 'bolt', 'cloud']); - - StrListCast(Doc.UserDoc().myFilterHotKeyTitles).forEach(key => { - Doc.UserDoc()[key] = key.toLowerCase(); - }); -} + 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 handleTags(this.toolType, _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 handleTags(this.toolType, _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 handleTags(this.toolType, _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 handleTags(this.toolType, _readOnly_);}'}}, + ]; // hack: if there's no dashboard, create default filters. otherwise, just make sure that the Options button is preserved - return (Doc.UserDoc().activeDashboard ? [] : [ - { title: "star", isSystem: false,icon: "star", toolTip:"Click to toggle the star group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"star", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, - { title: "heart", isSystem: false,icon: "heart", toolTip:"Click to toggle the heart group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"heart", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, - { title: "bolt", isSystem: false,icon: "bolt", toolTip:"Click to toggle the bolt group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"bolt", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, - { title: "cloud", isSystem: false,icon: "cloud", toolTip:"Click to toggle the cloud group's visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"cloud", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}}, - ]).concat([ - { title: "Options", isSystem: true,icon: "gear", toolTip:"Click to customize your filter panel", btnType: ButtonType.ClickButton, expertMode: false, toolType:"opts", funcs: {}, scripts: { onClick: '{ return handleTags(this.toolType, _readOnly_);}'}} - ]) + 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 handleTags(this.toolType, _readOnly_);}'}}, + ...(Doc.UserDoc().activeDashboard ? [] : defaultTagButtonDescs) + ] } static viewTools(): Button[] { return [ @@ -720,8 +715,8 @@ pie title Minerals in my tap water { title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, toolType:"font", ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'}, btnList: new List(["Roboto", "Roboto Mono", "Nunito", "Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]) }, { title: "Font Size",toolTip: "Font size (%size)", btnType: ButtonType.NumberDropdownButton, toolType:"fontSize", ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'}, numBtnMax: 200, numBtnMin: 6 }, - { title: "Color", toolTip: "Font color (%color)", btnType: ButtonType.ColorButton, icon: "font", toolType:"fontColor",ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'}}, - { title: "Highlight",toolTip: "Font highlight", btnType: ButtonType.ColorButton, icon: "highlighter", toolType:"highlight",ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'}}, + { title: "Color", toolTip: "Font color (%color)", btnType: ButtonType.ColorButton, icon: "font", toolType:"fontColor",ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'} }, + { title: "Highlight",toolTip: "Font highlight", btnType: ButtonType.ColorButton, icon: "highlighter", toolType:"highlight",ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'} }, { title: "Bold", toolTip: "Bold (Ctrl+B)", btnType: ButtonType.ToggleButton, icon: "bold", toolType:"bold", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} }, { title: "Italic", toolTip: "Italic (Ctrl+I)", btnType: ButtonType.ToggleButton, icon: "italic", toolType:"italics", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} }, { title: "Under", toolTip: "Underline (Ctrl+U)", btnType: ButtonType.ToggleButton, icon: "underline", toolType:"underline",ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} }, @@ -730,12 +725,12 @@ pie title Minerals in my tap water { title: "Vcenter", toolTip: "Vertical center", btnType: ButtonType.ToggleButton, icon: "pallet", toolType:"vcent", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} }, { title: "Align", toolTip: "Alignment", btnType: ButtonType.MultiToggleButton, toolType:"alignment", ignoreClick: true, subMenu: [ - { title: "Left", toolTip: "Left align (Cmd-[)", btnType: ButtonType.ToggleButton, icon: "align-left", toolType:"left", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}' }}, + { title: "Left", toolTip: "Left align (Cmd-[)", btnType: ButtonType.ToggleButton, icon: "align-left", toolType:"left", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} }, { title: "Center", toolTip: "Center align (Cmd-\\)",btnType: ButtonType.ToggleButton, icon: "align-center",toolType:"center",ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} }, { title: "Right", toolTip: "Right align (Cmd-])", btnType: ButtonType.ToggleButton, icon: "align-right", toolType:"right", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} }, ]}, - { title: "Elide", toolTip: "Elide selection", btnType: ButtonType.ToggleButton, icon: "eye", toolType:"elide", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'}}, - { title: "Dictate", toolTip: "Dictate", btnType: ButtonType.ToggleButton, icon: "microphone", toolType:"dictation", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'}}, + { title: "Elide", toolTip: "Elide selection", btnType: ButtonType.ToggleButton, icon: "eye", toolType:"elide", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} }, + { title: "Dictate", toolTip: "Dictate", btnType: ButtonType.ToggleButton, icon: "microphone", toolType:"dictation", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} }, { title: "NoLink", toolTip: "Auto Link", btnType: ButtonType.ToggleButton, icon: "link", toolType:"noAutoLink", expertMode:true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'}, funcs: {hidden: 'IsNoviceMode()'}}, // { title: "Strikethrough", tooltip: "Strikethrough", btnType: ButtonType.ToggleButton, icon: "strikethrough", scripts: {onClick:: 'toggleStrikethrough()'}}, // { title: "Superscript", tooltip: "Superscript", btnType: ButtonType.ToggleButton, icon: "superscript", scripts: {onClick:: 'toggleSuperscript()'}}, @@ -806,26 +801,20 @@ pie title Minerals in my tap water { title: "Num", icon:"", toolTip: "Frame # (click to toggle edit mode)",btnType: ButtonType.TextButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)', buttonText: 'selectedDocs()?.lastElement()?.currentFrame?.toString()'}, width: 20, scripts: { onClick: '{ return curKeyFrame(_readOnly_);}'}}, { title: "Fwd", icon: "chevron-right", toolTip: "Next Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, width: 30, scripts: { onClick: 'nextKeyFrame(_readOnly_)'}}, + { title: "Text", icon: "Text", toolTip: "Text functions", subMenu: CurrentUserUtils.textTools(), expertMode: false, toolType:DocumentType.RTF, funcs: { linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available + { title: "Ink", icon: "Ink", toolTip: "Ink functions", subMenu: CurrentUserUtils.inkTools(), expertMode: false, toolType:DocumentType.INK, funcs: {hidden: `IsExploreMode()`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`}, scripts: { onClick: 'setInkToolDefaults()'} }, // Always available + { title: "Doc", icon: "Doc", toolTip: "Freeform Doc tools", subMenu: CurrentUserUtils.freeTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode, true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available + { title: "View", icon: "View", toolTip: "View tools", subMenu: CurrentUserUtils.viewTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available + { title: "Stack", icon: "View", toolTip: "Stacking tools", subMenu: CurrentUserUtils.stackTools(), expertMode: false, toolType:CollectionViewType.Stacking, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available - - { title: "Text", icon: "Text", toolTip: "Text functions", subMenu: CurrentUserUtils.textTools(), expertMode: false, toolType:DocumentType.RTF, funcs: { linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available - { title: "Ink", icon: "Ink", toolTip: "Ink functions", subMenu: CurrentUserUtils.inkTools(), expertMode: false, toolType:DocumentType.INK, funcs: {hidden: `IsExploreMode()`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`}, scripts: { onClick: 'setInkToolDefaults()'} }, // Always available - { title: "Doc", icon: "Doc", toolTip: "Freeform Doc tools", subMenu: CurrentUserUtils.freeTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode, true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available - { title: "View", icon: "View", toolTip: "View tools", subMenu: CurrentUserUtils.viewTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available - { title: "Stack", icon: "View", toolTip: "Stacking tools", subMenu: CurrentUserUtils.stackTools(), expertMode: false, toolType:CollectionViewType.Stacking, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available - - { title: "Card", icon: "Card", toolTip: "Card View Tools", subMenu: CurrentUserUtils.cardTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available - // { title: "Create", icon: "Create", toolTip: "Assign card labels", subMenu: CurrentUserUtils.labelTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available - { title: "Web", icon: "Web", toolTip: "Web functions", subMenu: CurrentUserUtils.webTools(), expertMode: false, toolType:DocumentType.WEB, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when Web is selected - { title: "Video", icon: "Video", toolTip: "Video functions", subMenu: CurrentUserUtils.videoTools(), expertMode: false, toolType:DocumentType.VID, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when video is selected - { title: "Image", icon: "Image", toolTip: "Image functions", subMenu: CurrentUserUtils.imageTools(), expertMode: false, toolType:DocumentType.IMG, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when image is selected - { title: "Schema", icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(),expertMode: false,toolType:CollectionViewType.Schema,funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when Schema is selected - { title: "Filter", icon:"=", toolTip:"Filter cards by tags", btnType: ButtonType.MultiToggleButton, width: 150, ignoreClick: true,toolType:DocumentType.COL, - subMenu: this.tagGroupTools(), funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, - - }, - ]; - + { title: "Card", icon: "Card", toolTip: "Card View Tools", subMenu: CurrentUserUtils.cardTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available + // { title: "Create", icon: "Create", toolTip: "Assign card labels", subMenu: CurrentUserUtils.labelTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available + { title: "Web", icon: "Web", toolTip: "Web functions", subMenu: CurrentUserUtils.webTools(), expertMode: false, toolType:DocumentType.WEB, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when Web is selected + { title: "Video", icon: "Video", toolTip: "Video functions", subMenu: CurrentUserUtils.videoTools(), expertMode: false, toolType:DocumentType.VID, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when video is selected + { title: "Image", icon: "Image", toolTip: "Image functions", subMenu: CurrentUserUtils.imageTools(), expertMode: false, toolType:DocumentType.IMG, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when image is selected + { title: "Schema", icon: "Schema", toolTip: "Schema functions", subMenu: CurrentUserUtils.schemaTools(), expertMode: false, toolType:CollectionViewType.Schema, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`}, linearBtnWidth:58 }, // Only when Schema is selected + { title: "Filter", icon: "=", toolTip: "Filter cards by tags", subMenu: CurrentUserUtils.tagGroupTools(),ignoreClick:true, toolType:DocumentType.COL, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, btnType: ButtonType.MultiToggleButton, width: 150}, + ]; } /// initializes a context menu button for the top bar context menu diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index b6bea1d4b..a3c8fc383 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -26,7 +26,7 @@ import { ObservableReactComponent } from './ObservableReactComponent'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; interface HotKeyButtonProps { - hotKey: string; + hotKey: Doc; selected?: Doc; } @@ -53,7 +53,7 @@ const HotKeyIconButton: React.FC = observer(({ hotKey /*, sel this.isEditing = false; }, setHotKey(newHotKey: string) { - this.myHotKey = newHotKey; + this.myHotKey.title = newHotKey; }, })); @@ -64,24 +64,13 @@ const HotKeyIconButton: React.FC = observer(({ hotKey /*, sel state.toggleActive(); }; - const hotKeys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles); const buttons = DocCast(Doc.UserDoc().myContextMenuBtns); - const filter = DocCast(buttons.Filter); - - /** - * The doc of the button in the context menu that corresponds to the current hotkey - * @returns - */ - const myHotKeyDoc = () => { - const hotKeyDocs = DocListCast(filter.data); - return hotKeyDocs.filter(k => StrCast(k.title) === hotKey)[0]; - }; /** * Removes a hotkey from list */ const removeHotKey = () => { - Doc.RemoveDocFromList(filter, 'data', myHotKeyDoc()); + Doc.RemFromFilterHotKeys(hotKey); }; /** @@ -89,11 +78,8 @@ const HotKeyIconButton: React.FC = observer(({ hotKey /*, sel * hotkey with the current icon */ const updateFromInput = undoable(() => { - const myDoc = myHotKeyDoc(); - Doc.UserDoc().myFilterHotKeyTitles = new List(hotKeys.map(k => (k === hotKey ? state.myHotKey : k))); - Doc.UserDoc()[state.myHotKey] = StrCast(Doc.UserDoc()[hotKey]); - myDoc.title = state.myHotKey; - myDoc.toolTip = `Click to toggle the ${state.myHotKey}'s group's visibility`; + hotKey.title = StrCast(state.myHotKey.title); + hotKey.toolTip = `Click to toggle the ${StrCast(hotKey.title)}'s group's visibility`; }, ''); /** @@ -123,13 +109,12 @@ const HotKeyIconButton: React.FC = observer(({ hotKey /*, sel /** * Panel of icons the user can choose from to represent their tag */ - const iconPanel = iconOpts.map((icon, i) => ( + const iconPanel = iconOpts.map(icon => ( {state.isActive &&
{iconPanel}
} @@ -166,7 +151,7 @@ const HotKeyIconButton: React.FC = observer(({ hotKey /*, sel state.setHotKey(e.target.value)} onBlur={() => { state.stopEditing(); @@ -181,13 +166,12 @@ const HotKeyIconButton: React.FC = observer(({ hotKey /*, sel className="hotkey-title-input" /> ) : ( -

{hotKey.toUpperCase()}

+

{StrCast(hotKey.title).toUpperCase()}

)}
}> + Click to customize this hotkey's icon
}> )); @@ -561,6 +541,22 @@ export class FilterPanel extends ObservableReactComponent {
); }); + case 'togglebox': + return ( +
+ filter.split(Doc.FilterSep)[0] === 'tags' && filter.split(Doc.FilterSep)[1] === facetHeader) + ?.split(Doc.FilterSep)[2] ?? '' + )} + type={'checkbox'} + onChange={undoable(e => Doc.setDocFilter(this.Document, 'tags', facetHeader, e.target.checked ? 'check' : 'remove'), 'set filter')} + /> + -set- +
+ ); case 'range': { diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index e940ba6f9..f3221d005 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -1176,7 +1176,7 @@ export class PropertiesView extends ObservableReactComponent { this.openFilters = bool; }} onDoubleClick={this.CloseAll}> + { this.openFilters = bool; })} onDoubleClick={this.CloseAll}>
diff --git a/src/client/views/TagsView.tsx b/src/client/views/TagsView.tsx index cae30218c..2f30edb80 100644 --- a/src/client/views/TagsView.tsx +++ b/src/client/views/TagsView.tsx @@ -371,26 +371,20 @@ export class TagsView extends ObservableReactComponent { style={{ width: '8px' }} tooltip="Close Menu" onPointerDown={e => - setupMoveUpEvents( - this, - e, - returnFalse, - emptyFunction, - upEv => { - this.setToEditing(!this._isEditing); - upEv.stopPropagation(); - } - ) + setupMoveUpEvents(this, e, returnFalse, emptyFunction, upEv => { + this.setToEditing(!this._isEditing); + upEv.stopPropagation(); + }) } icon={} /> )} {Array.from(tagsList) - .filter(tag => tag.startsWith('#') || tag.startsWith('@')) - .map((tag, i) => ( + .filter(tag => (tag.startsWith('#') || tag.startsWith('@')) && !Doc.MyFilterHotKeys.some(key => key.toolType === tag)) + .map(tag => ( view.Document)} tag={tag} tagDoc={TagItem.findTagCollectionDoc(tag) ?? TagItem.createTagCollectionDoc(tag)} @@ -398,8 +392,8 @@ export class TagsView extends ObservableReactComponent { showRemoveUI={this.isEditing} /> ))} - {Array.from(facesList).map((tag, i) => ( - view.Document)} tag={tag} tagDoc={undefined} setToEditing={this.setToEditing} showRemoveUI={this.isEditing} /> + {Array.from(facesList).map(tag => ( + view.Document)} tag={tag} tagDoc={undefined} setToEditing={this.setToEditing} showRemoveUI={this.isEditing} /> ))}
{this.isEditing ? ( @@ -421,9 +415,9 @@ export class TagsView extends ObservableReactComponent { />
- {TagItem.AllTagCollectionDocs.filter(doc => StrCast(doc.title).startsWith('#') || StrCast(doc.title).startsWith('@')).map(doc => { - const tag = StrCast(doc.title); - return ( + {TagItem.AllTagCollectionDocs.map(doc => StrCast(doc.title)) + .filter(tag => (tag.startsWith('#') || tag.startsWith('@')) && !Doc.MyFilterHotKeys.some(key => key.toolType === tag)) + .map(tag => (
) : null} diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index cab7d51e4..bcb42111f 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -328,24 +328,22 @@ export class CollectionCardView extends CollectionSubView() { */ tagValue = (doc: Doc) => { - const keys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles); + const keys = Doc.MyFilterHotKeys; - const isTagActive = (buttonID: number) => { - return BoolCast(doc[StrCast(Doc.UserDoc()[keys[buttonID]])]); - }; + const isTagActive = (key: Doc) => BoolCast(key.active); let base = ''; let fraction = ''; - for (let i = 0; i < keys.length; i++) { - if (isTagActive(i)) { + keys.forEach(key => { + if (isTagActive(key)) { if (base === '') { - base = i.toString(); // First active tag becomes the base + base = StrCast(key.toolType); // First active tag becomes the base } else { - fraction += i.toString(); // Subsequent active tags become part of the fraction + fraction += StrCast(key.toolType); // Subsequent active tags become part of the fraction } } - } + }); // If no tag was active, return 0 by default if (base === '') { @@ -553,17 +551,16 @@ export class CollectionCardView extends CollectionSubView() { doc.chatIndex = index; break; case '1': { - const allHotKeys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles); + const allHotKeys = Doc.MyFilterHotKeys; let myTag = ''; if (tag) { for (let i = 0; i < allHotKeys.length; i++) { - if (tag.includes(allHotKeys[i])) { - myTag = StrCast(Doc.UserDoc()[allHotKeys[i]]); - break; - } else if (tag.includes(StrCast(Doc.UserDoc()[allHotKeys[i]]))) { - myTag = StrCast(Doc.UserDoc()[allHotKeys[i]]); + // bcz: CHECK THIS CODE OUT -- SOMETHING CHANGED + const keyTag = StrCast(allHotKeys[i].toolType); + if (tag.includes(keyTag)) { + myTag = keyTag; break; } } diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index d2cee39e2..f7a9689c9 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -270,27 +270,29 @@ ScriptingGlobals.add(function showFreeform(attr: 'hcenter' | 'vcenter' | 'grid' }); /** - * Applies a filter to the selected document (or, if the settins button is pressed, opens the filter panel) + * Applies a filter to the selected document (or, if the settings button is pressed, opens the filter panel) */ // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function handleTags(value: string, checkResult?: boolean) { const selected = DocumentView.SelectedDocs().lastElement(); + const isOptions = value === '-opts-'; - function isAttrFiltered(attr: string) { - return StrListCast(selected._childFilters).some(filter => filter.includes(attr)); - } + const isAttrFiltered = (attr: string) => + StrListCast(selected._childFilters) + .map(filter => filter.split(Doc.FilterSep)) + .some(([key, val]) => key === 'tags' && val === attr); if (checkResult) { - return value === 'opts' ? PropertiesView.Instance?.openFilters : isAttrFiltered(value); + return isOptions ? false : isAttrFiltered(value); } - if (value != 'opts') { - isAttrFiltered(value) ? Doc.setDocFilter(selected, value, true, 'remove') : Doc.setDocFilter(selected, value, true, 'match'); + if (!isOptions) { + isAttrFiltered(value) ? Doc.setDocFilter(selected, 'tags', value, 'remove') : Doc.setDocFilter(selected, 'tags', value, 'check'); } else { SnappingManager.PropertiesWidth < 5 && SnappingManager.SetPropertiesWidth(0); SnappingManager.SetPropertiesWidth(MainView.Instance.propertiesWidth() < 15 ? 250 : 0); PropertiesView.Instance?.CloseAll(); - PropertiesView.Instance.openFilters = true; + runInAction(() => (PropertiesView.Instance.openFilters = SnappingManager.PropertiesWidth > 5)); } return undefined; diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index f53a7d163..0e4288574 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -267,6 +267,8 @@ export class FontIconBox extends ViewBoxBaseComponent() { const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color) as string; const items = DocListCast(this.dataDoc.data); const multiDoc = this.Document; + const selectedItem = StrCast(items.find(itemDoc => ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, value: undefined, _readOnly_: true }).result)?.toolType ?? StrCast(multiDoc.toolType)); + console.log(selectedItem); return ( () { tooltip: StrCast(item.toolTip), val: StrCast(item.toolType), }))} - selectedVal={StrCast(items.find(itemDoc => ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, value: undefined, _readOnly_: true }).result)?.toolType ?? StrCast(multiDoc.toolType))} + selectedVal={selectedItem} setSelectedVal={(val: string | number) => { const itemDoc = items.find(item => item.toolType === val); itemDoc && ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, value: val, _readOnly_: false }); diff --git a/src/client/views/nodes/IconTagBox.tsx b/src/client/views/nodes/IconTagBox.tsx index 70992e28a..01dca0fbb 100644 --- a/src/client/views/nodes/IconTagBox.tsx +++ b/src/client/views/nodes/IconTagBox.tsx @@ -1,21 +1,21 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; -import { computed } from 'mobx'; +import { action, computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import React from 'react'; -import { emptyFunction, numberRange } from '../../../Utils'; -import { Doc, StrListCast } from '../../../fields/Doc'; +import { returnFalse, setupMoveUpEvents } from '../../../ClientUtils'; +import { emptyFunction } from '../../../Utils'; +import { Doc } from '../../../fields/Doc'; import { StrCast } from '../../../fields/Types'; import { SnappingManager } from '../../util/SnappingManager'; import { undoable } from '../../util/UndoManager'; import { MainView } from '../MainView'; import { ObservableReactComponent } from '../ObservableReactComponent'; import { PropertiesView } from '../PropertiesView'; +import { TagItem } from '../TagsView'; import { DocumentView } from './DocumentView'; import './IconTagBox.scss'; -import { TagItem } from '../TagsView'; -import { returnFalse, setupMoveUpEvents } from '../../../ClientUtils'; export interface IconTagProps { Views: DocumentView[]; @@ -30,48 +30,36 @@ export interface IconTagProps { export class IconTagBox extends ObservableReactComponent { constructor(props: IconTagProps) { super(props); + makeObservable(this); } - @computed get View() { - return this._props.Views.lastElement(); - } - @computed get currentScale() { - return this.View?.screenToLocalScale(); - } + @computed get View() { return this._props.Views.lastElement(); } // prettier-ignore + @computed get currentScale() { return this.View?.screenToLocalScale(); } // prettier-ignore /** - * Opens the filter panel in the properties menu + * Sets or removes the specified tag + * @param tag tag name (should begin with '#') + * @param state flag to add or remove the metadata */ - - openHotKeyMenu = () => { - SnappingManager.PropertiesWidth < 5 && SnappingManager.SetPropertiesWidth(0); - SnappingManager.SetPropertiesWidth(MainView.Instance.propertiesWidth() < 15 ? 250 : 0); - - PropertiesView.Instance.CloseAll(); - PropertiesView.Instance.openFilters = true; - }; - - /** - * @param buttonID - * @param doc - */ - setIconTag = undoable((icon: string, state: boolean) => { + setIconTag = undoable((tag: string, state: boolean) => { this._props.Views.forEach(view => { - state && TagItem.addTagToDoc(view.dataDoc, icon); - !state && TagItem.removeTagFromDoc(view.dataDoc, icon); - view.dataDoc[icon] = state; + state && TagItem.addTagToDoc(view.dataDoc, tag); + !state && TagItem.removeTagFromDoc(view.dataDoc, tag); }); }, 'toggle card tag'); /** - * Determines whether or not the given icon is active depending on the doc's data - * @param doc - * @param icon - * @returns + * Returns a renderable version of the button Doc that is colorized to indicate + * whether the doc has the associated tag set on it or not. + * @param doc doc to test + * @param key metadata icon button + * @returns an icon for the metdata button */ - getButtonIcon = (doc: Doc, icon: IconProp): JSX.Element => { - const isActive = TagItem.docHasTag(doc, icon.toString()); // doc[icon.toString()]; - const color = isActive ? '#4476f7' : '#323232'; + getButtonIcon = (doc: Doc, key: Doc): JSX.Element => { + const icon = StrCast(key.icon) as IconProp; + const tag = StrCast(key.toolType); + const isActive = TagItem.docHasTag(doc, tag); + const color = isActive ? '#4476f7' : '#323232'; // TODO should use theme colors return ; }; @@ -80,37 +68,26 @@ export class IconTagBox extends ObservableReactComponent { * Renders the buttons to customize sorting depending on which group the card belongs to and the amount of total groups */ render() { - const amButtons = StrListCast(Doc.UserDoc().myFilterHotKeyTitles).length + 1; - - const keys = StrListCast(Doc.UserDoc().myFilterHotKeyTitles); - - const iconMap = (buttonID: number) => { - return StrCast(Doc.UserDoc()[keys[buttonID]]) as IconProp; - }; - const buttons = numberRange(amButtons - 1) - .filter(i => this._props.IsEditing || this.View.Document[iconMap(i).toString()] || (DocumentView.Selected.length === 1 && this.View.IsSelected)) - .map(i => ( - Click to add/remove this card from the {iconMap(i).toString()} group}> + const buttons = Doc.MyFilterHotKeys + .map(key => ({ key, tag: StrCast(key.toolType) })) + .filter(({ tag }) => this._props.IsEditing || this.View.Document[tag] || (DocumentView.Selected.length === 1 && this.View.IsSelected)) + .map(({ key, tag }) => ( + Click to add/remove this card from the {tag} group}> - )); + )); // prettier-ignore + return !buttons.length ? null : ( -
+
{buttons}
); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 7abba7679..f6b7708b3 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -256,7 +256,13 @@ export class Doc extends RefField { public static set ActivePresentation(val) { Doc.ActiveDashboard && (Doc.ActiveDashboard.activePresentation = val) } // prettier-ignore public static get ActiveDashboard() { return DocCast(Doc.UserDoc().activeDashboard); } // prettier-ignore public static set ActiveDashboard(val: Opt) { Doc.UserDoc().activeDashboard = val; } // prettier-ignore - + public static get MyFilterHotKeys() { return DocListCast(DocCast(DocCast(Doc.UserDoc().myContextMenuBtns)?.Filter)?.data).filter(key => key.toolType !== "-opts-"); } // prettier-ignore + public static RemFromFilterHotKeys(doc: Doc) { + return Doc.RemoveDocFromList(DocCast(DocCast(Doc.UserDoc().myContextMenuBtns)?.Filter), 'data', doc); + } + public static AddToFilterHotKeys(doc: Doc) { + return Doc.AddDocToList(DocCast(DocCast(Doc.UserDoc().myContextMenuBtns)?.Filter), 'data', doc); + } public static IsInMyOverlay(doc: Doc) { return Doc.MyOverlayDocs.includes(doc); } // prettier-ignore public static AddToMyOverlay(doc: Doc) { return Doc.ActiveDashboard ? Doc.AddDocToList(Doc.ActiveDashboard, 'myOverlayDocs', doc) : Doc.AddDocToList(DocCast(Doc.UserDoc().myOverlayDocs), undefined, doc); } // prettier-ignore public static RemFromMyOverlay(doc: Doc) { return Doc.ActiveDashboard ? Doc.RemoveDocFromList(Doc.ActiveDashboard,'myOverlayDocs', doc) : Doc.RemoveDocFromList(DocCast(Doc.UserDoc().myOverlayDocs), undefined, doc); } // prettier-ignore -- cgit v1.2.3-70-g09d2 From 11bf7c3c04b875ab8c0003001df600675470dca7 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 20 Sep 2024 14:03:34 -0400 Subject: fixed filter dropdown to work properly with multiselect. --- package-lock.json | 8 ++++---- package.json | 2 +- src/client/documents/DocUtils.ts | 3 +++ src/client/util/CurrentUserUtils.ts | 10 +++++----- src/client/views/global/globalScripts.ts | 20 ++++++++++---------- src/client/views/nodes/FontIconBox/FontIconBox.tsx | 21 ++++++++++++--------- 6 files changed, 35 insertions(+), 29 deletions(-) (limited to 'src/client/util/CurrentUserUtils.ts') diff --git a/package-lock.json b/package-lock.json index 5e2e67839..fac1cc20b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -70,7 +70,7 @@ "body-parser": "^1.20.2", "bootstrap": "^5.3.2", "brotli": "^1.3.3", - "browndash-components": "^0.1.45", + "browndash-components": "^0.1.47", "browser-assert": "^1.2.1", "bson": "^6.2.0", "canvas": "^2.11.2", @@ -11553,9 +11553,9 @@ } }, "node_modules/browndash-components": { - "version": "0.1.45", - "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.45.tgz", - "integrity": "sha512-A2/3SikcA1kntY8jajwWJjnRGVRP9+DheaOMh9fAdgiQrdMZVMty+nUasbXk9HjyjkMfAUAkGvCR+SS28QL/zA==", + "version": "0.1.47", + "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.47.tgz", + "integrity": "sha512-562nWku81I1wccgEQbMU/30+RP/81sxsIGoPGLH7Otm9TdrHXWgW8yJS4tzBPXBF03Q2AX8DyQusi6T0LSc7Mw==", "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", diff --git a/package.json b/package.json index 967549197..7e521eb37 100644 --- a/package.json +++ b/package.json @@ -149,7 +149,7 @@ "body-parser": "^1.20.2", "bootstrap": "^5.3.2", "brotli": "^1.3.3", - "browndash-components": "^0.1.45", + "browndash-components": "^0.1.47", "browser-assert": "^1.2.1", "bson": "^6.2.0", "canvas": "^2.11.2", diff --git a/src/client/documents/DocUtils.ts b/src/client/documents/DocUtils.ts index 30b71a09b..4d105e372 100644 --- a/src/client/documents/DocUtils.ts +++ b/src/client/documents/DocUtils.ts @@ -241,7 +241,10 @@ export namespace DocUtils { Object.keys(scripts).forEach(key => { const script = scripts[key] as string; if (ScriptCast(doc[key])?.script.originalScript !== scripts[key] && script) { + const additionalItems: { [key: string]: unknown } = {}; + script.match(/_[a-zA-Z]*_/)?.forEach(match => (additionalItems[match] = 'any')); (key.startsWith('_') ? doc : Doc.GetProto(doc))[key] = ScriptField.MakeScript(script, { + ...additionalItems, this: Doc.name, dragData: Doc.DocDragDataName, value: 'any', diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 21df0fd3b..e72acf93f 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -688,14 +688,14 @@ pie title Minerals in my tap water static tagGroupTools(): 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 handleTags(this.toolType, _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 handleTags(this.toolType, _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 handleTags(this.toolType, _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 handleTags(this.toolType, _readOnly_);}'}}, + { 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_);}'}}, ]; // 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 handleTags(this.toolType, _readOnly_);}'}}, + { 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) ] } diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index f7a9689c9..588073568 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -270,24 +270,24 @@ ScriptingGlobals.add(function showFreeform(attr: 'hcenter' | 'vcenter' | 'grid' }); /** - * Applies a filter to the selected document (or, if the settings button is pressed, opens the filter panel) + * Applies (or removes) a filter to the selected document for the specified tag + * NOTE: this also opens the filter panel if the settings button is clicked (probably should be a different function) */ // eslint-disable-next-line prefer-arrow-callback -ScriptingGlobals.add(function handleTags(value: string, checkResult?: boolean) { +ScriptingGlobals.add(function setTagFilter(tag: string, added: boolean, checkResult?: boolean) { const selected = DocumentView.SelectedDocs().lastElement(); - const isOptions = value === '-opts-'; - - const isAttrFiltered = (attr: string) => - StrListCast(selected._childFilters) - .map(filter => filter.split(Doc.FilterSep)) - .some(([key, val]) => key === 'tags' && val === attr); + const isOptions = tag === '-opts-'; if (checkResult) { - return isOptions ? false : isAttrFiltered(value); + return isOptions + ? false + : StrListCast(selected._childFilters) // check all filters for one that filters tags:value where value is the tag's name + .map(filter => filter.split(Doc.FilterSep)) + .some(([key, val]) => key === 'tags' && val === tag); } if (!isOptions) { - isAttrFiltered(value) ? Doc.setDocFilter(selected, 'tags', value, 'remove') : Doc.setDocFilter(selected, 'tags', value, 'check'); + added ? Doc.setDocFilter(selected, 'tags', tag, 'check') : Doc.setDocFilter(selected, 'tags', tag, 'remove'); } else { SnappingManager.PropertiesWidth < 5 && SnappingManager.SetPropertiesWidth(0); SnappingManager.SetPropertiesWidth(MainView.Instance.propertiesWidth() < 15 ? 250 : 0); diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index 0e4288574..cb0c4d188 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -266,28 +266,31 @@ export class FontIconBox extends ViewBoxBaseComponent() { // Colors const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color) as string; const items = DocListCast(this.dataDoc.data); - const multiDoc = this.Document; - const selectedItem = StrCast(items.find(itemDoc => ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, value: undefined, _readOnly_: true }).result)?.toolType ?? StrCast(multiDoc.toolType)); - console.log(selectedItem); + const selectedItems = items.filter(itemDoc => ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, value: undefined, _readOnly_: true }).result).map(item => StrCast(item.toolType)); return ( script && !toggleStatus && setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => script.run({ this: multiDoc, value: undefined, _readOnly_: false }))} + multiSelect={true} + onPointerDown={e => script && !toggleStatus && setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => script.run({ this: this.Document, value: undefined, _readOnly_: false }))} isToggle={script ? true : false} toggleStatus={toggleStatus} //background={SnappingManager.userBackgroundColor} label={this.label} - items={DocListCast(this.dataDoc.data).map(item => ({ + items={items.map(item => ({ icon: , tooltip: StrCast(item.toolTip), val: StrCast(item.toolType), }))} - selectedVal={selectedItem} - setSelectedVal={(val: string | number) => { - const itemDoc = items.find(item => item.toolType === val); - itemDoc && ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, value: val, _readOnly_: false }); + selectedItems={selectedItems} + onSelectionChange={(val: (string | number) | (string | number)[], added: boolean) => { + // note: the multitoggle is telling us whether the selection was toggled on or off, but we ignore this since we know the state of all the buttons + // and control it through the selectedItems prop. Therefore, the callback script will have to re-determine the toggle information. + // it would be better to pas the 'added' flag to the callback script, but our script generator from currentUserUtils makes it hard to define + // arbitrary parameter variables (but it could be done as a special case or with additional effort when creating the sript) + const itemsChanged = items.filter(item => (val instanceof Array ? val.includes(item.toolType as string | number) : item.toolType === val)); + itemsChanged.forEach(itemDoc => ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, _added_: added, itemDoc, _readOnly_: false })); }} /> ); -- cgit v1.2.3-70-g09d2